Add dependencies needed for mesos containerizer

This commit is contained in:
Sashank Appireddy 2018-06-27 23:04:34 +00:00
parent ed0e3f0f43
commit ff8c1e80df
76 changed files with 188164 additions and 0 deletions

108
Godeps/Godeps.json generated
View File

@ -21,6 +21,26 @@
"Comment": "v0.3.2",
"Rev": "862b6557927a5c5c81e411c12aa6de7e566cbb7a"
},
{
"ImportPath": "github.com/Rican7/retry",
"Comment": "v0.1.0-9-g272ad12",
"Rev": "272ad122d6e5ce1be757544007cf8bcd1c9c9ab0"
},
{
"ImportPath": "github.com/Rican7/retry/backoff",
"Comment": "v0.1.0-9-g272ad12",
"Rev": "272ad122d6e5ce1be757544007cf8bcd1c9c9ab0"
},
{
"ImportPath": "github.com/Rican7/retry/jitter",
"Comment": "v0.1.0-9-g272ad12",
"Rev": "272ad122d6e5ce1be757544007cf8bcd1c9c9ab0"
},
{
"ImportPath": "github.com/Rican7/retry/strategy",
"Comment": "v0.1.0-9-g272ad12",
"Rev": "272ad122d6e5ce1be757544007cf8bcd1c9c9ab0"
},
{
"ImportPath": "github.com/SeanDolphin/bqschema",
"Rev": "f92a08f515e1bf718e995076a37c2f534b1deb08"
@ -394,11 +414,21 @@
"Comment": "v3",
"Rev": "c7fdd8b5cd55e87b4e1f4e372cdb1db61dd6c66f"
},
{
"ImportPath": "github.com/gogo/protobuf/gogoproto",
"Comment": "v0.4-3-gc0656edd",
"Rev": "c0656edd0d9eab7c66d1eb0c568f9039345796f7"
},
{
"ImportPath": "github.com/gogo/protobuf/proto",
"Comment": "v0.4-3-gc0656edd",
"Rev": "c0656edd0d9eab7c66d1eb0c568f9039345796f7"
},
{
"ImportPath": "github.com/gogo/protobuf/protoc-gen-gogo/descriptor",
"Comment": "v0.4-3-gc0656edd",
"Rev": "c0656edd0d9eab7c66d1eb0c568f9039345796f7"
},
{
"ImportPath": "github.com/gogo/protobuf/sortkeys",
"Comment": "v0.4-3-gc0656edd",
@ -479,6 +509,76 @@
"ImportPath": "github.com/matttproud/golang_protobuf_extensions/pbutil",
"Rev": "fc2b8d3a73c4867e51861bbdd5ae3c1f0869dd6a"
},
{
"ImportPath": "github.com/mesos/mesos-go/api/v1/lib",
"Comment": "mesos-1.4.x-33-g29de6ff",
"Rev": "29de6ff97b48c29cb5ac07029ed75186e5ba0eed"
},
{
"ImportPath": "github.com/mesos/mesos-go/api/v1/lib/agent",
"Comment": "mesos-1.4.x-33-g29de6ff",
"Rev": "29de6ff97b48c29cb5ac07029ed75186e5ba0eed"
},
{
"ImportPath": "github.com/mesos/mesos-go/api/v1/lib/agent/calls",
"Comment": "mesos-1.4.x-33-g29de6ff",
"Rev": "29de6ff97b48c29cb5ac07029ed75186e5ba0eed"
},
{
"ImportPath": "github.com/mesos/mesos-go/api/v1/lib/client",
"Comment": "mesos-1.4.x-33-g29de6ff",
"Rev": "29de6ff97b48c29cb5ac07029ed75186e5ba0eed"
},
{
"ImportPath": "github.com/mesos/mesos-go/api/v1/lib/debug",
"Comment": "mesos-1.4.x-33-g29de6ff",
"Rev": "29de6ff97b48c29cb5ac07029ed75186e5ba0eed"
},
{
"ImportPath": "github.com/mesos/mesos-go/api/v1/lib/encoding",
"Comment": "mesos-1.4.x-33-g29de6ff",
"Rev": "29de6ff97b48c29cb5ac07029ed75186e5ba0eed"
},
{
"ImportPath": "github.com/mesos/mesos-go/api/v1/lib/encoding/codecs",
"Comment": "mesos-1.4.x-33-g29de6ff",
"Rev": "29de6ff97b48c29cb5ac07029ed75186e5ba0eed"
},
{
"ImportPath": "github.com/mesos/mesos-go/api/v1/lib/encoding/framing",
"Comment": "mesos-1.4.x-33-g29de6ff",
"Rev": "29de6ff97b48c29cb5ac07029ed75186e5ba0eed"
},
{
"ImportPath": "github.com/mesos/mesos-go/api/v1/lib/encoding/json",
"Comment": "mesos-1.4.x-33-g29de6ff",
"Rev": "29de6ff97b48c29cb5ac07029ed75186e5ba0eed"
},
{
"ImportPath": "github.com/mesos/mesos-go/api/v1/lib/encoding/proto",
"Comment": "mesos-1.4.x-33-g29de6ff",
"Rev": "29de6ff97b48c29cb5ac07029ed75186e5ba0eed"
},
{
"ImportPath": "github.com/mesos/mesos-go/api/v1/lib/httpcli",
"Comment": "mesos-1.4.x-33-g29de6ff",
"Rev": "29de6ff97b48c29cb5ac07029ed75186e5ba0eed"
},
{
"ImportPath": "github.com/mesos/mesos-go/api/v1/lib/httpcli/apierrors",
"Comment": "mesos-1.4.x-33-g29de6ff",
"Rev": "29de6ff97b48c29cb5ac07029ed75186e5ba0eed"
},
{
"ImportPath": "github.com/mesos/mesos-go/api/v1/lib/recordio",
"Comment": "mesos-1.4.x-33-g29de6ff",
"Rev": "29de6ff97b48c29cb5ac07029ed75186e5ba0eed"
},
{
"ImportPath": "github.com/mesos/mesos-go/api/v1/lib/roles",
"Comment": "mesos-1.4.x-33-g29de6ff",
"Rev": "29de6ff97b48c29cb5ac07029ed75186e5ba0eed"
},
{
"ImportPath": "github.com/mindprince/gonvml",
"Rev": "fee913ce8fb235edf54739d259ca0ecc226c7b8a"
@ -616,6 +716,14 @@
"Comment": "v1.0.0",
"Rev": "792786c7400a136282c1664665ae0a8db921c6c2"
},
{
"ImportPath": "github.com/pquerna/ffjson/fflib/v1",
"Rev": "d49c2bc1aa135aad0c6f4fc2056623ec78f5d5ac"
},
{
"ImportPath": "github.com/pquerna/ffjson/fflib/v1/internal",
"Rev": "d49c2bc1aa135aad0c6f4fc2056623ec78f5d5ac"
},
{
"ImportPath": "github.com/prometheus/client_golang/prometheus",
"Comment": "v0.8.0-62-g08fd2e1",

39
vendor/github.com/Rican7/retry/.travis.yml generated vendored Normal file
View File

@ -0,0 +1,39 @@
language: go
go:
- 1.6
- tip
sudo: false
before_install:
# Install tools necessary to report code-coverage to Coveralls.io
- go get github.com/mattn/goveralls
# Export some environment variables
- export GO_TEST_COVERAGE_FILE_NAME='coverage.out'
install:
# Get all imported packages
- make install-deps install-deps-dev
# Basic build errors
- make build
script:
# Lint
- make format-lint
- make import-lint
- make copyright-lint
# Run tests
- make test-with-coverage-profile
after_success:
# Report our code-coverage to Coveralls.io
- goveralls -service=travis-ci -coverprofile="${GO_TEST_COVERAGE_FILE_NAME}"
matrix:
allow_failures:
- go: tip
fast_finish: true

19
vendor/github.com/Rican7/retry/LICENSE generated vendored Normal file
View File

@ -0,0 +1,19 @@
Copyright (C) 2016 Trevor N. Suarez (Rican7)
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.

83
vendor/github.com/Rican7/retry/Makefile generated vendored Normal file
View File

@ -0,0 +1,83 @@
# Define some VCS context
PARENT_BRANCH ?= master
# Set the mode for code-coverage
GO_TEST_COVERAGE_MODE ?= count
GO_TEST_COVERAGE_FILE_NAME ?= coverage.out
# Set flags for `gofmt`
GOFMT_FLAGS ?= -s
# Set a default `min_confidence` value for `golint`
GOLINT_MIN_CONFIDENCE ?= 0.3
all: install-deps build install
clean:
go clean -i -x ./...
build:
go build -v ./...
install:
go install ./...
install-deps:
go get -d -t ./...
install-deps-dev: install-deps
go get github.com/golang/lint/golint
go get golang.org/x/tools/cmd/goimports
update-deps:
go get -d -t -u ./...
update-deps-dev: update-deps
go get -u github.com/golang/lint/golint
go get -u golang.org/x/tools/cmd/goimports
test:
go test -v ./...
test-with-coverage:
go test -cover ./...
test-with-coverage-formatted:
go test -cover ./... | column -t | sort -r
test-with-coverage-profile:
echo "mode: ${GO_TEST_COVERAGE_MODE}" > ${GO_TEST_COVERAGE_FILE_NAME}
for package in $$(go list ./...); do \
go test -covermode ${GO_TEST_COVERAGE_MODE} -coverprofile "coverage_$${package##*/}.out" "$${package}"; \
sed '1d' "coverage_$${package##*/}.out" >> ${GO_TEST_COVERAGE_FILE_NAME}; \
done
format-lint:
errors=$$(gofmt -l ${GOFMT_FLAGS} .); if [ "$${errors}" != "" ]; then echo "$${errors}"; exit 1; fi
import-lint:
errors=$$(goimports -l .); if [ "$${errors}" != "" ]; then echo "$${errors}"; exit 1; fi
style-lint:
errors=$$(golint -min_confidence=${GOLINT_MIN_CONFIDENCE} ./...); if [ "$${errors}" != "" ]; then echo "$${errors}"; exit 1; fi
copyright-lint:
@old_dates=$$(git diff --diff-filter=ACMRTUXB --name-only "${PARENT_BRANCH}" | xargs grep -E '[Cc]opyright(\s+)[©Cc]?(\s+)[0-9]{4}' | grep -E -v "[Cc]opyright(\s+)[©Cc]?(\s+)$$(date '+%Y')"); if [ "$${old_dates}" != "" ]; then printf "The following files contain outdated copyrights:\n$${old_dates}\n\nThis can be fixed with 'make copyright-fix'\n"; exit 1; fi
lint: install-deps-dev format-lint import-lint style-lint copyright-lint
format-fix:
gofmt -w ${GOFMT_FLAGS} .
import-fix:
goimports -w .
copyright-fix:
@git diff --diff-filter=ACMRTUXB --name-only "${PARENT_BRANCH}" | xargs -I '_FILENAME' -- sh -c 'sed -i.bak "s/\([Cc]opyright\([[:space:]][©Cc]\{0,1\}[[:space:]]*\)\)[0-9]\{4\}/\1"$$(date '+%Y')"/g" _FILENAME && rm _FILENAME.bak'
vet:
go vet ./...
.PHONY: all clean build install install-deps install-deps-dev update-deps update-deps-dev test test-with-coverage test-with-coverage-formatted test-with-coverage-profile format-lint import-lint style-lint copyright-lint lint format-fix import-fix copyright-fix vet

101
vendor/github.com/Rican7/retry/README.md generated vendored Normal file
View File

@ -0,0 +1,101 @@
# retry
[![Build Status](https://travis-ci.org/Rican7/retry.svg?branch=master)](https://travis-ci.org/Rican7/retry)
[![Coverage Status](https://coveralls.io/repos/github/Rican7/retry/badge.svg)](https://coveralls.io/github/Rican7/retry)
[![Go Report Card](https://goreportcard.com/badge/Rican7/retry)](http://goreportcard.com/report/Rican7/retry)
[![GoDoc](https://godoc.org/github.com/Rican7/retry?status.png)](https://godoc.org/github.com/Rican7/retry)
[![Latest Stable Version](https://img.shields.io/github/release/Rican7/retry.svg?style=flat)](https://github.com/Rican7/retry/releases)
A simple, stateless, functional mechanism to perform actions repetitively until successful.
## Project Status
This project is currently in "pre-release". While the code is heavily tested, the API may change.
Vendor (commit or lock) this dependency if you plan on using it.
## Install
`go get github.com/Rican7/retry`
## Examples
### Basic
```go
retry.Retry(func(attempt uint) error {
return nil // Do something that may or may not cause an error
})
```
### File Open
```go
const logFilePath = "/var/log/myapp.log"
var logFile *os.File
err := retry.Retry(func(attempt uint) error {
var err error
logFile, err = os.Open(logFilePath)
return err
})
if nil != err {
log.Fatalf("Unable to open file %q with error %q", logFilePath, err)
}
logFile.Chdir() // Do something with the file
```
### HTTP request with strategies and backoff
```go
var response *http.Response
action := func(attempt uint) error {
var err error
response, err = http.Get("https://api.github.com/repos/Rican7/retry")
if nil == err && nil != response && response.StatusCode > 200 {
err = fmt.Errorf("failed to fetch (attempt #%d) with status code: %d", attempt, response.StatusCode)
}
return err
}
err := retry.Retry(
action,
strategy.Limit(5),
strategy.Backoff(backoff.Fibonacci(10*time.Millisecond)),
)
if nil != err {
log.Fatalf("Failed to fetch repository with error %q", err)
}
```
### Retry with backoff jitter
```go
action := func(attempt uint) error {
return errors.New("something happened")
}
seed := time.Now().UnixNano()
random := rand.New(rand.NewSource(seed))
retry.Retry(
action,
strategy.Limit(5),
strategy.BackoffWithJitter(
backoff.BinaryExponential(10*time.Millisecond),
jitter.Deviation(random, 0.5),
),
)
```

67
vendor/github.com/Rican7/retry/backoff/backoff.go generated vendored Normal file
View File

@ -0,0 +1,67 @@
// Package backoff provides stateless methods of calculating durations based on
// a number of attempts made.
//
// Copyright © 2016 Trevor N. Suarez (Rican7)
package backoff
import (
"math"
"time"
)
// Algorithm defines a function that calculates a time.Duration based on
// the given retry attempt number.
type Algorithm func(attempt uint) time.Duration
// Incremental creates a Algorithm that increments the initial duration
// by the given increment for each attempt.
func Incremental(initial, increment time.Duration) Algorithm {
return func(attempt uint) time.Duration {
return initial + (increment * time.Duration(attempt))
}
}
// Linear creates a Algorithm that linearly multiplies the factor
// duration by the attempt number for each attempt.
func Linear(factor time.Duration) Algorithm {
return func(attempt uint) time.Duration {
return (factor * time.Duration(attempt))
}
}
// Exponential creates a Algorithm that multiplies the factor duration by
// an exponentially increasing factor for each attempt, where the factor is
// calculated as the given base raised to the attempt number.
func Exponential(factor time.Duration, base float64) Algorithm {
return func(attempt uint) time.Duration {
return (factor * time.Duration(math.Pow(base, float64(attempt))))
}
}
// BinaryExponential creates a Algorithm that multiplies the factor
// duration by an exponentially increasing factor for each attempt, where the
// factor is calculated as `2` raised to the attempt number (2^attempt).
func BinaryExponential(factor time.Duration) Algorithm {
return Exponential(factor, 2)
}
// Fibonacci creates a Algorithm that multiplies the factor duration by
// an increasing factor for each attempt, where the factor is the Nth number in
// the Fibonacci sequence.
func Fibonacci(factor time.Duration) Algorithm {
return func(attempt uint) time.Duration {
return (factor * time.Duration(fibonacciNumber(attempt)))
}
}
// fibonacciNumber calculates the Fibonacci sequence number for the given
// sequence position.
func fibonacciNumber(n uint) uint {
if 0 == n {
return 0
} else if 1 == n {
return 1
} else {
return fibonacciNumber(n-1) + fibonacciNumber(n-2)
}
}

89
vendor/github.com/Rican7/retry/jitter/jitter.go generated vendored Normal file
View File

@ -0,0 +1,89 @@
// Package jitter provides methods of transforming durations.
//
// Copyright © 2016 Trevor N. Suarez (Rican7)
package jitter
import (
"math"
"math/rand"
"time"
)
// Transformation defines a function that calculates a time.Duration based on
// the given duration.
type Transformation func(duration time.Duration) time.Duration
// Full creates a Transformation that transforms a duration into a result
// duration in [0, n) randomly, where n is the given duration.
//
// The given generator is what is used to determine the random transformation.
// If a nil generator is passed, a default one will be provided.
//
// Inspired by https://www.awsarchitectureblog.com/2015/03/backoff.html
func Full(generator *rand.Rand) Transformation {
random := fallbackNewRandom(generator)
return func(duration time.Duration) time.Duration {
return time.Duration(random.Int63n(int64(duration)))
}
}
// Equal creates a Transformation that transforms a duration into a result
// duration in [n/2, n) randomly, where n is the given duration.
//
// The given generator is what is used to determine the random transformation.
// If a nil generator is passed, a default one will be provided.
//
// Inspired by https://www.awsarchitectureblog.com/2015/03/backoff.html
func Equal(generator *rand.Rand) Transformation {
random := fallbackNewRandom(generator)
return func(duration time.Duration) time.Duration {
return (duration / 2) + time.Duration(random.Int63n(int64(duration))/2)
}
}
// Deviation creates a Transformation that transforms a duration into a result
// duration that deviates from the input randomly by a given factor.
//
// The given generator is what is used to determine the random transformation.
// If a nil generator is passed, a default one will be provided.
//
// Inspired by https://developers.google.com/api-client-library/java/google-http-java-client/backoff
func Deviation(generator *rand.Rand, factor float64) Transformation {
random := fallbackNewRandom(generator)
return func(duration time.Duration) time.Duration {
min := int64(math.Floor(float64(duration) * (1 - factor)))
max := int64(math.Ceil(float64(duration) * (1 + factor)))
return time.Duration(random.Int63n(max-min) + min)
}
}
// NormalDistribution creates a Transformation that transforms a duration into a
// result duration based on a normal distribution of the input and the given
// standard deviation.
//
// The given generator is what is used to determine the random transformation.
// If a nil generator is passed, a default one will be provided.
func NormalDistribution(generator *rand.Rand, standardDeviation float64) Transformation {
random := fallbackNewRandom(generator)
return func(duration time.Duration) time.Duration {
return time.Duration(random.NormFloat64()*standardDeviation + float64(duration))
}
}
// fallbackNewRandom returns the passed in random instance if it's not nil,
// and otherwise returns a new random instance seeded with the current time.
func fallbackNewRandom(random *rand.Rand) *rand.Rand {
// Return the passed in value if it's already not null
if nil != random {
return random
}
seed := time.Now().UnixNano()
return rand.New(rand.NewSource(seed))
}

36
vendor/github.com/Rican7/retry/retry.go generated vendored Normal file
View File

@ -0,0 +1,36 @@
// Package retry provides a simple, stateless, functional mechanism to perform
// actions repetitively until successful.
//
// Copyright © 2016 Trevor N. Suarez (Rican7)
package retry
import "github.com/Rican7/retry/strategy"
// Action defines a callable function that package retry can handle.
type Action func(attempt uint) error
// Retry takes an action and performs it, repetitively, until successful.
//
// Optionally, strategies may be passed that assess whether or not an attempt
// should be made.
func Retry(action Action, strategies ...strategy.Strategy) error {
var err error
for attempt := uint(0); (0 == attempt || nil != err) && shouldAttempt(attempt, strategies...); attempt++ {
err = action(attempt)
}
return err
}
// shouldAttempt evaluates the provided strategies with the given attempt to
// determine if the Retry loop should make another attempt.
func shouldAttempt(attempt uint, strategies ...strategy.Strategy) bool {
shouldAttempt := true
for i := 0; shouldAttempt && i < len(strategies); i++ {
shouldAttempt = shouldAttempt && strategies[i](attempt)
}
return shouldAttempt
}

85
vendor/github.com/Rican7/retry/strategy/strategy.go generated vendored Normal file
View File

@ -0,0 +1,85 @@
// Package strategy provides a way to change the way that retry is performed.
//
// Copyright © 2016 Trevor N. Suarez (Rican7)
package strategy
import (
"time"
"github.com/Rican7/retry/backoff"
"github.com/Rican7/retry/jitter"
)
// Strategy defines a function that Retry calls before every successive attempt
// to determine whether it should make the next attempt or not. Returning `true`
// allows for the next attempt to be made. Returning `false` halts the retrying
// process and returns the last error returned by the called Action.
//
// The strategy will be passed an "attempt" number on each successive retry
// iteration, starting with a `0` value before the first attempt is actually
// made. This allows for a pre-action delay, etc.
type Strategy func(attempt uint) bool
// Limit creates a Strategy that limits the number of attempts that Retry will
// make.
func Limit(attemptLimit uint) Strategy {
return func(attempt uint) bool {
return (attempt <= attemptLimit)
}
}
// Delay creates a Strategy that waits the given duration before the first
// attempt is made.
func Delay(duration time.Duration) Strategy {
return func(attempt uint) bool {
if 0 == attempt {
time.Sleep(duration)
}
return true
}
}
// Wait creates a Strategy that waits the given durations for each attempt after
// the first. If the number of attempts is greater than the number of durations
// provided, then the strategy uses the last duration provided.
func Wait(durations ...time.Duration) Strategy {
return func(attempt uint) bool {
if 0 < attempt && 0 < len(durations) {
durationIndex := int(attempt - 1)
if len(durations) <= durationIndex {
durationIndex = len(durations) - 1
}
time.Sleep(durations[durationIndex])
}
return true
}
}
// Backoff creates a Strategy that waits before each attempt, with a duration as
// defined by the given backoff.Algorithm.
func Backoff(algorithm backoff.Algorithm) Strategy {
return BackoffWithJitter(algorithm, noJitter())
}
// BackoffWithJitter creates a Strategy that waits before each attempt, with a
// duration as defined by the given backoff.Algorithm and jitter.Transformation.
func BackoffWithJitter(algorithm backoff.Algorithm, transformation jitter.Transformation) Strategy {
return func(attempt uint) bool {
if 0 < attempt {
time.Sleep(transformation(algorithm(attempt)))
}
return true
}
}
// noJitter creates a jitter.Transformation that simply returns the input.
func noJitter() jitter.Transformation {
return func(duration time.Duration) time.Duration {
return duration
}
}

37
vendor/github.com/gogo/protobuf/gogoproto/Makefile generated vendored Normal file
View File

@ -0,0 +1,37 @@
# Protocol Buffers for Go with Gadgets
#
# Copyright (c) 2013, The GoGo Authors. All rights reserved.
# http://github.com/gogo/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.
#
# 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.
regenerate:
go install github.com/gogo/protobuf/protoc-gen-gogo
protoc --gogo_out=Mgoogle/protobuf/descriptor.proto=github.com/gogo/protobuf/protoc-gen-gogo/descriptor:. --proto_path=../../../../:../protobuf/:. *.proto
restore:
cp gogo.pb.golden gogo.pb.go
preserve:
cp gogo.pb.go gogo.pb.golden

169
vendor/github.com/gogo/protobuf/gogoproto/doc.go generated vendored Normal file
View File

@ -0,0 +1,169 @@
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2013, The GoGo Authors. All rights reserved.
// http://github.com/gogo/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.
//
// 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 gogoproto provides extensions for protocol buffers to achieve:
- fast marshalling and unmarshalling.
- peace of mind by optionally generating test and benchmark code.
- more canonical Go structures.
- less typing by optionally generating extra helper code.
- goprotobuf compatibility
More Canonical Go Structures
A lot of time working with a goprotobuf struct will lead you to a place where you create another struct that is easier to work with and then have a function to copy the values between the two structs.
You might also find that basic structs that started their life as part of an API need to be sent over the wire. With gob, you could just send it. With goprotobuf, you need to make a parallel struct.
Gogoprotobuf tries to fix these problems with the nullable, embed, customtype and customname field extensions.
- nullable, if false, a field is generated without a pointer (see warning below).
- embed, if true, the field is generated as an embedded field.
- customtype, It works with the Marshal and Unmarshal methods, to allow you to have your own types in your struct, but marshal to bytes. For example, custom.Uuid or custom.Fixed128
- customname (beta), Changes the generated fieldname. This is especially useful when generated methods conflict with fieldnames.
- casttype (beta), Changes the generated fieldtype. All generated code assumes that this type is castable to the protocol buffer field type. It does not work for structs or enums.
- castkey (beta), Changes the generated fieldtype for a map key. All generated code assumes that this type is castable to the protocol buffer field type. Only supported on maps.
- castvalue (beta), Changes the generated fieldtype for a map value. All generated code assumes that this type is castable to the protocol buffer field type. Only supported on maps.
Warning about nullable: According to the Protocol Buffer specification, you should be able to tell whether a field is set or unset. With the option nullable=false this feature is lost, since your non-nullable fields will always be set. It can be seen as a layer on top of Protocol Buffers, where before and after marshalling all non-nullable fields are set and they cannot be unset.
Let us look at:
github.com/gogo/protobuf/test/example/example.proto
for a quicker overview.
The following message:
package test;
import "github.com/gogo/protobuf/gogoproto/gogo.proto";
message A {
optional string Description = 1 [(gogoproto.nullable) = false];
optional int64 Number = 2 [(gogoproto.nullable) = false];
optional bytes Id = 3 [(gogoproto.customtype) = "github.com/gogo/protobuf/test/custom.Uuid", (gogoproto.nullable) = false];
}
Will generate a go struct which looks a lot like this:
type A struct {
Description string
Number int64
Id github_com_gogo_protobuf_test_custom.Uuid
}
You will see there are no pointers, since all fields are non-nullable.
You will also see a custom type which marshals to a string.
Be warned it is your responsibility to test your custom types thoroughly.
You should think of every possible empty and nil case for your marshaling, unmarshaling and size methods.
Next we will embed the message A in message B.
message B {
optional A A = 1 [(gogoproto.nullable) = false, (gogoproto.embed) = true];
repeated bytes G = 2 [(gogoproto.customtype) = "github.com/gogo/protobuf/test/custom.Uint128", (gogoproto.nullable) = false];
}
See below that A is embedded in B.
type B struct {
A
G []github_com_gogo_protobuf_test_custom.Uint128
}
Also see the repeated custom type.
type Uint128 [2]uint64
Next we will create a custom name for one of our fields.
message C {
optional int64 size = 1 [(gogoproto.customname) = "MySize"];
}
See below that the field's name is MySize and not Size.
type C struct {
MySize *int64
}
The is useful when having a protocol buffer message with a field name which conflicts with a generated method.
As an example, having a field name size and using the sizer plugin to generate a Size method will cause a go compiler error.
Using customname you can fix this error without changing the field name.
This is typically useful when working with a protocol buffer that was designed before these methods and/or the go language were avialable.
Gogoprotobuf also has some more subtle changes, these could be changed back:
- the generated package name for imports do not have the extra /filename.pb,
but are actually the imports specified in the .proto file.
Gogoprotobuf also has lost some features which should be brought back with time:
- Marshalling and unmarshalling with reflect and without the unsafe package,
this requires work in pointer_reflect.go
Why does nullable break protocol buffer specifications:
The protocol buffer specification states, somewhere, that you should be able to tell whether a
field is set or unset. With the option nullable=false this feature is lost,
since your non-nullable fields will always be set. It can be seen as a layer on top of
protocol buffers, where before and after marshalling all non-nullable fields are set
and they cannot be unset.
Goprotobuf Compatibility:
Gogoprotobuf is compatible with Goprotobuf, because it is compatible with protocol buffers.
Gogoprotobuf generates the same code as goprotobuf if no extensions are used.
The enumprefix, getters and stringer extensions can be used to remove some of the unnecessary code generated by goprotobuf:
- gogoproto_import, if false, the generated code imports github.com/golang/protobuf/proto instead of github.com/gogo/protobuf/proto.
- goproto_enum_prefix, if false, generates the enum constant names without the messagetype prefix
- goproto_enum_stringer (experimental), if false, the enum is generated without the default string method, this is useful for rather using enum_stringer, or allowing you to write your own string method.
- goproto_getters, if false, the message is generated without get methods, this is useful when you would rather want to use face
- goproto_stringer, if false, the message is generated without the default string method, this is useful for rather using stringer, or allowing you to write your own string method.
- goproto_extensions_map (beta), if false, the extensions field is generated as type []byte instead of type map[int32]proto.Extension
- goproto_unrecognized (beta), if false, XXX_unrecognized field is not generated. This is useful in conjunction with gogoproto.nullable=false, to generate structures completely devoid of pointers and reduce GC pressure at the cost of losing information about unrecognized fields.
- goproto_registration (beta), if true, the generated files will register all messages and types against both gogo/protobuf and golang/protobuf. This is necessary when using third-party packages which read registrations from golang/protobuf (such as the grpc-gateway).
Less Typing and Peace of Mind is explained in their specific plugin folders godoc:
- github.com/gogo/protobuf/plugin/<extension_name>
If you do not use any of these extension the code that is generated
will be the same as if goprotobuf has generated it.
The most complete way to see examples is to look at
github.com/gogo/protobuf/test/thetest.proto
Gogoprototest is a seperate project,
because we want to keep gogoprotobuf independant of goprotobuf,
but we still want to test it thoroughly.
*/
package gogoproto

804
vendor/github.com/gogo/protobuf/gogoproto/gogo.pb.go generated vendored Normal file
View File

@ -0,0 +1,804 @@
// Code generated by protoc-gen-gogo.
// source: gogo.proto
// DO NOT EDIT!
/*
Package gogoproto is a generated protocol buffer package.
It is generated from these files:
gogo.proto
It has these top-level messages:
*/
package gogoproto
import proto "github.com/gogo/protobuf/proto"
import fmt "fmt"
import math "math"
import google_protobuf "github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
// 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.GoGoProtoPackageIsVersion2 // please upgrade the proto package
var E_GoprotoEnumPrefix = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.EnumOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 62001,
Name: "gogoproto.goproto_enum_prefix",
Tag: "varint,62001,opt,name=goproto_enum_prefix,json=goprotoEnumPrefix",
Filename: "gogo.proto",
}
var E_GoprotoEnumStringer = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.EnumOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 62021,
Name: "gogoproto.goproto_enum_stringer",
Tag: "varint,62021,opt,name=goproto_enum_stringer,json=goprotoEnumStringer",
Filename: "gogo.proto",
}
var E_EnumStringer = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.EnumOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 62022,
Name: "gogoproto.enum_stringer",
Tag: "varint,62022,opt,name=enum_stringer,json=enumStringer",
Filename: "gogo.proto",
}
var E_EnumCustomname = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.EnumOptions)(nil),
ExtensionType: (*string)(nil),
Field: 62023,
Name: "gogoproto.enum_customname",
Tag: "bytes,62023,opt,name=enum_customname,json=enumCustomname",
Filename: "gogo.proto",
}
var E_Enumdecl = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.EnumOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 62024,
Name: "gogoproto.enumdecl",
Tag: "varint,62024,opt,name=enumdecl",
Filename: "gogo.proto",
}
var E_EnumvalueCustomname = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.EnumValueOptions)(nil),
ExtensionType: (*string)(nil),
Field: 66001,
Name: "gogoproto.enumvalue_customname",
Tag: "bytes,66001,opt,name=enumvalue_customname,json=enumvalueCustomname",
Filename: "gogo.proto",
}
var E_GoprotoGettersAll = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FileOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 63001,
Name: "gogoproto.goproto_getters_all",
Tag: "varint,63001,opt,name=goproto_getters_all,json=goprotoGettersAll",
Filename: "gogo.proto",
}
var E_GoprotoEnumPrefixAll = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FileOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 63002,
Name: "gogoproto.goproto_enum_prefix_all",
Tag: "varint,63002,opt,name=goproto_enum_prefix_all,json=goprotoEnumPrefixAll",
Filename: "gogo.proto",
}
var E_GoprotoStringerAll = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FileOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 63003,
Name: "gogoproto.goproto_stringer_all",
Tag: "varint,63003,opt,name=goproto_stringer_all,json=goprotoStringerAll",
Filename: "gogo.proto",
}
var E_VerboseEqualAll = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FileOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 63004,
Name: "gogoproto.verbose_equal_all",
Tag: "varint,63004,opt,name=verbose_equal_all,json=verboseEqualAll",
Filename: "gogo.proto",
}
var E_FaceAll = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FileOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 63005,
Name: "gogoproto.face_all",
Tag: "varint,63005,opt,name=face_all,json=faceAll",
Filename: "gogo.proto",
}
var E_GostringAll = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FileOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 63006,
Name: "gogoproto.gostring_all",
Tag: "varint,63006,opt,name=gostring_all,json=gostringAll",
Filename: "gogo.proto",
}
var E_PopulateAll = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FileOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 63007,
Name: "gogoproto.populate_all",
Tag: "varint,63007,opt,name=populate_all,json=populateAll",
Filename: "gogo.proto",
}
var E_StringerAll = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FileOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 63008,
Name: "gogoproto.stringer_all",
Tag: "varint,63008,opt,name=stringer_all,json=stringerAll",
Filename: "gogo.proto",
}
var E_OnlyoneAll = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FileOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 63009,
Name: "gogoproto.onlyone_all",
Tag: "varint,63009,opt,name=onlyone_all,json=onlyoneAll",
Filename: "gogo.proto",
}
var E_EqualAll = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FileOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 63013,
Name: "gogoproto.equal_all",
Tag: "varint,63013,opt,name=equal_all,json=equalAll",
Filename: "gogo.proto",
}
var E_DescriptionAll = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FileOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 63014,
Name: "gogoproto.description_all",
Tag: "varint,63014,opt,name=description_all,json=descriptionAll",
Filename: "gogo.proto",
}
var E_TestgenAll = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FileOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 63015,
Name: "gogoproto.testgen_all",
Tag: "varint,63015,opt,name=testgen_all,json=testgenAll",
Filename: "gogo.proto",
}
var E_BenchgenAll = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FileOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 63016,
Name: "gogoproto.benchgen_all",
Tag: "varint,63016,opt,name=benchgen_all,json=benchgenAll",
Filename: "gogo.proto",
}
var E_MarshalerAll = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FileOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 63017,
Name: "gogoproto.marshaler_all",
Tag: "varint,63017,opt,name=marshaler_all,json=marshalerAll",
Filename: "gogo.proto",
}
var E_UnmarshalerAll = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FileOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 63018,
Name: "gogoproto.unmarshaler_all",
Tag: "varint,63018,opt,name=unmarshaler_all,json=unmarshalerAll",
Filename: "gogo.proto",
}
var E_StableMarshalerAll = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FileOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 63019,
Name: "gogoproto.stable_marshaler_all",
Tag: "varint,63019,opt,name=stable_marshaler_all,json=stableMarshalerAll",
Filename: "gogo.proto",
}
var E_SizerAll = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FileOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 63020,
Name: "gogoproto.sizer_all",
Tag: "varint,63020,opt,name=sizer_all,json=sizerAll",
Filename: "gogo.proto",
}
var E_GoprotoEnumStringerAll = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FileOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 63021,
Name: "gogoproto.goproto_enum_stringer_all",
Tag: "varint,63021,opt,name=goproto_enum_stringer_all,json=goprotoEnumStringerAll",
Filename: "gogo.proto",
}
var E_EnumStringerAll = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FileOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 63022,
Name: "gogoproto.enum_stringer_all",
Tag: "varint,63022,opt,name=enum_stringer_all,json=enumStringerAll",
Filename: "gogo.proto",
}
var E_UnsafeMarshalerAll = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FileOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 63023,
Name: "gogoproto.unsafe_marshaler_all",
Tag: "varint,63023,opt,name=unsafe_marshaler_all,json=unsafeMarshalerAll",
Filename: "gogo.proto",
}
var E_UnsafeUnmarshalerAll = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FileOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 63024,
Name: "gogoproto.unsafe_unmarshaler_all",
Tag: "varint,63024,opt,name=unsafe_unmarshaler_all,json=unsafeUnmarshalerAll",
Filename: "gogo.proto",
}
var E_GoprotoExtensionsMapAll = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FileOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 63025,
Name: "gogoproto.goproto_extensions_map_all",
Tag: "varint,63025,opt,name=goproto_extensions_map_all,json=goprotoExtensionsMapAll",
Filename: "gogo.proto",
}
var E_GoprotoUnrecognizedAll = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FileOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 63026,
Name: "gogoproto.goproto_unrecognized_all",
Tag: "varint,63026,opt,name=goproto_unrecognized_all,json=goprotoUnrecognizedAll",
Filename: "gogo.proto",
}
var E_GogoprotoImport = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FileOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 63027,
Name: "gogoproto.gogoproto_import",
Tag: "varint,63027,opt,name=gogoproto_import,json=gogoprotoImport",
Filename: "gogo.proto",
}
var E_ProtosizerAll = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FileOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 63028,
Name: "gogoproto.protosizer_all",
Tag: "varint,63028,opt,name=protosizer_all,json=protosizerAll",
Filename: "gogo.proto",
}
var E_CompareAll = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FileOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 63029,
Name: "gogoproto.compare_all",
Tag: "varint,63029,opt,name=compare_all,json=compareAll",
Filename: "gogo.proto",
}
var E_TypedeclAll = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FileOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 63030,
Name: "gogoproto.typedecl_all",
Tag: "varint,63030,opt,name=typedecl_all,json=typedeclAll",
Filename: "gogo.proto",
}
var E_EnumdeclAll = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FileOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 63031,
Name: "gogoproto.enumdecl_all",
Tag: "varint,63031,opt,name=enumdecl_all,json=enumdeclAll",
Filename: "gogo.proto",
}
var E_GoprotoRegistration = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FileOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 63032,
Name: "gogoproto.goproto_registration",
Tag: "varint,63032,opt,name=goproto_registration,json=goprotoRegistration",
Filename: "gogo.proto",
}
var E_GoprotoGetters = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.MessageOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 64001,
Name: "gogoproto.goproto_getters",
Tag: "varint,64001,opt,name=goproto_getters,json=goprotoGetters",
Filename: "gogo.proto",
}
var E_GoprotoStringer = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.MessageOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 64003,
Name: "gogoproto.goproto_stringer",
Tag: "varint,64003,opt,name=goproto_stringer,json=goprotoStringer",
Filename: "gogo.proto",
}
var E_VerboseEqual = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.MessageOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 64004,
Name: "gogoproto.verbose_equal",
Tag: "varint,64004,opt,name=verbose_equal,json=verboseEqual",
Filename: "gogo.proto",
}
var E_Face = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.MessageOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 64005,
Name: "gogoproto.face",
Tag: "varint,64005,opt,name=face",
Filename: "gogo.proto",
}
var E_Gostring = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.MessageOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 64006,
Name: "gogoproto.gostring",
Tag: "varint,64006,opt,name=gostring",
Filename: "gogo.proto",
}
var E_Populate = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.MessageOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 64007,
Name: "gogoproto.populate",
Tag: "varint,64007,opt,name=populate",
Filename: "gogo.proto",
}
var E_Stringer = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.MessageOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 67008,
Name: "gogoproto.stringer",
Tag: "varint,67008,opt,name=stringer",
Filename: "gogo.proto",
}
var E_Onlyone = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.MessageOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 64009,
Name: "gogoproto.onlyone",
Tag: "varint,64009,opt,name=onlyone",
Filename: "gogo.proto",
}
var E_Equal = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.MessageOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 64013,
Name: "gogoproto.equal",
Tag: "varint,64013,opt,name=equal",
Filename: "gogo.proto",
}
var E_Description = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.MessageOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 64014,
Name: "gogoproto.description",
Tag: "varint,64014,opt,name=description",
Filename: "gogo.proto",
}
var E_Testgen = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.MessageOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 64015,
Name: "gogoproto.testgen",
Tag: "varint,64015,opt,name=testgen",
Filename: "gogo.proto",
}
var E_Benchgen = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.MessageOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 64016,
Name: "gogoproto.benchgen",
Tag: "varint,64016,opt,name=benchgen",
Filename: "gogo.proto",
}
var E_Marshaler = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.MessageOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 64017,
Name: "gogoproto.marshaler",
Tag: "varint,64017,opt,name=marshaler",
Filename: "gogo.proto",
}
var E_Unmarshaler = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.MessageOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 64018,
Name: "gogoproto.unmarshaler",
Tag: "varint,64018,opt,name=unmarshaler",
Filename: "gogo.proto",
}
var E_StableMarshaler = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.MessageOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 64019,
Name: "gogoproto.stable_marshaler",
Tag: "varint,64019,opt,name=stable_marshaler,json=stableMarshaler",
Filename: "gogo.proto",
}
var E_Sizer = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.MessageOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 64020,
Name: "gogoproto.sizer",
Tag: "varint,64020,opt,name=sizer",
Filename: "gogo.proto",
}
var E_UnsafeMarshaler = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.MessageOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 64023,
Name: "gogoproto.unsafe_marshaler",
Tag: "varint,64023,opt,name=unsafe_marshaler,json=unsafeMarshaler",
Filename: "gogo.proto",
}
var E_UnsafeUnmarshaler = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.MessageOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 64024,
Name: "gogoproto.unsafe_unmarshaler",
Tag: "varint,64024,opt,name=unsafe_unmarshaler,json=unsafeUnmarshaler",
Filename: "gogo.proto",
}
var E_GoprotoExtensionsMap = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.MessageOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 64025,
Name: "gogoproto.goproto_extensions_map",
Tag: "varint,64025,opt,name=goproto_extensions_map,json=goprotoExtensionsMap",
Filename: "gogo.proto",
}
var E_GoprotoUnrecognized = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.MessageOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 64026,
Name: "gogoproto.goproto_unrecognized",
Tag: "varint,64026,opt,name=goproto_unrecognized,json=goprotoUnrecognized",
Filename: "gogo.proto",
}
var E_Protosizer = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.MessageOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 64028,
Name: "gogoproto.protosizer",
Tag: "varint,64028,opt,name=protosizer",
Filename: "gogo.proto",
}
var E_Compare = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.MessageOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 64029,
Name: "gogoproto.compare",
Tag: "varint,64029,opt,name=compare",
Filename: "gogo.proto",
}
var E_Typedecl = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.MessageOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 64030,
Name: "gogoproto.typedecl",
Tag: "varint,64030,opt,name=typedecl",
Filename: "gogo.proto",
}
var E_Nullable = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FieldOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 65001,
Name: "gogoproto.nullable",
Tag: "varint,65001,opt,name=nullable",
Filename: "gogo.proto",
}
var E_Embed = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FieldOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 65002,
Name: "gogoproto.embed",
Tag: "varint,65002,opt,name=embed",
Filename: "gogo.proto",
}
var E_Customtype = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FieldOptions)(nil),
ExtensionType: (*string)(nil),
Field: 65003,
Name: "gogoproto.customtype",
Tag: "bytes,65003,opt,name=customtype",
Filename: "gogo.proto",
}
var E_Customname = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FieldOptions)(nil),
ExtensionType: (*string)(nil),
Field: 65004,
Name: "gogoproto.customname",
Tag: "bytes,65004,opt,name=customname",
Filename: "gogo.proto",
}
var E_Jsontag = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FieldOptions)(nil),
ExtensionType: (*string)(nil),
Field: 65005,
Name: "gogoproto.jsontag",
Tag: "bytes,65005,opt,name=jsontag",
Filename: "gogo.proto",
}
var E_Moretags = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FieldOptions)(nil),
ExtensionType: (*string)(nil),
Field: 65006,
Name: "gogoproto.moretags",
Tag: "bytes,65006,opt,name=moretags",
Filename: "gogo.proto",
}
var E_Casttype = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FieldOptions)(nil),
ExtensionType: (*string)(nil),
Field: 65007,
Name: "gogoproto.casttype",
Tag: "bytes,65007,opt,name=casttype",
Filename: "gogo.proto",
}
var E_Castkey = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FieldOptions)(nil),
ExtensionType: (*string)(nil),
Field: 65008,
Name: "gogoproto.castkey",
Tag: "bytes,65008,opt,name=castkey",
Filename: "gogo.proto",
}
var E_Castvalue = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FieldOptions)(nil),
ExtensionType: (*string)(nil),
Field: 65009,
Name: "gogoproto.castvalue",
Tag: "bytes,65009,opt,name=castvalue",
Filename: "gogo.proto",
}
var E_Stdtime = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FieldOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 65010,
Name: "gogoproto.stdtime",
Tag: "varint,65010,opt,name=stdtime",
Filename: "gogo.proto",
}
var E_Stdduration = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FieldOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 65011,
Name: "gogoproto.stdduration",
Tag: "varint,65011,opt,name=stdduration",
Filename: "gogo.proto",
}
func init() {
proto.RegisterExtension(E_GoprotoEnumPrefix)
proto.RegisterExtension(E_GoprotoEnumStringer)
proto.RegisterExtension(E_EnumStringer)
proto.RegisterExtension(E_EnumCustomname)
proto.RegisterExtension(E_Enumdecl)
proto.RegisterExtension(E_EnumvalueCustomname)
proto.RegisterExtension(E_GoprotoGettersAll)
proto.RegisterExtension(E_GoprotoEnumPrefixAll)
proto.RegisterExtension(E_GoprotoStringerAll)
proto.RegisterExtension(E_VerboseEqualAll)
proto.RegisterExtension(E_FaceAll)
proto.RegisterExtension(E_GostringAll)
proto.RegisterExtension(E_PopulateAll)
proto.RegisterExtension(E_StringerAll)
proto.RegisterExtension(E_OnlyoneAll)
proto.RegisterExtension(E_EqualAll)
proto.RegisterExtension(E_DescriptionAll)
proto.RegisterExtension(E_TestgenAll)
proto.RegisterExtension(E_BenchgenAll)
proto.RegisterExtension(E_MarshalerAll)
proto.RegisterExtension(E_UnmarshalerAll)
proto.RegisterExtension(E_StableMarshalerAll)
proto.RegisterExtension(E_SizerAll)
proto.RegisterExtension(E_GoprotoEnumStringerAll)
proto.RegisterExtension(E_EnumStringerAll)
proto.RegisterExtension(E_UnsafeMarshalerAll)
proto.RegisterExtension(E_UnsafeUnmarshalerAll)
proto.RegisterExtension(E_GoprotoExtensionsMapAll)
proto.RegisterExtension(E_GoprotoUnrecognizedAll)
proto.RegisterExtension(E_GogoprotoImport)
proto.RegisterExtension(E_ProtosizerAll)
proto.RegisterExtension(E_CompareAll)
proto.RegisterExtension(E_TypedeclAll)
proto.RegisterExtension(E_EnumdeclAll)
proto.RegisterExtension(E_GoprotoRegistration)
proto.RegisterExtension(E_GoprotoGetters)
proto.RegisterExtension(E_GoprotoStringer)
proto.RegisterExtension(E_VerboseEqual)
proto.RegisterExtension(E_Face)
proto.RegisterExtension(E_Gostring)
proto.RegisterExtension(E_Populate)
proto.RegisterExtension(E_Stringer)
proto.RegisterExtension(E_Onlyone)
proto.RegisterExtension(E_Equal)
proto.RegisterExtension(E_Description)
proto.RegisterExtension(E_Testgen)
proto.RegisterExtension(E_Benchgen)
proto.RegisterExtension(E_Marshaler)
proto.RegisterExtension(E_Unmarshaler)
proto.RegisterExtension(E_StableMarshaler)
proto.RegisterExtension(E_Sizer)
proto.RegisterExtension(E_UnsafeMarshaler)
proto.RegisterExtension(E_UnsafeUnmarshaler)
proto.RegisterExtension(E_GoprotoExtensionsMap)
proto.RegisterExtension(E_GoprotoUnrecognized)
proto.RegisterExtension(E_Protosizer)
proto.RegisterExtension(E_Compare)
proto.RegisterExtension(E_Typedecl)
proto.RegisterExtension(E_Nullable)
proto.RegisterExtension(E_Embed)
proto.RegisterExtension(E_Customtype)
proto.RegisterExtension(E_Customname)
proto.RegisterExtension(E_Jsontag)
proto.RegisterExtension(E_Moretags)
proto.RegisterExtension(E_Casttype)
proto.RegisterExtension(E_Castkey)
proto.RegisterExtension(E_Castvalue)
proto.RegisterExtension(E_Stdtime)
proto.RegisterExtension(E_Stdduration)
}
func init() { proto.RegisterFile("gogo.proto", fileDescriptorGogo) }
var fileDescriptorGogo = []byte{
// 1201 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x98, 0xcb, 0x6f, 0x1c, 0x45,
0x13, 0xc0, 0xf5, 0xe9, 0x73, 0x64, 0x6f, 0xf9, 0x85, 0xd7, 0xc6, 0x84, 0x08, 0x44, 0x72, 0xe3,
0xe4, 0x9c, 0x22, 0x94, 0xb6, 0x22, 0xcb, 0xb1, 0x1c, 0x2b, 0x11, 0x06, 0x63, 0xe2, 0x00, 0xe2,
0xb0, 0x9a, 0xdd, 0x6d, 0x4f, 0x06, 0x66, 0xa6, 0x87, 0x99, 0x9e, 0x28, 0xce, 0x0d, 0x85, 0x87,
0x10, 0xe2, 0x8d, 0x04, 0x09, 0x49, 0x80, 0x03, 0xef, 0x67, 0x78, 0x1f, 0xb9, 0xf0, 0xb8, 0xf2,
0x3f, 0x70, 0x01, 0xcc, 0xdb, 0x37, 0x5f, 0x50, 0xcd, 0x56, 0xcd, 0xf6, 0xac, 0x57, 0xea, 0xde,
0xdb, 0xec, 0xba, 0x7f, 0xbf, 0xad, 0xa9, 0x9a, 0xae, 0xea, 0x31, 0x80, 0xaf, 0x7c, 0x35, 0x97,
0xa4, 0x4a, 0xab, 0x7a, 0x0d, 0xaf, 0x8b, 0xcb, 0x03, 0x07, 0x7d, 0xa5, 0xfc, 0x50, 0x1e, 0x2e,
0x3e, 0x35, 0xf3, 0xcd, 0xc3, 0x6d, 0x99, 0xb5, 0xd2, 0x20, 0xd1, 0x2a, 0xed, 0x2c, 0x16, 0x77,
0xc1, 0x34, 0x2d, 0x6e, 0xc8, 0x38, 0x8f, 0x1a, 0x49, 0x2a, 0x37, 0x83, 0xf3, 0xf5, 0x5b, 0xe6,
0x3a, 0xe4, 0x1c, 0x93, 0x73, 0xcb, 0x71, 0x1e, 0xdd, 0x9d, 0xe8, 0x40, 0xc5, 0xd9, 0xfe, 0xeb,
0x3f, 0xff, 0xff, 0xe0, 0xff, 0x6e, 0x1f, 0x59, 0x9f, 0x22, 0x14, 0xff, 0xb6, 0x56, 0x80, 0x62,
0x1d, 0x6e, 0xac, 0xf8, 0x32, 0x9d, 0x06, 0xb1, 0x2f, 0x53, 0x8b, 0xf1, 0x3b, 0x32, 0x4e, 0x1b,
0xc6, 0x7b, 0x09, 0x15, 0x4b, 0x30, 0x3e, 0x88, 0xeb, 0x7b, 0x72, 0x8d, 0x49, 0x53, 0xb2, 0x02,
0x93, 0x85, 0xa4, 0x95, 0x67, 0x5a, 0x45, 0xb1, 0x17, 0x49, 0x8b, 0xe6, 0x87, 0x42, 0x53, 0x5b,
0x9f, 0x40, 0x6c, 0xa9, 0xa4, 0x84, 0x80, 0x11, 0xfc, 0xa6, 0x2d, 0x5b, 0xa1, 0xc5, 0xf0, 0x23,
0x05, 0x52, 0xae, 0x17, 0x67, 0x60, 0x06, 0xaf, 0xcf, 0x79, 0x61, 0x2e, 0xcd, 0x48, 0x0e, 0xf5,
0xf5, 0x9c, 0xc1, 0x65, 0x2c, 0xfb, 0xe9, 0xe2, 0x50, 0x11, 0xce, 0x74, 0x29, 0x30, 0x62, 0x32,
0xaa, 0xe8, 0x4b, 0xad, 0x65, 0x9a, 0x35, 0xbc, 0xb0, 0x5f, 0x78, 0x27, 0x82, 0xb0, 0x34, 0x5e,
0xda, 0xae, 0x56, 0x71, 0xa5, 0x43, 0x2e, 0x86, 0xa1, 0xd8, 0x80, 0x9b, 0xfa, 0x3c, 0x15, 0x0e,
0xce, 0xcb, 0xe4, 0x9c, 0xd9, 0xf3, 0x64, 0xa0, 0x76, 0x0d, 0xf8, 0xfb, 0xb2, 0x96, 0x0e, 0xce,
0xd7, 0xc8, 0x59, 0x27, 0x96, 0x4b, 0x8a, 0xc6, 0x53, 0x30, 0x75, 0x4e, 0xa6, 0x4d, 0x95, 0xc9,
0x86, 0x7c, 0x24, 0xf7, 0x42, 0x07, 0xdd, 0x15, 0xd2, 0x4d, 0x12, 0xb8, 0x8c, 0x1c, 0xba, 0x8e,
0xc2, 0xc8, 0xa6, 0xd7, 0x92, 0x0e, 0x8a, 0xab, 0xa4, 0x18, 0xc6, 0xf5, 0x88, 0x2e, 0xc2, 0x98,
0xaf, 0x3a, 0xb7, 0xe4, 0x80, 0x5f, 0x23, 0x7c, 0x94, 0x19, 0x52, 0x24, 0x2a, 0xc9, 0x43, 0x4f,
0xbb, 0x44, 0xf0, 0x3a, 0x2b, 0x98, 0x21, 0xc5, 0x00, 0x69, 0x7d, 0x83, 0x15, 0x99, 0x91, 0xcf,
0x05, 0x18, 0x55, 0x71, 0xb8, 0xa5, 0x62, 0x97, 0x20, 0xde, 0x24, 0x03, 0x10, 0x82, 0x82, 0x79,
0xa8, 0xb9, 0x16, 0xe2, 0xad, 0x6d, 0xde, 0x1e, 0x5c, 0x81, 0x15, 0x98, 0xe4, 0x06, 0x15, 0xa8,
0xd8, 0x41, 0xf1, 0x36, 0x29, 0x26, 0x0c, 0x8c, 0x6e, 0x43, 0xcb, 0x4c, 0xfb, 0xd2, 0x45, 0xf2,
0x0e, 0xdf, 0x06, 0x21, 0x94, 0xca, 0xa6, 0x8c, 0x5b, 0x67, 0xdd, 0x0c, 0xef, 0x72, 0x2a, 0x99,
0x41, 0xc5, 0x12, 0x8c, 0x47, 0x5e, 0x9a, 0x9d, 0xf5, 0x42, 0xa7, 0x72, 0xbc, 0x47, 0x8e, 0xb1,
0x12, 0xa2, 0x8c, 0xe4, 0xf1, 0x20, 0x9a, 0xf7, 0x39, 0x23, 0x06, 0x46, 0x5b, 0x2f, 0xd3, 0x5e,
0x33, 0x94, 0x8d, 0x41, 0x6c, 0x1f, 0xf0, 0xd6, 0xeb, 0xb0, 0xab, 0xa6, 0x71, 0x1e, 0x6a, 0x59,
0x70, 0xc1, 0x49, 0xf3, 0x21, 0x57, 0xba, 0x00, 0x10, 0x7e, 0x00, 0x6e, 0xee, 0x3b, 0x26, 0x1c,
0x64, 0x1f, 0x91, 0x6c, 0xb6, 0xcf, 0xa8, 0xa0, 0x96, 0x30, 0xa8, 0xf2, 0x63, 0x6e, 0x09, 0xb2,
0xc7, 0xb5, 0x06, 0x33, 0x79, 0x9c, 0x79, 0x9b, 0x83, 0x65, 0xed, 0x13, 0xce, 0x5a, 0x87, 0xad,
0x64, 0xed, 0x34, 0xcc, 0x92, 0x71, 0xb0, 0xba, 0x7e, 0xca, 0x8d, 0xb5, 0x43, 0x6f, 0x54, 0xab,
0xfb, 0x20, 0x1c, 0x28, 0xd3, 0x79, 0x5e, 0xcb, 0x38, 0x43, 0xa6, 0x11, 0x79, 0x89, 0x83, 0xf9,
0x3a, 0x99, 0xb9, 0xe3, 0x2f, 0x97, 0x82, 0x55, 0x2f, 0x41, 0xf9, 0xfd, 0xb0, 0x9f, 0xe5, 0x79,
0x9c, 0xca, 0x96, 0xf2, 0xe3, 0xe0, 0x82, 0x6c, 0x3b, 0xa8, 0x3f, 0xeb, 0x29, 0xd5, 0x86, 0x81,
0xa3, 0xf9, 0x24, 0xdc, 0x50, 0x9e, 0x55, 0x1a, 0x41, 0x94, 0xa8, 0x54, 0x5b, 0x8c, 0x9f, 0x73,
0xa5, 0x4a, 0xee, 0x64, 0x81, 0x89, 0x65, 0x98, 0x28, 0x3e, 0xba, 0x3e, 0x92, 0x5f, 0x90, 0x68,
0xbc, 0x4b, 0x51, 0xe3, 0x68, 0xa9, 0x28, 0xf1, 0x52, 0x97, 0xfe, 0xf7, 0x25, 0x37, 0x0e, 0x42,
0xa8, 0x71, 0xe8, 0xad, 0x44, 0xe2, 0xb4, 0x77, 0x30, 0x7c, 0xc5, 0x8d, 0x83, 0x19, 0x52, 0xf0,
0x81, 0xc1, 0x41, 0xf1, 0x35, 0x2b, 0x98, 0x41, 0xc5, 0x3d, 0xdd, 0x41, 0x9b, 0x4a, 0x3f, 0xc8,
0x74, 0xea, 0xe1, 0x6a, 0x8b, 0xea, 0x9b, 0xed, 0xea, 0x21, 0x6c, 0xdd, 0x40, 0xc5, 0x29, 0x98,
0xec, 0x39, 0x62, 0xd4, 0x6f, 0xdb, 0x63, 0x5b, 0x95, 0x59, 0xe6, 0xf9, 0xa5, 0xf0, 0xd1, 0x1d,
0x6a, 0x46, 0xd5, 0x13, 0x86, 0xb8, 0x13, 0xeb, 0x5e, 0x3d, 0x07, 0xd8, 0x65, 0x17, 0x77, 0xca,
0xd2, 0x57, 0x8e, 0x01, 0xe2, 0x04, 0x8c, 0x57, 0xce, 0x00, 0x76, 0xd5, 0x63, 0xa4, 0x1a, 0x33,
0x8f, 0x00, 0xe2, 0x08, 0x0c, 0xe1, 0x3c, 0xb7, 0xe3, 0x8f, 0x13, 0x5e, 0x2c, 0x17, 0xc7, 0x60,
0x84, 0xe7, 0xb8, 0x1d, 0x7d, 0x82, 0xd0, 0x12, 0x41, 0x9c, 0x67, 0xb8, 0x1d, 0x7f, 0x92, 0x71,
0x46, 0x10, 0x77, 0x4f, 0xe1, 0xb7, 0x4f, 0x0f, 0x51, 0x1f, 0xe6, 0xdc, 0xcd, 0xc3, 0x30, 0x0d,
0x6f, 0x3b, 0xfd, 0x14, 0xfd, 0x38, 0x13, 0xe2, 0x0e, 0xd8, 0xe7, 0x98, 0xf0, 0x67, 0x08, 0xed,
0xac, 0x17, 0x4b, 0x30, 0x6a, 0x0c, 0x6c, 0x3b, 0xfe, 0x2c, 0xe1, 0x26, 0x85, 0xa1, 0xd3, 0xc0,
0xb6, 0x0b, 0x9e, 0xe3, 0xd0, 0x89, 0xc0, 0xb4, 0xf1, 0xac, 0xb6, 0xd3, 0xcf, 0x73, 0xd6, 0x19,
0x11, 0x0b, 0x50, 0x2b, 0xfb, 0xaf, 0x9d, 0x7f, 0x81, 0xf8, 0x2e, 0x83, 0x19, 0x30, 0xfa, 0xbf,
0x5d, 0xf1, 0x22, 0x67, 0xc0, 0xa0, 0x70, 0x1b, 0xf5, 0xce, 0x74, 0xbb, 0xe9, 0x25, 0xde, 0x46,
0x3d, 0x23, 0x1d, 0xab, 0x59, 0xb4, 0x41, 0xbb, 0xe2, 0x65, 0xae, 0x66, 0xb1, 0x1e, 0xc3, 0xe8,
0x1d, 0x92, 0x76, 0xc7, 0x2b, 0x1c, 0x46, 0xcf, 0x8c, 0x14, 0x6b, 0x50, 0xdf, 0x3b, 0x20, 0xed,
0xbe, 0x57, 0xc9, 0x37, 0xb5, 0x67, 0x3e, 0x8a, 0xfb, 0x60, 0xb6, 0xff, 0x70, 0xb4, 0x5b, 0x2f,
0xed, 0xf4, 0xbc, 0xce, 0x98, 0xb3, 0x51, 0x9c, 0xee, 0x76, 0x59, 0x73, 0x30, 0xda, 0xb5, 0x97,
0x77, 0xaa, 0x8d, 0xd6, 0x9c, 0x8b, 0x62, 0x11, 0xa0, 0x3b, 0x93, 0xec, 0xae, 0x2b, 0xe4, 0x32,
0x20, 0xdc, 0x1a, 0x34, 0x92, 0xec, 0xfc, 0x55, 0xde, 0x1a, 0x44, 0xe0, 0xd6, 0xe0, 0x69, 0x64,
0xa7, 0xaf, 0xf1, 0xd6, 0x60, 0x44, 0xcc, 0xc3, 0x48, 0x9c, 0x87, 0x21, 0x3e, 0x5b, 0xf5, 0x5b,
0xfb, 0x8c, 0x1b, 0x19, 0xb6, 0x19, 0xfe, 0x65, 0x97, 0x60, 0x06, 0xc4, 0x11, 0xd8, 0x27, 0xa3,
0xa6, 0x6c, 0xdb, 0xc8, 0x5f, 0x77, 0xb9, 0x9f, 0xe0, 0x6a, 0xb1, 0x00, 0xd0, 0x79, 0x99, 0xc6,
0x28, 0x6c, 0xec, 0x6f, 0xbb, 0x9d, 0xf7, 0x7a, 0x03, 0xe9, 0x0a, 0x8a, 0xb7, 0x71, 0x8b, 0x60,
0xbb, 0x2a, 0x28, 0x5e, 0xc0, 0x8f, 0xc2, 0xf0, 0x43, 0x99, 0x8a, 0xb5, 0xe7, 0xdb, 0xe8, 0xdf,
0x89, 0xe6, 0xf5, 0x98, 0xb0, 0x48, 0xa5, 0x52, 0x7b, 0x7e, 0x66, 0x63, 0xff, 0x20, 0xb6, 0x04,
0x10, 0x6e, 0x79, 0x99, 0x76, 0xb9, 0xef, 0x3f, 0x19, 0x66, 0x00, 0x83, 0xc6, 0xeb, 0x87, 0xe5,
0x96, 0x8d, 0xfd, 0x8b, 0x83, 0xa6, 0xf5, 0xe2, 0x18, 0xd4, 0xf0, 0xb2, 0xf8, 0x3f, 0x84, 0x0d,
0xfe, 0x9b, 0xe0, 0x2e, 0x81, 0xbf, 0x9c, 0xe9, 0xb6, 0x0e, 0xec, 0xc9, 0xfe, 0x87, 0x2a, 0xcd,
0xeb, 0xc5, 0x22, 0x8c, 0x66, 0xba, 0xdd, 0xce, 0xe9, 0x44, 0x63, 0xc1, 0xff, 0xdd, 0x2d, 0x5f,
0x72, 0x4b, 0xe6, 0xf8, 0x21, 0x98, 0x6e, 0xa9, 0xa8, 0x17, 0x3c, 0x0e, 0x2b, 0x6a, 0x45, 0xad,
0x15, 0xbb, 0xe8, 0xbf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x0a, 0x9c, 0xec, 0xd8, 0x50, 0x13, 0x00,
0x00,
}

View File

@ -0,0 +1,45 @@
// Code generated by protoc-gen-go.
// source: gogo.proto
// DO NOT EDIT!
package gogoproto
import proto "github.com/gogo/protobuf/proto"
import json "encoding/json"
import math "math"
import google_protobuf "github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
// Reference proto, json, and math imports to suppress error if they are not otherwise used.
var _ = proto.Marshal
var _ = &json.SyntaxError{}
var _ = math.Inf
var E_Nullable = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FieldOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 51235,
Name: "gogoproto.nullable",
Tag: "varint,51235,opt,name=nullable",
}
var E_Embed = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FieldOptions)(nil),
ExtensionType: (*bool)(nil),
Field: 51236,
Name: "gogoproto.embed",
Tag: "varint,51236,opt,name=embed",
}
var E_Customtype = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.FieldOptions)(nil),
ExtensionType: (*string)(nil),
Field: 51237,
Name: "gogoproto.customtype",
Tag: "bytes,51237,opt,name=customtype",
}
func init() {
proto.RegisterExtension(E_Nullable)
proto.RegisterExtension(E_Embed)
proto.RegisterExtension(E_Customtype)
}

132
vendor/github.com/gogo/protobuf/gogoproto/gogo.proto generated vendored Normal file
View File

@ -0,0 +1,132 @@
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2013, The GoGo Authors. All rights reserved.
// http://github.com/gogo/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.
//
// 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 = "proto2";
package gogoproto;
import "google/protobuf/descriptor.proto";
option java_package = "com.google.protobuf";
option java_outer_classname = "GoGoProtos";
extend google.protobuf.EnumOptions {
optional bool goproto_enum_prefix = 62001;
optional bool goproto_enum_stringer = 62021;
optional bool enum_stringer = 62022;
optional string enum_customname = 62023;
optional bool enumdecl = 62024;
}
extend google.protobuf.EnumValueOptions {
optional string enumvalue_customname = 66001;
}
extend google.protobuf.FileOptions {
optional bool goproto_getters_all = 63001;
optional bool goproto_enum_prefix_all = 63002;
optional bool goproto_stringer_all = 63003;
optional bool verbose_equal_all = 63004;
optional bool face_all = 63005;
optional bool gostring_all = 63006;
optional bool populate_all = 63007;
optional bool stringer_all = 63008;
optional bool onlyone_all = 63009;
optional bool equal_all = 63013;
optional bool description_all = 63014;
optional bool testgen_all = 63015;
optional bool benchgen_all = 63016;
optional bool marshaler_all = 63017;
optional bool unmarshaler_all = 63018;
optional bool stable_marshaler_all = 63019;
optional bool sizer_all = 63020;
optional bool goproto_enum_stringer_all = 63021;
optional bool enum_stringer_all = 63022;
optional bool unsafe_marshaler_all = 63023;
optional bool unsafe_unmarshaler_all = 63024;
optional bool goproto_extensions_map_all = 63025;
optional bool goproto_unrecognized_all = 63026;
optional bool gogoproto_import = 63027;
optional bool protosizer_all = 63028;
optional bool compare_all = 63029;
optional bool typedecl_all = 63030;
optional bool enumdecl_all = 63031;
optional bool goproto_registration = 63032;
}
extend google.protobuf.MessageOptions {
optional bool goproto_getters = 64001;
optional bool goproto_stringer = 64003;
optional bool verbose_equal = 64004;
optional bool face = 64005;
optional bool gostring = 64006;
optional bool populate = 64007;
optional bool stringer = 67008;
optional bool onlyone = 64009;
optional bool equal = 64013;
optional bool description = 64014;
optional bool testgen = 64015;
optional bool benchgen = 64016;
optional bool marshaler = 64017;
optional bool unmarshaler = 64018;
optional bool stable_marshaler = 64019;
optional bool sizer = 64020;
optional bool unsafe_marshaler = 64023;
optional bool unsafe_unmarshaler = 64024;
optional bool goproto_extensions_map = 64025;
optional bool goproto_unrecognized = 64026;
optional bool protosizer = 64028;
optional bool compare = 64029;
optional bool typedecl = 64030;
}
extend google.protobuf.FieldOptions {
optional bool nullable = 65001;
optional bool embed = 65002;
optional string customtype = 65003;
optional string customname = 65004;
optional string jsontag = 65005;
optional string moretags = 65006;
optional string casttype = 65007;
optional string castkey = 65008;
optional string castvalue = 65009;
optional bool stdtime = 65010;
optional bool stdduration = 65011;
}

357
vendor/github.com/gogo/protobuf/gogoproto/helper.go generated vendored Normal file
View File

@ -0,0 +1,357 @@
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2013, The GoGo Authors. All rights reserved.
// http://github.com/gogo/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.
//
// 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 gogoproto
import google_protobuf "github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
import proto "github.com/gogo/protobuf/proto"
func IsEmbed(field *google_protobuf.FieldDescriptorProto) bool {
return proto.GetBoolExtension(field.Options, E_Embed, false)
}
func IsNullable(field *google_protobuf.FieldDescriptorProto) bool {
return proto.GetBoolExtension(field.Options, E_Nullable, true)
}
func IsStdTime(field *google_protobuf.FieldDescriptorProto) bool {
return proto.GetBoolExtension(field.Options, E_Stdtime, false)
}
func IsStdDuration(field *google_protobuf.FieldDescriptorProto) bool {
return proto.GetBoolExtension(field.Options, E_Stdduration, false)
}
func NeedsNilCheck(proto3 bool, field *google_protobuf.FieldDescriptorProto) bool {
nullable := IsNullable(field)
if field.IsMessage() || IsCustomType(field) {
return nullable
}
if proto3 {
return false
}
return nullable || *field.Type == google_protobuf.FieldDescriptorProto_TYPE_BYTES
}
func IsCustomType(field *google_protobuf.FieldDescriptorProto) bool {
typ := GetCustomType(field)
if len(typ) > 0 {
return true
}
return false
}
func IsCastType(field *google_protobuf.FieldDescriptorProto) bool {
typ := GetCastType(field)
if len(typ) > 0 {
return true
}
return false
}
func IsCastKey(field *google_protobuf.FieldDescriptorProto) bool {
typ := GetCastKey(field)
if len(typ) > 0 {
return true
}
return false
}
func IsCastValue(field *google_protobuf.FieldDescriptorProto) bool {
typ := GetCastValue(field)
if len(typ) > 0 {
return true
}
return false
}
func HasEnumDecl(file *google_protobuf.FileDescriptorProto, enum *google_protobuf.EnumDescriptorProto) bool {
return proto.GetBoolExtension(enum.Options, E_Enumdecl, proto.GetBoolExtension(file.Options, E_EnumdeclAll, true))
}
func HasTypeDecl(file *google_protobuf.FileDescriptorProto, message *google_protobuf.DescriptorProto) bool {
return proto.GetBoolExtension(message.Options, E_Typedecl, proto.GetBoolExtension(file.Options, E_TypedeclAll, true))
}
func GetCustomType(field *google_protobuf.FieldDescriptorProto) string {
if field == nil {
return ""
}
if field.Options != nil {
v, err := proto.GetExtension(field.Options, E_Customtype)
if err == nil && v.(*string) != nil {
return *(v.(*string))
}
}
return ""
}
func GetCastType(field *google_protobuf.FieldDescriptorProto) string {
if field == nil {
return ""
}
if field.Options != nil {
v, err := proto.GetExtension(field.Options, E_Casttype)
if err == nil && v.(*string) != nil {
return *(v.(*string))
}
}
return ""
}
func GetCastKey(field *google_protobuf.FieldDescriptorProto) string {
if field == nil {
return ""
}
if field.Options != nil {
v, err := proto.GetExtension(field.Options, E_Castkey)
if err == nil && v.(*string) != nil {
return *(v.(*string))
}
}
return ""
}
func GetCastValue(field *google_protobuf.FieldDescriptorProto) string {
if field == nil {
return ""
}
if field.Options != nil {
v, err := proto.GetExtension(field.Options, E_Castvalue)
if err == nil && v.(*string) != nil {
return *(v.(*string))
}
}
return ""
}
func IsCustomName(field *google_protobuf.FieldDescriptorProto) bool {
name := GetCustomName(field)
if len(name) > 0 {
return true
}
return false
}
func IsEnumCustomName(field *google_protobuf.EnumDescriptorProto) bool {
name := GetEnumCustomName(field)
if len(name) > 0 {
return true
}
return false
}
func IsEnumValueCustomName(field *google_protobuf.EnumValueDescriptorProto) bool {
name := GetEnumValueCustomName(field)
if len(name) > 0 {
return true
}
return false
}
func GetCustomName(field *google_protobuf.FieldDescriptorProto) string {
if field == nil {
return ""
}
if field.Options != nil {
v, err := proto.GetExtension(field.Options, E_Customname)
if err == nil && v.(*string) != nil {
return *(v.(*string))
}
}
return ""
}
func GetEnumCustomName(field *google_protobuf.EnumDescriptorProto) string {
if field == nil {
return ""
}
if field.Options != nil {
v, err := proto.GetExtension(field.Options, E_EnumCustomname)
if err == nil && v.(*string) != nil {
return *(v.(*string))
}
}
return ""
}
func GetEnumValueCustomName(field *google_protobuf.EnumValueDescriptorProto) string {
if field == nil {
return ""
}
if field.Options != nil {
v, err := proto.GetExtension(field.Options, E_EnumvalueCustomname)
if err == nil && v.(*string) != nil {
return *(v.(*string))
}
}
return ""
}
func GetJsonTag(field *google_protobuf.FieldDescriptorProto) *string {
if field == nil {
return nil
}
if field.Options != nil {
v, err := proto.GetExtension(field.Options, E_Jsontag)
if err == nil && v.(*string) != nil {
return (v.(*string))
}
}
return nil
}
func GetMoreTags(field *google_protobuf.FieldDescriptorProto) *string {
if field == nil {
return nil
}
if field.Options != nil {
v, err := proto.GetExtension(field.Options, E_Moretags)
if err == nil && v.(*string) != nil {
return (v.(*string))
}
}
return nil
}
type EnableFunc func(file *google_protobuf.FileDescriptorProto, message *google_protobuf.DescriptorProto) bool
func EnabledGoEnumPrefix(file *google_protobuf.FileDescriptorProto, enum *google_protobuf.EnumDescriptorProto) bool {
return proto.GetBoolExtension(enum.Options, E_GoprotoEnumPrefix, proto.GetBoolExtension(file.Options, E_GoprotoEnumPrefixAll, true))
}
func EnabledGoStringer(file *google_protobuf.FileDescriptorProto, message *google_protobuf.DescriptorProto) bool {
return proto.GetBoolExtension(message.Options, E_GoprotoStringer, proto.GetBoolExtension(file.Options, E_GoprotoStringerAll, true))
}
func HasGoGetters(file *google_protobuf.FileDescriptorProto, message *google_protobuf.DescriptorProto) bool {
return proto.GetBoolExtension(message.Options, E_GoprotoGetters, proto.GetBoolExtension(file.Options, E_GoprotoGettersAll, true))
}
func IsUnion(file *google_protobuf.FileDescriptorProto, message *google_protobuf.DescriptorProto) bool {
return proto.GetBoolExtension(message.Options, E_Onlyone, proto.GetBoolExtension(file.Options, E_OnlyoneAll, false))
}
func HasGoString(file *google_protobuf.FileDescriptorProto, message *google_protobuf.DescriptorProto) bool {
return proto.GetBoolExtension(message.Options, E_Gostring, proto.GetBoolExtension(file.Options, E_GostringAll, false))
}
func HasEqual(file *google_protobuf.FileDescriptorProto, message *google_protobuf.DescriptorProto) bool {
return proto.GetBoolExtension(message.Options, E_Equal, proto.GetBoolExtension(file.Options, E_EqualAll, false))
}
func HasVerboseEqual(file *google_protobuf.FileDescriptorProto, message *google_protobuf.DescriptorProto) bool {
return proto.GetBoolExtension(message.Options, E_VerboseEqual, proto.GetBoolExtension(file.Options, E_VerboseEqualAll, false))
}
func IsStringer(file *google_protobuf.FileDescriptorProto, message *google_protobuf.DescriptorProto) bool {
return proto.GetBoolExtension(message.Options, E_Stringer, proto.GetBoolExtension(file.Options, E_StringerAll, false))
}
func IsFace(file *google_protobuf.FileDescriptorProto, message *google_protobuf.DescriptorProto) bool {
return proto.GetBoolExtension(message.Options, E_Face, proto.GetBoolExtension(file.Options, E_FaceAll, false))
}
func HasDescription(file *google_protobuf.FileDescriptorProto, message *google_protobuf.DescriptorProto) bool {
return proto.GetBoolExtension(message.Options, E_Description, proto.GetBoolExtension(file.Options, E_DescriptionAll, false))
}
func HasPopulate(file *google_protobuf.FileDescriptorProto, message *google_protobuf.DescriptorProto) bool {
return proto.GetBoolExtension(message.Options, E_Populate, proto.GetBoolExtension(file.Options, E_PopulateAll, false))
}
func HasTestGen(file *google_protobuf.FileDescriptorProto, message *google_protobuf.DescriptorProto) bool {
return proto.GetBoolExtension(message.Options, E_Testgen, proto.GetBoolExtension(file.Options, E_TestgenAll, false))
}
func HasBenchGen(file *google_protobuf.FileDescriptorProto, message *google_protobuf.DescriptorProto) bool {
return proto.GetBoolExtension(message.Options, E_Benchgen, proto.GetBoolExtension(file.Options, E_BenchgenAll, false))
}
func IsMarshaler(file *google_protobuf.FileDescriptorProto, message *google_protobuf.DescriptorProto) bool {
return proto.GetBoolExtension(message.Options, E_Marshaler, proto.GetBoolExtension(file.Options, E_MarshalerAll, false))
}
func IsUnmarshaler(file *google_protobuf.FileDescriptorProto, message *google_protobuf.DescriptorProto) bool {
return proto.GetBoolExtension(message.Options, E_Unmarshaler, proto.GetBoolExtension(file.Options, E_UnmarshalerAll, false))
}
func IsStableMarshaler(file *google_protobuf.FileDescriptorProto, message *google_protobuf.DescriptorProto) bool {
return proto.GetBoolExtension(message.Options, E_StableMarshaler, proto.GetBoolExtension(file.Options, E_StableMarshalerAll, false))
}
func IsSizer(file *google_protobuf.FileDescriptorProto, message *google_protobuf.DescriptorProto) bool {
return proto.GetBoolExtension(message.Options, E_Sizer, proto.GetBoolExtension(file.Options, E_SizerAll, false))
}
func IsProtoSizer(file *google_protobuf.FileDescriptorProto, message *google_protobuf.DescriptorProto) bool {
return proto.GetBoolExtension(message.Options, E_Protosizer, proto.GetBoolExtension(file.Options, E_ProtosizerAll, false))
}
func IsGoEnumStringer(file *google_protobuf.FileDescriptorProto, enum *google_protobuf.EnumDescriptorProto) bool {
return proto.GetBoolExtension(enum.Options, E_GoprotoEnumStringer, proto.GetBoolExtension(file.Options, E_GoprotoEnumStringerAll, true))
}
func IsEnumStringer(file *google_protobuf.FileDescriptorProto, enum *google_protobuf.EnumDescriptorProto) bool {
return proto.GetBoolExtension(enum.Options, E_EnumStringer, proto.GetBoolExtension(file.Options, E_EnumStringerAll, false))
}
func IsUnsafeMarshaler(file *google_protobuf.FileDescriptorProto, message *google_protobuf.DescriptorProto) bool {
return proto.GetBoolExtension(message.Options, E_UnsafeMarshaler, proto.GetBoolExtension(file.Options, E_UnsafeMarshalerAll, false))
}
func IsUnsafeUnmarshaler(file *google_protobuf.FileDescriptorProto, message *google_protobuf.DescriptorProto) bool {
return proto.GetBoolExtension(message.Options, E_UnsafeUnmarshaler, proto.GetBoolExtension(file.Options, E_UnsafeUnmarshalerAll, false))
}
func HasExtensionsMap(file *google_protobuf.FileDescriptorProto, message *google_protobuf.DescriptorProto) bool {
return proto.GetBoolExtension(message.Options, E_GoprotoExtensionsMap, proto.GetBoolExtension(file.Options, E_GoprotoExtensionsMapAll, true))
}
func HasUnrecognized(file *google_protobuf.FileDescriptorProto, message *google_protobuf.DescriptorProto) bool {
if IsProto3(file) {
return false
}
return proto.GetBoolExtension(message.Options, E_GoprotoUnrecognized, proto.GetBoolExtension(file.Options, E_GoprotoUnrecognizedAll, true))
}
func IsProto3(file *google_protobuf.FileDescriptorProto) bool {
return file.GetSyntax() == "proto3"
}
func ImportsGoGoProto(file *google_protobuf.FileDescriptorProto) bool {
return proto.GetBoolExtension(file.Options, E_GogoprotoImport, true)
}
func HasCompare(file *google_protobuf.FileDescriptorProto, message *google_protobuf.DescriptorProto) bool {
return proto.GetBoolExtension(message.Options, E_Compare, proto.GetBoolExtension(file.Options, E_CompareAll, false))
}
func RegistersGolangProto(file *google_protobuf.FileDescriptorProto) bool {
return proto.GetBoolExtension(file.Options, E_GoprotoRegistration, false)
}

View File

@ -0,0 +1,36 @@
# 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.
regenerate:
go install github.com/gogo/protobuf/protoc-gen-gogo
go install github.com/gogo/protobuf/protoc-gen-gostring
protoc --gogo_out=. -I=../../protobuf/google/protobuf ../../protobuf/google/protobuf/descriptor.proto
protoc --gostring_out=. -I=../../protobuf/google/protobuf ../../protobuf/google/protobuf/descriptor.proto

View File

@ -0,0 +1,118 @@
// 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 descriptor provides functions for obtaining protocol buffer
// descriptors for generated Go types.
//
// These functions cannot go in package proto because they depend on the
// generated protobuf descriptor messages, which themselves depend on proto.
package descriptor
import (
"bytes"
"compress/gzip"
"fmt"
"io/ioutil"
"github.com/gogo/protobuf/proto"
)
// extractFile extracts a FileDescriptorProto from a gzip'd buffer.
func extractFile(gz []byte) (*FileDescriptorProto, error) {
r, err := gzip.NewReader(bytes.NewReader(gz))
if err != nil {
return nil, fmt.Errorf("failed to open gzip reader: %v", err)
}
defer r.Close()
b, err := ioutil.ReadAll(r)
if err != nil {
return nil, fmt.Errorf("failed to uncompress descriptor: %v", err)
}
fd := new(FileDescriptorProto)
if err := proto.Unmarshal(b, fd); err != nil {
return nil, fmt.Errorf("malformed FileDescriptorProto: %v", err)
}
return fd, nil
}
// Message is a proto.Message with a method to return its descriptor.
//
// Message types generated by the protocol compiler always satisfy
// the Message interface.
type Message interface {
proto.Message
Descriptor() ([]byte, []int)
}
// ForMessage returns a FileDescriptorProto and a DescriptorProto from within it
// describing the given message.
func ForMessage(msg Message) (fd *FileDescriptorProto, md *DescriptorProto) {
gz, path := msg.Descriptor()
fd, err := extractFile(gz)
if err != nil {
panic(fmt.Sprintf("invalid FileDescriptorProto for %T: %v", msg, err))
}
md = fd.MessageType[path[0]]
for _, i := range path[1:] {
md = md.NestedType[i]
}
return fd, md
}
// Is this field a scalar numeric type?
func (field *FieldDescriptorProto) IsScalar() bool {
if field.Type == nil {
return false
}
switch *field.Type {
case FieldDescriptorProto_TYPE_DOUBLE,
FieldDescriptorProto_TYPE_FLOAT,
FieldDescriptorProto_TYPE_INT64,
FieldDescriptorProto_TYPE_UINT64,
FieldDescriptorProto_TYPE_INT32,
FieldDescriptorProto_TYPE_FIXED64,
FieldDescriptorProto_TYPE_FIXED32,
FieldDescriptorProto_TYPE_BOOL,
FieldDescriptorProto_TYPE_UINT32,
FieldDescriptorProto_TYPE_ENUM,
FieldDescriptorProto_TYPE_SFIXED32,
FieldDescriptorProto_TYPE_SFIXED64,
FieldDescriptorProto_TYPE_SINT32,
FieldDescriptorProto_TYPE_SINT64:
return true
default:
return false
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,721 @@
// Code generated by protoc-gen-gogo.
// source: descriptor.proto
// DO NOT EDIT!
/*
Package descriptor is a generated protocol buffer package.
It is generated from these files:
descriptor.proto
It has these top-level messages:
FileDescriptorSet
FileDescriptorProto
DescriptorProto
FieldDescriptorProto
OneofDescriptorProto
EnumDescriptorProto
EnumValueDescriptorProto
ServiceDescriptorProto
MethodDescriptorProto
FileOptions
MessageOptions
FieldOptions
OneofOptions
EnumOptions
EnumValueOptions
ServiceOptions
MethodOptions
UninterpretedOption
SourceCodeInfo
GeneratedCodeInfo
*/
package descriptor
import fmt "fmt"
import strings "strings"
import github_com_gogo_protobuf_proto "github.com/gogo/protobuf/proto"
import sort "sort"
import strconv "strconv"
import reflect "reflect"
import proto "github.com/gogo/protobuf/proto"
import math "math"
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
func (this *FileDescriptorSet) GoString() string {
if this == nil {
return "nil"
}
s := make([]string, 0, 5)
s = append(s, "&descriptor.FileDescriptorSet{")
if this.File != nil {
s = append(s, "File: "+fmt.Sprintf("%#v", this.File)+",\n")
}
if this.XXX_unrecognized != nil {
s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
}
s = append(s, "}")
return strings.Join(s, "")
}
func (this *FileDescriptorProto) GoString() string {
if this == nil {
return "nil"
}
s := make([]string, 0, 16)
s = append(s, "&descriptor.FileDescriptorProto{")
if this.Name != nil {
s = append(s, "Name: "+valueToGoStringDescriptor(this.Name, "string")+",\n")
}
if this.Package != nil {
s = append(s, "Package: "+valueToGoStringDescriptor(this.Package, "string")+",\n")
}
if this.Dependency != nil {
s = append(s, "Dependency: "+fmt.Sprintf("%#v", this.Dependency)+",\n")
}
if this.PublicDependency != nil {
s = append(s, "PublicDependency: "+fmt.Sprintf("%#v", this.PublicDependency)+",\n")
}
if this.WeakDependency != nil {
s = append(s, "WeakDependency: "+fmt.Sprintf("%#v", this.WeakDependency)+",\n")
}
if this.MessageType != nil {
s = append(s, "MessageType: "+fmt.Sprintf("%#v", this.MessageType)+",\n")
}
if this.EnumType != nil {
s = append(s, "EnumType: "+fmt.Sprintf("%#v", this.EnumType)+",\n")
}
if this.Service != nil {
s = append(s, "Service: "+fmt.Sprintf("%#v", this.Service)+",\n")
}
if this.Extension != nil {
s = append(s, "Extension: "+fmt.Sprintf("%#v", this.Extension)+",\n")
}
if this.Options != nil {
s = append(s, "Options: "+fmt.Sprintf("%#v", this.Options)+",\n")
}
if this.SourceCodeInfo != nil {
s = append(s, "SourceCodeInfo: "+fmt.Sprintf("%#v", this.SourceCodeInfo)+",\n")
}
if this.Syntax != nil {
s = append(s, "Syntax: "+valueToGoStringDescriptor(this.Syntax, "string")+",\n")
}
if this.XXX_unrecognized != nil {
s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
}
s = append(s, "}")
return strings.Join(s, "")
}
func (this *DescriptorProto) GoString() string {
if this == nil {
return "nil"
}
s := make([]string, 0, 14)
s = append(s, "&descriptor.DescriptorProto{")
if this.Name != nil {
s = append(s, "Name: "+valueToGoStringDescriptor(this.Name, "string")+",\n")
}
if this.Field != nil {
s = append(s, "Field: "+fmt.Sprintf("%#v", this.Field)+",\n")
}
if this.Extension != nil {
s = append(s, "Extension: "+fmt.Sprintf("%#v", this.Extension)+",\n")
}
if this.NestedType != nil {
s = append(s, "NestedType: "+fmt.Sprintf("%#v", this.NestedType)+",\n")
}
if this.EnumType != nil {
s = append(s, "EnumType: "+fmt.Sprintf("%#v", this.EnumType)+",\n")
}
if this.ExtensionRange != nil {
s = append(s, "ExtensionRange: "+fmt.Sprintf("%#v", this.ExtensionRange)+",\n")
}
if this.OneofDecl != nil {
s = append(s, "OneofDecl: "+fmt.Sprintf("%#v", this.OneofDecl)+",\n")
}
if this.Options != nil {
s = append(s, "Options: "+fmt.Sprintf("%#v", this.Options)+",\n")
}
if this.ReservedRange != nil {
s = append(s, "ReservedRange: "+fmt.Sprintf("%#v", this.ReservedRange)+",\n")
}
if this.ReservedName != nil {
s = append(s, "ReservedName: "+fmt.Sprintf("%#v", this.ReservedName)+",\n")
}
if this.XXX_unrecognized != nil {
s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
}
s = append(s, "}")
return strings.Join(s, "")
}
func (this *DescriptorProto_ExtensionRange) GoString() string {
if this == nil {
return "nil"
}
s := make([]string, 0, 6)
s = append(s, "&descriptor.DescriptorProto_ExtensionRange{")
if this.Start != nil {
s = append(s, "Start: "+valueToGoStringDescriptor(this.Start, "int32")+",\n")
}
if this.End != nil {
s = append(s, "End: "+valueToGoStringDescriptor(this.End, "int32")+",\n")
}
if this.XXX_unrecognized != nil {
s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
}
s = append(s, "}")
return strings.Join(s, "")
}
func (this *DescriptorProto_ReservedRange) GoString() string {
if this == nil {
return "nil"
}
s := make([]string, 0, 6)
s = append(s, "&descriptor.DescriptorProto_ReservedRange{")
if this.Start != nil {
s = append(s, "Start: "+valueToGoStringDescriptor(this.Start, "int32")+",\n")
}
if this.End != nil {
s = append(s, "End: "+valueToGoStringDescriptor(this.End, "int32")+",\n")
}
if this.XXX_unrecognized != nil {
s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
}
s = append(s, "}")
return strings.Join(s, "")
}
func (this *FieldDescriptorProto) GoString() string {
if this == nil {
return "nil"
}
s := make([]string, 0, 14)
s = append(s, "&descriptor.FieldDescriptorProto{")
if this.Name != nil {
s = append(s, "Name: "+valueToGoStringDescriptor(this.Name, "string")+",\n")
}
if this.Number != nil {
s = append(s, "Number: "+valueToGoStringDescriptor(this.Number, "int32")+",\n")
}
if this.Label != nil {
s = append(s, "Label: "+valueToGoStringDescriptor(this.Label, "descriptor.FieldDescriptorProto_Label")+",\n")
}
if this.Type != nil {
s = append(s, "Type: "+valueToGoStringDescriptor(this.Type, "descriptor.FieldDescriptorProto_Type")+",\n")
}
if this.TypeName != nil {
s = append(s, "TypeName: "+valueToGoStringDescriptor(this.TypeName, "string")+",\n")
}
if this.Extendee != nil {
s = append(s, "Extendee: "+valueToGoStringDescriptor(this.Extendee, "string")+",\n")
}
if this.DefaultValue != nil {
s = append(s, "DefaultValue: "+valueToGoStringDescriptor(this.DefaultValue, "string")+",\n")
}
if this.OneofIndex != nil {
s = append(s, "OneofIndex: "+valueToGoStringDescriptor(this.OneofIndex, "int32")+",\n")
}
if this.JsonName != nil {
s = append(s, "JsonName: "+valueToGoStringDescriptor(this.JsonName, "string")+",\n")
}
if this.Options != nil {
s = append(s, "Options: "+fmt.Sprintf("%#v", this.Options)+",\n")
}
if this.XXX_unrecognized != nil {
s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
}
s = append(s, "}")
return strings.Join(s, "")
}
func (this *OneofDescriptorProto) GoString() string {
if this == nil {
return "nil"
}
s := make([]string, 0, 6)
s = append(s, "&descriptor.OneofDescriptorProto{")
if this.Name != nil {
s = append(s, "Name: "+valueToGoStringDescriptor(this.Name, "string")+",\n")
}
if this.Options != nil {
s = append(s, "Options: "+fmt.Sprintf("%#v", this.Options)+",\n")
}
if this.XXX_unrecognized != nil {
s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
}
s = append(s, "}")
return strings.Join(s, "")
}
func (this *EnumDescriptorProto) GoString() string {
if this == nil {
return "nil"
}
s := make([]string, 0, 7)
s = append(s, "&descriptor.EnumDescriptorProto{")
if this.Name != nil {
s = append(s, "Name: "+valueToGoStringDescriptor(this.Name, "string")+",\n")
}
if this.Value != nil {
s = append(s, "Value: "+fmt.Sprintf("%#v", this.Value)+",\n")
}
if this.Options != nil {
s = append(s, "Options: "+fmt.Sprintf("%#v", this.Options)+",\n")
}
if this.XXX_unrecognized != nil {
s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
}
s = append(s, "}")
return strings.Join(s, "")
}
func (this *EnumValueDescriptorProto) GoString() string {
if this == nil {
return "nil"
}
s := make([]string, 0, 7)
s = append(s, "&descriptor.EnumValueDescriptorProto{")
if this.Name != nil {
s = append(s, "Name: "+valueToGoStringDescriptor(this.Name, "string")+",\n")
}
if this.Number != nil {
s = append(s, "Number: "+valueToGoStringDescriptor(this.Number, "int32")+",\n")
}
if this.Options != nil {
s = append(s, "Options: "+fmt.Sprintf("%#v", this.Options)+",\n")
}
if this.XXX_unrecognized != nil {
s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
}
s = append(s, "}")
return strings.Join(s, "")
}
func (this *ServiceDescriptorProto) GoString() string {
if this == nil {
return "nil"
}
s := make([]string, 0, 7)
s = append(s, "&descriptor.ServiceDescriptorProto{")
if this.Name != nil {
s = append(s, "Name: "+valueToGoStringDescriptor(this.Name, "string")+",\n")
}
if this.Method != nil {
s = append(s, "Method: "+fmt.Sprintf("%#v", this.Method)+",\n")
}
if this.Options != nil {
s = append(s, "Options: "+fmt.Sprintf("%#v", this.Options)+",\n")
}
if this.XXX_unrecognized != nil {
s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
}
s = append(s, "}")
return strings.Join(s, "")
}
func (this *MethodDescriptorProto) GoString() string {
if this == nil {
return "nil"
}
s := make([]string, 0, 10)
s = append(s, "&descriptor.MethodDescriptorProto{")
if this.Name != nil {
s = append(s, "Name: "+valueToGoStringDescriptor(this.Name, "string")+",\n")
}
if this.InputType != nil {
s = append(s, "InputType: "+valueToGoStringDescriptor(this.InputType, "string")+",\n")
}
if this.OutputType != nil {
s = append(s, "OutputType: "+valueToGoStringDescriptor(this.OutputType, "string")+",\n")
}
if this.Options != nil {
s = append(s, "Options: "+fmt.Sprintf("%#v", this.Options)+",\n")
}
if this.ClientStreaming != nil {
s = append(s, "ClientStreaming: "+valueToGoStringDescriptor(this.ClientStreaming, "bool")+",\n")
}
if this.ServerStreaming != nil {
s = append(s, "ServerStreaming: "+valueToGoStringDescriptor(this.ServerStreaming, "bool")+",\n")
}
if this.XXX_unrecognized != nil {
s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
}
s = append(s, "}")
return strings.Join(s, "")
}
func (this *FileOptions) GoString() string {
if this == nil {
return "nil"
}
s := make([]string, 0, 20)
s = append(s, "&descriptor.FileOptions{")
if this.JavaPackage != nil {
s = append(s, "JavaPackage: "+valueToGoStringDescriptor(this.JavaPackage, "string")+",\n")
}
if this.JavaOuterClassname != nil {
s = append(s, "JavaOuterClassname: "+valueToGoStringDescriptor(this.JavaOuterClassname, "string")+",\n")
}
if this.JavaMultipleFiles != nil {
s = append(s, "JavaMultipleFiles: "+valueToGoStringDescriptor(this.JavaMultipleFiles, "bool")+",\n")
}
if this.JavaGenerateEqualsAndHash != nil {
s = append(s, "JavaGenerateEqualsAndHash: "+valueToGoStringDescriptor(this.JavaGenerateEqualsAndHash, "bool")+",\n")
}
if this.JavaStringCheckUtf8 != nil {
s = append(s, "JavaStringCheckUtf8: "+valueToGoStringDescriptor(this.JavaStringCheckUtf8, "bool")+",\n")
}
if this.OptimizeFor != nil {
s = append(s, "OptimizeFor: "+valueToGoStringDescriptor(this.OptimizeFor, "descriptor.FileOptions_OptimizeMode")+",\n")
}
if this.GoPackage != nil {
s = append(s, "GoPackage: "+valueToGoStringDescriptor(this.GoPackage, "string")+",\n")
}
if this.CcGenericServices != nil {
s = append(s, "CcGenericServices: "+valueToGoStringDescriptor(this.CcGenericServices, "bool")+",\n")
}
if this.JavaGenericServices != nil {
s = append(s, "JavaGenericServices: "+valueToGoStringDescriptor(this.JavaGenericServices, "bool")+",\n")
}
if this.PyGenericServices != nil {
s = append(s, "PyGenericServices: "+valueToGoStringDescriptor(this.PyGenericServices, "bool")+",\n")
}
if this.Deprecated != nil {
s = append(s, "Deprecated: "+valueToGoStringDescriptor(this.Deprecated, "bool")+",\n")
}
if this.CcEnableArenas != nil {
s = append(s, "CcEnableArenas: "+valueToGoStringDescriptor(this.CcEnableArenas, "bool")+",\n")
}
if this.ObjcClassPrefix != nil {
s = append(s, "ObjcClassPrefix: "+valueToGoStringDescriptor(this.ObjcClassPrefix, "string")+",\n")
}
if this.CsharpNamespace != nil {
s = append(s, "CsharpNamespace: "+valueToGoStringDescriptor(this.CsharpNamespace, "string")+",\n")
}
if this.SwiftPrefix != nil {
s = append(s, "SwiftPrefix: "+valueToGoStringDescriptor(this.SwiftPrefix, "string")+",\n")
}
if this.UninterpretedOption != nil {
s = append(s, "UninterpretedOption: "+fmt.Sprintf("%#v", this.UninterpretedOption)+",\n")
}
s = append(s, "XXX_InternalExtensions: "+extensionToGoStringDescriptor(this)+",\n")
if this.XXX_unrecognized != nil {
s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
}
s = append(s, "}")
return strings.Join(s, "")
}
func (this *MessageOptions) GoString() string {
if this == nil {
return "nil"
}
s := make([]string, 0, 9)
s = append(s, "&descriptor.MessageOptions{")
if this.MessageSetWireFormat != nil {
s = append(s, "MessageSetWireFormat: "+valueToGoStringDescriptor(this.MessageSetWireFormat, "bool")+",\n")
}
if this.NoStandardDescriptorAccessor != nil {
s = append(s, "NoStandardDescriptorAccessor: "+valueToGoStringDescriptor(this.NoStandardDescriptorAccessor, "bool")+",\n")
}
if this.Deprecated != nil {
s = append(s, "Deprecated: "+valueToGoStringDescriptor(this.Deprecated, "bool")+",\n")
}
if this.MapEntry != nil {
s = append(s, "MapEntry: "+valueToGoStringDescriptor(this.MapEntry, "bool")+",\n")
}
if this.UninterpretedOption != nil {
s = append(s, "UninterpretedOption: "+fmt.Sprintf("%#v", this.UninterpretedOption)+",\n")
}
s = append(s, "XXX_InternalExtensions: "+extensionToGoStringDescriptor(this)+",\n")
if this.XXX_unrecognized != nil {
s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
}
s = append(s, "}")
return strings.Join(s, "")
}
func (this *FieldOptions) GoString() string {
if this == nil {
return "nil"
}
s := make([]string, 0, 11)
s = append(s, "&descriptor.FieldOptions{")
if this.Ctype != nil {
s = append(s, "Ctype: "+valueToGoStringDescriptor(this.Ctype, "descriptor.FieldOptions_CType")+",\n")
}
if this.Packed != nil {
s = append(s, "Packed: "+valueToGoStringDescriptor(this.Packed, "bool")+",\n")
}
if this.Jstype != nil {
s = append(s, "Jstype: "+valueToGoStringDescriptor(this.Jstype, "descriptor.FieldOptions_JSType")+",\n")
}
if this.Lazy != nil {
s = append(s, "Lazy: "+valueToGoStringDescriptor(this.Lazy, "bool")+",\n")
}
if this.Deprecated != nil {
s = append(s, "Deprecated: "+valueToGoStringDescriptor(this.Deprecated, "bool")+",\n")
}
if this.Weak != nil {
s = append(s, "Weak: "+valueToGoStringDescriptor(this.Weak, "bool")+",\n")
}
if this.UninterpretedOption != nil {
s = append(s, "UninterpretedOption: "+fmt.Sprintf("%#v", this.UninterpretedOption)+",\n")
}
s = append(s, "XXX_InternalExtensions: "+extensionToGoStringDescriptor(this)+",\n")
if this.XXX_unrecognized != nil {
s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
}
s = append(s, "}")
return strings.Join(s, "")
}
func (this *OneofOptions) GoString() string {
if this == nil {
return "nil"
}
s := make([]string, 0, 5)
s = append(s, "&descriptor.OneofOptions{")
if this.UninterpretedOption != nil {
s = append(s, "UninterpretedOption: "+fmt.Sprintf("%#v", this.UninterpretedOption)+",\n")
}
s = append(s, "XXX_InternalExtensions: "+extensionToGoStringDescriptor(this)+",\n")
if this.XXX_unrecognized != nil {
s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
}
s = append(s, "}")
return strings.Join(s, "")
}
func (this *EnumOptions) GoString() string {
if this == nil {
return "nil"
}
s := make([]string, 0, 7)
s = append(s, "&descriptor.EnumOptions{")
if this.AllowAlias != nil {
s = append(s, "AllowAlias: "+valueToGoStringDescriptor(this.AllowAlias, "bool")+",\n")
}
if this.Deprecated != nil {
s = append(s, "Deprecated: "+valueToGoStringDescriptor(this.Deprecated, "bool")+",\n")
}
if this.UninterpretedOption != nil {
s = append(s, "UninterpretedOption: "+fmt.Sprintf("%#v", this.UninterpretedOption)+",\n")
}
s = append(s, "XXX_InternalExtensions: "+extensionToGoStringDescriptor(this)+",\n")
if this.XXX_unrecognized != nil {
s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
}
s = append(s, "}")
return strings.Join(s, "")
}
func (this *EnumValueOptions) GoString() string {
if this == nil {
return "nil"
}
s := make([]string, 0, 6)
s = append(s, "&descriptor.EnumValueOptions{")
if this.Deprecated != nil {
s = append(s, "Deprecated: "+valueToGoStringDescriptor(this.Deprecated, "bool")+",\n")
}
if this.UninterpretedOption != nil {
s = append(s, "UninterpretedOption: "+fmt.Sprintf("%#v", this.UninterpretedOption)+",\n")
}
s = append(s, "XXX_InternalExtensions: "+extensionToGoStringDescriptor(this)+",\n")
if this.XXX_unrecognized != nil {
s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
}
s = append(s, "}")
return strings.Join(s, "")
}
func (this *ServiceOptions) GoString() string {
if this == nil {
return "nil"
}
s := make([]string, 0, 6)
s = append(s, "&descriptor.ServiceOptions{")
if this.Deprecated != nil {
s = append(s, "Deprecated: "+valueToGoStringDescriptor(this.Deprecated, "bool")+",\n")
}
if this.UninterpretedOption != nil {
s = append(s, "UninterpretedOption: "+fmt.Sprintf("%#v", this.UninterpretedOption)+",\n")
}
s = append(s, "XXX_InternalExtensions: "+extensionToGoStringDescriptor(this)+",\n")
if this.XXX_unrecognized != nil {
s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
}
s = append(s, "}")
return strings.Join(s, "")
}
func (this *MethodOptions) GoString() string {
if this == nil {
return "nil"
}
s := make([]string, 0, 7)
s = append(s, "&descriptor.MethodOptions{")
if this.Deprecated != nil {
s = append(s, "Deprecated: "+valueToGoStringDescriptor(this.Deprecated, "bool")+",\n")
}
if this.IdempotencyLevel != nil {
s = append(s, "IdempotencyLevel: "+valueToGoStringDescriptor(this.IdempotencyLevel, "descriptor.MethodOptions_IdempotencyLevel")+",\n")
}
if this.UninterpretedOption != nil {
s = append(s, "UninterpretedOption: "+fmt.Sprintf("%#v", this.UninterpretedOption)+",\n")
}
s = append(s, "XXX_InternalExtensions: "+extensionToGoStringDescriptor(this)+",\n")
if this.XXX_unrecognized != nil {
s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
}
s = append(s, "}")
return strings.Join(s, "")
}
func (this *UninterpretedOption) GoString() string {
if this == nil {
return "nil"
}
s := make([]string, 0, 11)
s = append(s, "&descriptor.UninterpretedOption{")
if this.Name != nil {
s = append(s, "Name: "+fmt.Sprintf("%#v", this.Name)+",\n")
}
if this.IdentifierValue != nil {
s = append(s, "IdentifierValue: "+valueToGoStringDescriptor(this.IdentifierValue, "string")+",\n")
}
if this.PositiveIntValue != nil {
s = append(s, "PositiveIntValue: "+valueToGoStringDescriptor(this.PositiveIntValue, "uint64")+",\n")
}
if this.NegativeIntValue != nil {
s = append(s, "NegativeIntValue: "+valueToGoStringDescriptor(this.NegativeIntValue, "int64")+",\n")
}
if this.DoubleValue != nil {
s = append(s, "DoubleValue: "+valueToGoStringDescriptor(this.DoubleValue, "float64")+",\n")
}
if this.StringValue != nil {
s = append(s, "StringValue: "+valueToGoStringDescriptor(this.StringValue, "byte")+",\n")
}
if this.AggregateValue != nil {
s = append(s, "AggregateValue: "+valueToGoStringDescriptor(this.AggregateValue, "string")+",\n")
}
if this.XXX_unrecognized != nil {
s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
}
s = append(s, "}")
return strings.Join(s, "")
}
func (this *UninterpretedOption_NamePart) GoString() string {
if this == nil {
return "nil"
}
s := make([]string, 0, 6)
s = append(s, "&descriptor.UninterpretedOption_NamePart{")
if this.NamePart != nil {
s = append(s, "NamePart: "+valueToGoStringDescriptor(this.NamePart, "string")+",\n")
}
if this.IsExtension != nil {
s = append(s, "IsExtension: "+valueToGoStringDescriptor(this.IsExtension, "bool")+",\n")
}
if this.XXX_unrecognized != nil {
s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
}
s = append(s, "}")
return strings.Join(s, "")
}
func (this *SourceCodeInfo) GoString() string {
if this == nil {
return "nil"
}
s := make([]string, 0, 5)
s = append(s, "&descriptor.SourceCodeInfo{")
if this.Location != nil {
s = append(s, "Location: "+fmt.Sprintf("%#v", this.Location)+",\n")
}
if this.XXX_unrecognized != nil {
s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
}
s = append(s, "}")
return strings.Join(s, "")
}
func (this *SourceCodeInfo_Location) GoString() string {
if this == nil {
return "nil"
}
s := make([]string, 0, 9)
s = append(s, "&descriptor.SourceCodeInfo_Location{")
if this.Path != nil {
s = append(s, "Path: "+fmt.Sprintf("%#v", this.Path)+",\n")
}
if this.Span != nil {
s = append(s, "Span: "+fmt.Sprintf("%#v", this.Span)+",\n")
}
if this.LeadingComments != nil {
s = append(s, "LeadingComments: "+valueToGoStringDescriptor(this.LeadingComments, "string")+",\n")
}
if this.TrailingComments != nil {
s = append(s, "TrailingComments: "+valueToGoStringDescriptor(this.TrailingComments, "string")+",\n")
}
if this.LeadingDetachedComments != nil {
s = append(s, "LeadingDetachedComments: "+fmt.Sprintf("%#v", this.LeadingDetachedComments)+",\n")
}
if this.XXX_unrecognized != nil {
s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
}
s = append(s, "}")
return strings.Join(s, "")
}
func (this *GeneratedCodeInfo) GoString() string {
if this == nil {
return "nil"
}
s := make([]string, 0, 5)
s = append(s, "&descriptor.GeneratedCodeInfo{")
if this.Annotation != nil {
s = append(s, "Annotation: "+fmt.Sprintf("%#v", this.Annotation)+",\n")
}
if this.XXX_unrecognized != nil {
s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
}
s = append(s, "}")
return strings.Join(s, "")
}
func (this *GeneratedCodeInfo_Annotation) GoString() string {
if this == nil {
return "nil"
}
s := make([]string, 0, 8)
s = append(s, "&descriptor.GeneratedCodeInfo_Annotation{")
if this.Path != nil {
s = append(s, "Path: "+fmt.Sprintf("%#v", this.Path)+",\n")
}
if this.SourceFile != nil {
s = append(s, "SourceFile: "+valueToGoStringDescriptor(this.SourceFile, "string")+",\n")
}
if this.Begin != nil {
s = append(s, "Begin: "+valueToGoStringDescriptor(this.Begin, "int32")+",\n")
}
if this.End != nil {
s = append(s, "End: "+valueToGoStringDescriptor(this.End, "int32")+",\n")
}
if this.XXX_unrecognized != nil {
s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
}
s = append(s, "}")
return strings.Join(s, "")
}
func valueToGoStringDescriptor(v interface{}, typ string) string {
rv := reflect.ValueOf(v)
if rv.IsNil() {
return "nil"
}
pv := reflect.Indirect(rv).Interface()
return fmt.Sprintf("func(v %v) *%v { return &v } ( %#v )", typ, typ, pv)
}
func extensionToGoStringDescriptor(m github_com_gogo_protobuf_proto.Message) string {
e := github_com_gogo_protobuf_proto.GetUnsafeExtensionsMap(m)
if e == nil {
return "nil"
}
s := "proto.NewUnsafeXXX_InternalExtensions(map[int32]proto.Extension{"
keys := make([]int, 0, len(e))
for k := range e {
keys = append(keys, int(k))
}
sort.Ints(keys)
ss := []string{}
for _, k := range keys {
ss = append(ss, strconv.Itoa(k)+": "+e[int32(k)].GoString())
}
s += strings.Join(ss, ",") + "})"
return s
}

View File

@ -0,0 +1,390 @@
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2013, The GoGo Authors. All rights reserved.
// http://github.com/gogo/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.
//
// 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 descriptor
import (
"strings"
)
func (msg *DescriptorProto) GetMapFields() (*FieldDescriptorProto, *FieldDescriptorProto) {
if !msg.GetOptions().GetMapEntry() {
return nil, nil
}
return msg.GetField()[0], msg.GetField()[1]
}
func dotToUnderscore(r rune) rune {
if r == '.' {
return '_'
}
return r
}
func (field *FieldDescriptorProto) WireType() (wire int) {
switch *field.Type {
case FieldDescriptorProto_TYPE_DOUBLE:
return 1
case FieldDescriptorProto_TYPE_FLOAT:
return 5
case FieldDescriptorProto_TYPE_INT64:
return 0
case FieldDescriptorProto_TYPE_UINT64:
return 0
case FieldDescriptorProto_TYPE_INT32:
return 0
case FieldDescriptorProto_TYPE_UINT32:
return 0
case FieldDescriptorProto_TYPE_FIXED64:
return 1
case FieldDescriptorProto_TYPE_FIXED32:
return 5
case FieldDescriptorProto_TYPE_BOOL:
return 0
case FieldDescriptorProto_TYPE_STRING:
return 2
case FieldDescriptorProto_TYPE_GROUP:
return 2
case FieldDescriptorProto_TYPE_MESSAGE:
return 2
case FieldDescriptorProto_TYPE_BYTES:
return 2
case FieldDescriptorProto_TYPE_ENUM:
return 0
case FieldDescriptorProto_TYPE_SFIXED32:
return 5
case FieldDescriptorProto_TYPE_SFIXED64:
return 1
case FieldDescriptorProto_TYPE_SINT32:
return 0
case FieldDescriptorProto_TYPE_SINT64:
return 0
}
panic("unreachable")
}
func (field *FieldDescriptorProto) GetKeyUint64() (x uint64) {
packed := field.IsPacked()
wireType := field.WireType()
fieldNumber := field.GetNumber()
if packed {
wireType = 2
}
x = uint64(uint32(fieldNumber)<<3 | uint32(wireType))
return x
}
func (field *FieldDescriptorProto) GetKey3Uint64() (x uint64) {
packed := field.IsPacked3()
wireType := field.WireType()
fieldNumber := field.GetNumber()
if packed {
wireType = 2
}
x = uint64(uint32(fieldNumber)<<3 | uint32(wireType))
return x
}
func (field *FieldDescriptorProto) GetKey() []byte {
x := field.GetKeyUint64()
i := 0
keybuf := make([]byte, 0)
for i = 0; x > 127; i++ {
keybuf = append(keybuf, 0x80|uint8(x&0x7F))
x >>= 7
}
keybuf = append(keybuf, uint8(x))
return keybuf
}
func (field *FieldDescriptorProto) GetKey3() []byte {
x := field.GetKey3Uint64()
i := 0
keybuf := make([]byte, 0)
for i = 0; x > 127; i++ {
keybuf = append(keybuf, 0x80|uint8(x&0x7F))
x >>= 7
}
keybuf = append(keybuf, uint8(x))
return keybuf
}
func (desc *FileDescriptorSet) GetField(packageName, messageName, fieldName string) *FieldDescriptorProto {
msg := desc.GetMessage(packageName, messageName)
if msg == nil {
return nil
}
for _, field := range msg.GetField() {
if field.GetName() == fieldName {
return field
}
}
return nil
}
func (file *FileDescriptorProto) GetMessage(typeName string) *DescriptorProto {
for _, msg := range file.GetMessageType() {
if msg.GetName() == typeName {
return msg
}
nes := file.GetNestedMessage(msg, strings.TrimPrefix(typeName, msg.GetName()+"."))
if nes != nil {
return nes
}
}
return nil
}
func (file *FileDescriptorProto) GetNestedMessage(msg *DescriptorProto, typeName string) *DescriptorProto {
for _, nes := range msg.GetNestedType() {
if nes.GetName() == typeName {
return nes
}
res := file.GetNestedMessage(nes, strings.TrimPrefix(typeName, nes.GetName()+"."))
if res != nil {
return res
}
}
return nil
}
func (desc *FileDescriptorSet) GetMessage(packageName string, typeName string) *DescriptorProto {
for _, file := range desc.GetFile() {
if strings.Map(dotToUnderscore, file.GetPackage()) != strings.Map(dotToUnderscore, packageName) {
continue
}
for _, msg := range file.GetMessageType() {
if msg.GetName() == typeName {
return msg
}
}
for _, msg := range file.GetMessageType() {
for _, nes := range msg.GetNestedType() {
if nes.GetName() == typeName {
return nes
}
if msg.GetName()+"."+nes.GetName() == typeName {
return nes
}
}
}
}
return nil
}
func (desc *FileDescriptorSet) IsProto3(packageName string, typeName string) bool {
for _, file := range desc.GetFile() {
if strings.Map(dotToUnderscore, file.GetPackage()) != strings.Map(dotToUnderscore, packageName) {
continue
}
for _, msg := range file.GetMessageType() {
if msg.GetName() == typeName {
return file.GetSyntax() == "proto3"
}
}
for _, msg := range file.GetMessageType() {
for _, nes := range msg.GetNestedType() {
if nes.GetName() == typeName {
return file.GetSyntax() == "proto3"
}
if msg.GetName()+"."+nes.GetName() == typeName {
return file.GetSyntax() == "proto3"
}
}
}
}
return false
}
func (msg *DescriptorProto) IsExtendable() bool {
return len(msg.GetExtensionRange()) > 0
}
func (desc *FileDescriptorSet) FindExtension(packageName string, typeName string, fieldName string) (extPackageName string, field *FieldDescriptorProto) {
parent := desc.GetMessage(packageName, typeName)
if parent == nil {
return "", nil
}
if !parent.IsExtendable() {
return "", nil
}
extendee := "." + packageName + "." + typeName
for _, file := range desc.GetFile() {
for _, ext := range file.GetExtension() {
if strings.Map(dotToUnderscore, file.GetPackage()) == strings.Map(dotToUnderscore, packageName) {
if !(ext.GetExtendee() == typeName || ext.GetExtendee() == extendee) {
continue
}
} else {
if ext.GetExtendee() != extendee {
continue
}
}
if ext.GetName() == fieldName {
return file.GetPackage(), ext
}
}
}
return "", nil
}
func (desc *FileDescriptorSet) FindExtensionByFieldNumber(packageName string, typeName string, fieldNum int32) (extPackageName string, field *FieldDescriptorProto) {
parent := desc.GetMessage(packageName, typeName)
if parent == nil {
return "", nil
}
if !parent.IsExtendable() {
return "", nil
}
extendee := "." + packageName + "." + typeName
for _, file := range desc.GetFile() {
for _, ext := range file.GetExtension() {
if strings.Map(dotToUnderscore, file.GetPackage()) == strings.Map(dotToUnderscore, packageName) {
if !(ext.GetExtendee() == typeName || ext.GetExtendee() == extendee) {
continue
}
} else {
if ext.GetExtendee() != extendee {
continue
}
}
if ext.GetNumber() == fieldNum {
return file.GetPackage(), ext
}
}
}
return "", nil
}
func (desc *FileDescriptorSet) FindMessage(packageName string, typeName string, fieldName string) (msgPackageName string, msgName string) {
parent := desc.GetMessage(packageName, typeName)
if parent == nil {
return "", ""
}
field := parent.GetFieldDescriptor(fieldName)
if field == nil {
var extPackageName string
extPackageName, field = desc.FindExtension(packageName, typeName, fieldName)
if field == nil {
return "", ""
}
packageName = extPackageName
}
typeNames := strings.Split(field.GetTypeName(), ".")
if len(typeNames) == 1 {
msg := desc.GetMessage(packageName, typeName)
if msg == nil {
return "", ""
}
return packageName, msg.GetName()
}
if len(typeNames) > 2 {
for i := 1; i < len(typeNames)-1; i++ {
packageName = strings.Join(typeNames[1:len(typeNames)-i], ".")
typeName = strings.Join(typeNames[len(typeNames)-i:], ".")
msg := desc.GetMessage(packageName, typeName)
if msg != nil {
typeNames := strings.Split(msg.GetName(), ".")
if len(typeNames) == 1 {
return packageName, msg.GetName()
}
return strings.Join(typeNames[1:len(typeNames)-1], "."), typeNames[len(typeNames)-1]
}
}
}
return "", ""
}
func (msg *DescriptorProto) GetFieldDescriptor(fieldName string) *FieldDescriptorProto {
for _, field := range msg.GetField() {
if field.GetName() == fieldName {
return field
}
}
return nil
}
func (desc *FileDescriptorSet) GetEnum(packageName string, typeName string) *EnumDescriptorProto {
for _, file := range desc.GetFile() {
if strings.Map(dotToUnderscore, file.GetPackage()) != strings.Map(dotToUnderscore, packageName) {
continue
}
for _, enum := range file.GetEnumType() {
if enum.GetName() == typeName {
return enum
}
}
}
return nil
}
func (f *FieldDescriptorProto) IsEnum() bool {
return *f.Type == FieldDescriptorProto_TYPE_ENUM
}
func (f *FieldDescriptorProto) IsMessage() bool {
return *f.Type == FieldDescriptorProto_TYPE_MESSAGE
}
func (f *FieldDescriptorProto) IsBytes() bool {
return *f.Type == FieldDescriptorProto_TYPE_BYTES
}
func (f *FieldDescriptorProto) IsRepeated() bool {
return f.Label != nil && *f.Label == FieldDescriptorProto_LABEL_REPEATED
}
func (f *FieldDescriptorProto) IsString() bool {
return *f.Type == FieldDescriptorProto_TYPE_STRING
}
func (f *FieldDescriptorProto) IsBool() bool {
return *f.Type == FieldDescriptorProto_TYPE_BOOL
}
func (f *FieldDescriptorProto) IsRequired() bool {
return f.Label != nil && *f.Label == FieldDescriptorProto_LABEL_REQUIRED
}
func (f *FieldDescriptorProto) IsPacked() bool {
return f.Options != nil && f.GetOptions().GetPacked()
}
func (f *FieldDescriptorProto) IsPacked3() bool {
if f.IsRepeated() && f.IsScalar() {
if f.Options == nil || f.GetOptions().Packed == nil {
return true
}
return f.Options != nil && f.GetOptions().GetPacked()
}
return false
}
func (m *DescriptorProto) HasExtension() bool {
return len(m.ExtensionRange) > 0
}

201
vendor/github.com/mesos/mesos-go/LICENSE generated vendored Normal file
View File

@ -0,0 +1,201 @@
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.

13
vendor/github.com/mesos/mesos-go/NOTICE generated vendored Normal file
View File

@ -0,0 +1,13 @@
Copyright 2013-2015, Mesosphere, 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.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,690 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you 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.
syntax = "proto2";
package mesos.agent;
import "github.com/mesos/mesos-go/api/v1/lib/mesos.proto";
import "github.com/gogo/protobuf/gogoproto/gogo.proto";
option go_package = "agent";
option (gogoproto.benchgen_all) = true;
option (gogoproto.enum_stringer_all) = true;
option (gogoproto.equal_all) = true;
option (gogoproto.goproto_enum_prefix_all) = false;
option (gogoproto.goproto_enum_stringer_all) = false;
option (gogoproto.goproto_stringer_all) = false;
option (gogoproto.goproto_unrecognized_all) = false;
option (gogoproto.gostring_all) = true;
option (gogoproto.marshaler_all) = true;
option (gogoproto.populate_all) = true;
option (gogoproto.protosizer_all) = true;
option (gogoproto.stringer_all) = true;
option (gogoproto.testgen_all) = true;
option (gogoproto.unmarshaler_all) = true;
option (gogoproto.verbose_equal_all) = true;
/**
* Calls that can be sent to the v1 agent API.
*
* A call is described using the standard protocol buffer "union"
* trick, see
* https://developers.google.com/protocol-buffers/docs/techniques#union.
*/
message Call {
// If a call of type `Call::FOO` requires additional parameters they can be
// included in the corresponding `Call::Foo` message. Similarly, if a call
// receives a synchronous response it will be returned as a `Response`
// message of type `Response::FOO`; see `Call::LaunchNestedContainerSession`
// and `Call::AttachContainerOutput` for exceptions.
enum Type {
UNKNOWN = 0;
GET_HEALTH = 1; // Retrieves the agent's health status.
GET_FLAGS = 2; // Retrieves the agent's flag configuration.
GET_VERSION = 3; // Retrieves the agent's version information.
GET_METRICS = 4; // See 'GetMetrics' below.
GET_LOGGING_LEVEL = 5; // Retrieves the agent's logging level.
SET_LOGGING_LEVEL = 6; // See 'SetLoggingLevel' below.
LIST_FILES = 7;
READ_FILE = 8; // See 'ReadFile' below.
GET_STATE = 9;
GET_CONTAINERS = 10;
// Retrieves the information about known frameworks.
GET_FRAMEWORKS = 11;
// Retrieves the information about known executors.
GET_EXECUTORS = 12;
// Retrieves the information about known tasks.
GET_TASKS = 13;
// Retrieves the agent information.
GET_AGENT = 20;
// Retrieves the information about known resource providers.
GET_RESOURCE_PROVIDERS = 26;
// Calls for managing nested containers underneath an executor's container.
// Some of these calls are deprecated in favor of the calls
// for both standalone or nested containers further below.
LAUNCH_NESTED_CONTAINER = 14 [deprecated = true];
WAIT_NESTED_CONTAINER = 15 [deprecated = true];
KILL_NESTED_CONTAINER = 16 [deprecated = true];
REMOVE_NESTED_CONTAINER = 21 [deprecated = true];
// See 'LaunchNestedContainerSession' below.
LAUNCH_NESTED_CONTAINER_SESSION = 17;
ATTACH_CONTAINER_INPUT = 18; // See 'AttachContainerInput' below.
ATTACH_CONTAINER_OUTPUT = 19; // see 'AttachContainerOutput' below.
// Calls for managing standalone containers
// or containers nested underneath another container.
LAUNCH_CONTAINER = 22; // See 'LaunchContainer' below.
WAIT_CONTAINER = 23; // See 'WaitContainer' below.
KILL_CONTAINER = 24; // See 'KillContainer' below.
REMOVE_CONTAINER = 25; // See 'RemoveContainer' below.
ADD_RESOURCE_PROVIDER_CONFIG = 27; // See 'AddResourceProviderConfig' below. // NOLINT
UPDATE_RESOURCE_PROVIDER_CONFIG = 28; // See 'UpdateResourceProviderConfig' below. // NOLINT
REMOVE_RESOURCE_PROVIDER_CONFIG = 29; // See 'RemoveResourceProviderConfig' below. // NOLINT
// Prune unused container images.
PRUNE_IMAGES = 30;
option (gogoproto.goproto_enum_prefix) = true;
}
// Provides a snapshot of the current metrics tracked by the agent.
message GetMetrics {
// If set, `timeout` would be used to determines the maximum amount of time
// the API will take to respond. If the timeout is exceeded, some metrics
// may not be included in the response.
optional DurationInfo timeout = 1;
}
// Sets the logging verbosity level for a specified duration. Mesos uses
// [glog](https://github.com/google/glog) for logging. The library only uses
// verbose logging which means nothing will be output unless the verbosity
// level is set (by default it's 0, libprocess uses levels 1, 2, and 3).
message SetLoggingLevel {
// The verbosity level.
required uint32 level = 1 [(gogoproto.nullable) = false];
// The duration to keep verbosity level toggled. After this duration, the
// verbosity level of log would revert to the original level.
required DurationInfo duration = 2 [(gogoproto.nullable) = false];
}
// Provides the file listing for a directory.
message ListFiles {
required string path = 1 [(gogoproto.nullable) = false];
}
// Reads data from a file.
message ReadFile {
// The path of file.
required string path = 1 [(gogoproto.nullable) = false];
// Initial offset in file to start reading from.
required uint64 offset = 2 [(gogoproto.nullable) = false];
// The maximum number of bytes to read. The read length is capped at 16
// memory pages.
optional uint64 length = 3;
}
// Lists active containers on the agent.
message GetContainers {
optional bool show_nested = 1;
optional bool show_standalone = 2;
}
// Deprecated in favor of `LaunchContainer`.
message LaunchNestedContainer {
required ContainerID container_id = 1 [(gogoproto.customname) = "ContainerID", (gogoproto.nullable) = false];
optional CommandInfo command = 2;
optional ContainerInfo container = 3;
}
// Deprecated in favor of `WaitContainer`.
message WaitNestedContainer {
required ContainerID container_id = 1 [(gogoproto.customname) = "ContainerID", (gogoproto.nullable) = false];
}
// Deprecated in favor of `KillContainer`.
message KillNestedContainer {
required ContainerID container_id = 1 [(gogoproto.customname) = "ContainerID", (gogoproto.nullable) = false];
optional int32 signal = 2;
}
// Deprecated in favor of `RemoveContainer`.
message RemoveNestedContainer {
required ContainerID container_id = 1 [(gogoproto.customname) = "ContainerID", (gogoproto.nullable) = false];
}
// Launches a nested container within an executor's tree of containers.
// The differences between this call and `LaunchNestedContainer` are:
// 1) The container's life-cycle is tied to the lifetime of the
// connection used to make this call, i.e., if the connection ever
// breaks, the container will be destroyed.
// 2) The nested container shares the same namespaces and cgroups as
// its parent container.
// 3) Results in a streaming response of type `ProcessIO`. So the call
// needs to be made on a persistent connection.
message LaunchNestedContainerSession {
required ContainerID container_id = 1 [(gogoproto.customname) = "ContainerID", (gogoproto.nullable) = false];
optional CommandInfo command = 2;
optional ContainerInfo container = 3;
}
// Attaches the caller to the STDIN of the entry point of the container.
// Clients can use this to stream input data to a container.
// Note that this call needs to be made on a persistent connection by
// streaming a CONTAINER_ID message followed by one or more PROCESS_IO
// messages.
message AttachContainerInput {
enum Type {
UNKNOWN = 0;
CONTAINER_ID = 1;
PROCESS_IO = 2;
option (gogoproto.goproto_enum_prefix) = true;
}
optional Type type = 1 [(gogoproto.nullable) = false];
optional ContainerID container_id = 2 [(gogoproto.customname) = "ContainerID"];
optional ProcessIO process_io = 3 [(gogoproto.customname) = "ProcessIO"];
}
// Attaches the caller to the STDOUT and STDERR of the entrypoint of
// the container. Clients can use this to stream output/error from the
// container. This call will result in a streaming response of `ProcessIO`;
// so this call needs to be made on a persistent connection.
message AttachContainerOutput {
required ContainerID container_id = 1 [(gogoproto.customname) = "ContainerID", (gogoproto.nullable) = false];
}
// Launches a either a "standalone" container on this agent
// or a nested container within another tree of containers.
//
// A standalone container is launched by specifying a ContainerID
// with no parent. Standalone containers bypass the normal offer cycle
// between the master and agent. Unlike other containers, a standalone
// container does not have an executor or any tasks. This means the
// standalone container does not report back to Mesos or any framework
// and must be supervised separately.
//
// A nested container is launched by specifying a ContainerID with
// another existing container (including standalone containers)
// as the parent.
//
// Returns 200 OK if the new container launch succeeds.
// Returns 202 Accepted if the requested ContainerID is already in use
// by a standalone or nested container.
// Returns 400 Bad Request if the container launch fails.
message LaunchContainer {
// NOTE: Some characters cannot be used in the ID. All characters
// must be valid filesystem path characters. In addition, '/' and '.'
// are reserved.
required ContainerID container_id = 1 [(gogoproto.nullable) = false, (gogoproto.customname) = "ContainerID"];
optional CommandInfo command = 2;
// NOTE: Nested containers may not specify resources and instead
// share resources with its parent container.
//
// TODO(josephw): These resources are purely used for isolation
// and are not accounted for by the Mesos master (if connected).
// It is the caller's responsibility to ensure that resources are
// not overcommitted (e.g. CPU and memory) or conflicting (e.g. ports
// and volumes). Once there is support for preempting tasks and a
// way to update the resources advertised by the agent, these standalone
// container resources should be accounted for by the master.
repeated Resource resources = 3 [(gogoproto.nullable) = false];
optional ContainerInfo container = 4;
}
// Waits for the standalone or nested container to terminate
// and returns the exit status.
//
// Returns 200 OK if and when the container exits.
// Returns 404 Not Found if the container does not exist.
message WaitContainer {
required ContainerID container_id = 1 [(gogoproto.nullable) = false, (gogoproto.customname) = "ContainerID"];
}
// Kills the standalone or nested container. The signal to be sent
// to the container can be specified in the 'signal' field.
//
// Returns 200 OK if the signal is sent successfully.
// Returns 404 Not Found if the container does not exist.
message KillContainer {
required ContainerID container_id = 1 [(gogoproto.nullable) = false, (gogoproto.customname) = "ContainerID"];
// Defaults to SIGKILL.
optional int32 signal = 2;
}
// Removes a container's artifacts (runtime and sandbox directories).
//
// For nested containers, it is important to use this call if multiple
// nested containers are launched under the same parent container, because
// garbage collection only takes place at the parent container. Artifacts
// belonging to nested containers will not be garbage collected while
// the parent container is running.
//
// TODO(josephw): A standalone container's runtime directory is currently
// garbage collected as soon as the container exits. To allow the user to
// retrieve the exit status reliably, the runtime directory cannot be
// garbage collected immediately. Instead, the user will eventually be
// required to make this call after the standalone container has exited.
// Also, a standalone container's sandbox directory is currently not
// garbage collected and is only deleted via this call.
//
// Returns 200 OK if the removal is successful or if the parent container
// (for nested containers) does not exist.
// Returns 500 Internal Server Error if anything goes wrong, including
// if the container is still running or does not exist.
//
// TODO(josephw): Consider returning a 400 Bad Request instead of 500
// Internal Server Error when the user tries to remove a running or
// nonexistent nested container.
message RemoveContainer {
required ContainerID container_id = 1 [(gogoproto.nullable) = false, (gogoproto.customname) = "ContainerID"];
}
// Adds a new resource provider config file.
//
// The content of the `info` field will be written into a new config file in
// the resource provider config directory, and a new resource provider will be
// launched asynchronously based on the config. Callers must not set the
// `info.id` field. This call is idempotent, so if a config file identical to
// the content of the `info` field already exists, this call will return
// without launching a resource provider. Note that if a config file is
// placed into the resource provider config directory out-of-band after the
// agent starts up, it will not be checked against this call.
//
// Returns 200 OK if a new config file is created, or an identical config file
// exists.
// Returns 400 Bad Request if `info` is not well-formed.
// Returns 403 Forbidden if the call is not authorized.
// Returns 409 Conflict if another config file that describes a
// resource provider of the same type and name exists, but the content is
// not identical.
// Returns 500 Internal Server Error if anything goes wrong.
message AddResourceProviderConfig {
required ResourceProviderInfo info = 1 [(gogoproto.nullable) = false];
}
// Updates an existing resource provider config file.
//
// The content of the `info` field will be written into an existing config
// file that describes a resource provider of the specified type and name in
// the resource provider config directory, and the corresponding resource
// provider will be relaunched asynchronously to reflect the changes in the
// config. Callers must not set the `info.id` field. This call is idempotent,
// so if there is no change in the config, this call will return without
// relaunching the resource provider. Note that if a config file is placed
// into the resource provider config directory out-of-band after the agent
// starts up, it will not be checked against this call.
//
// Returns 200 OK if an existing config file is updated, or there is no change
// in the config file.
// Returns 400 Bad Request if `info` is not well-formed.
// Returns 403 Forbidden if the call is not authorized.
// Returns 404 Not Found if no config file describes a resource
// provider of the same type and name exists.
// Returns 500 Internal Server Error if anything goes wrong.
message UpdateResourceProviderConfig {
required ResourceProviderInfo info = 1 [(gogoproto.nullable) = false];
}
// Removes a config file from the resource provider config directory.
//
// The config file that describes the resource provider of the specified type
// and name will be removed, and the corresponding resource provider will be
// terminated asynchronously. This call is idempotent, so if no matching
// config file exists, this call will return without terminating any resource
// provider. Note that if a config file is placed into the resource provider
// config directory out-of-band after the agent starts up, it will not be
// checked against this call.
//
// Returns 200 OK if the config file is removed, or no matching config file
// exists.
// Returns 403 Forbidden if the call is not authorized.
// Returns 500 Internal Server Error if anything goes wrong.
message RemoveResourceProviderConfig {
required string type = 1 [(gogoproto.nullable) = false];
required string name = 2 [(gogoproto.nullable) = false];
}
// Prune unused container images from image store.
//
// Images and layers referenced by active containers as well as
// image references specified in `excluded_images` will not be pruned.
message PruneImages {
repeated Image excluded_images = 1 [(gogoproto.nullable) = false];
}
optional Type type = 1 [(gogoproto.nullable) = false];
optional GetMetrics get_metrics = 2;
optional SetLoggingLevel set_logging_level = 3;
optional ListFiles list_files = 4;
optional ReadFile read_file = 5;
optional GetContainers get_containers = 20;
optional LaunchNestedContainer launch_nested_container = 6
[deprecated = true];
optional WaitNestedContainer wait_nested_container = 7 [deprecated = true];
optional KillNestedContainer kill_nested_container = 8 [deprecated = true];
optional RemoveNestedContainer remove_nested_container = 12
[deprecated = true];
optional LaunchNestedContainerSession launch_nested_container_session = 9;
optional AttachContainerInput attach_container_input = 10;
optional AttachContainerOutput attach_container_output = 11;
optional LaunchContainer launch_container = 13;
optional WaitContainer wait_container = 14;
optional KillContainer kill_container = 15;
optional RemoveContainer remove_container = 16;
optional AddResourceProviderConfig add_resource_provider_config = 17;
optional UpdateResourceProviderConfig update_resource_provider_config = 18;
optional RemoveResourceProviderConfig remove_resource_provider_config = 19;
optional PruneImages prune_images = 21;
}
/**
* Synchronous responses for all calls made to the v1 agent API.
*/
message Response {
// Each of the responses of type `FOO` corresponds to `Foo` message below.
enum Type {
UNKNOWN = 0;
GET_HEALTH = 1; // See 'GetHealth' below.
GET_FLAGS = 2; // See 'GetFlags' below.
GET_VERSION = 3; // See 'GetVersion' below.
GET_METRICS = 4; // See 'GetMetrics' below.
GET_LOGGING_LEVEL = 5; // See 'GetLoggingLevel' below.
LIST_FILES = 6;
READ_FILE = 7; // See 'ReadFile' below.
GET_STATE = 8;
GET_CONTAINERS = 9;
GET_FRAMEWORKS = 10; // See 'GetFrameworks' below.
GET_EXECUTORS = 11; // See 'GetExecutors' below.
GET_TASKS = 12; // See 'GetTasks' below.
GET_AGENT = 14; // See 'GetAgent' below.
GET_RESOURCE_PROVIDERS = 16; // See 'GetResourceProviders' below.
WAIT_NESTED_CONTAINER = 13 [deprecated = true];
WAIT_CONTAINER = 15; // See 'WaitContainer' below.
option (gogoproto.goproto_enum_prefix) = true;
}
// `healthy` would be true if the agent is healthy. Delayed responses are also
// indicative of the poor health of the agent.
message GetHealth {
required bool healthy = 1 [(gogoproto.nullable) = false];
}
// Contains the flag configuration of the agent.
message GetFlags {
repeated Flag flags = 1 [(gogoproto.nullable) = false];
}
// Contains the version information of the agent.
message GetVersion {
required VersionInfo version_info = 1 [(gogoproto.nullable) = false];
}
// Contains a snapshot of the current metrics.
message GetMetrics {
repeated Metric metrics = 1 [(gogoproto.nullable) = false];
}
// Contains the logging level of the agent.
message GetLoggingLevel {
required uint32 level = 1 [(gogoproto.nullable) = false];
}
// Contains the file listing(similar to `ls -l`) for a directory.
message ListFiles {
repeated FileInfo file_infos = 1 [(gogoproto.nullable) = false];
}
// Contains the file data.
message ReadFile {
// The size of file (in bytes).
required uint64 size = 1 [(gogoproto.nullable) = false];
required bytes data = 2;
}
// Contains full state of the agent i.e. information about the tasks,
// frameworks and executors running in the cluster.
message GetState {
optional GetTasks get_tasks = 1;
optional GetExecutors get_executors = 2;
optional GetFrameworks get_frameworks = 3;
}
// Information about containers running on this agent. It contains
// ContainerStatus and ResourceStatistics along with some metadata
// of the containers.
message GetContainers {
message Container {
optional FrameworkID framework_id = 1 [(gogoproto.customname) = "FrameworkID"];
optional ExecutorID executor_id = 2 [(gogoproto.customname) = "ExecutorID"];
optional string executor_name = 3;
required ContainerID container_id = 4 [(gogoproto.customname) = "ContainerID", (gogoproto.nullable) = false];
optional ContainerStatus container_status = 5;
optional ResourceStatistics resource_statistics = 6;
}
repeated Container containers = 1 [(gogoproto.nullable) = false];
}
// Information about all the frameworks known to the agent at the current
// time.
message GetFrameworks {
message Framework {
required FrameworkInfo framework_info = 1 [(gogoproto.nullable) = false];
}
repeated Framework frameworks = 1 [(gogoproto.nullable) = false];
repeated Framework completed_frameworks = 2 [(gogoproto.nullable) = false];
}
// Lists information about all the executors known to the agent at the
// current time.
message GetExecutors {
message Executor {
required ExecutorInfo executor_info = 1 [(gogoproto.nullable) = false];
}
repeated Executor executors = 1 [(gogoproto.nullable) = false];
repeated Executor completed_executors = 2 [(gogoproto.nullable) = false];
}
// Lists information about all the tasks known to the agent at the current
// time.
message GetTasks {
// Tasks that are pending in the agent's queue before an executor is
// launched.
repeated Task pending_tasks = 1 [(gogoproto.nullable) = false];
// Tasks that are enqueued for a launched executor that has not yet
// registered.
repeated Task queued_tasks = 2 [(gogoproto.nullable) = false];
// Tasks that are running.
repeated Task launched_tasks = 3 [(gogoproto.nullable) = false];
// Tasks that are terminated but pending updates.
repeated Task terminated_tasks = 4 [(gogoproto.nullable) = false];
// Tasks that are terminated and updates acked.
repeated Task completed_tasks = 5 [(gogoproto.nullable) = false];
}
// Contains the agent's information.
message GetAgent {
optional AgentInfo agent_info = 1;
}
// Lists information about all resource providers known to the agent
// at the current time.
message GetResourceProviders {
message ResourceProvider {
required ResourceProviderInfo resource_provider_info = 1 [(gogoproto.nullable) = false];
}
repeated ResourceProvider resource_providers = 1 [(gogoproto.nullable) = false];
}
// Returns termination information about the nested container.
message WaitNestedContainer {
// Wait status of the lead process in the container. Note that this
// is the return value of `wait(2)`, so callers must use the `wait(2)`
// family of macros to extract whether the process exited cleanly and
// what the exit code was.
optional int32 exit_status = 1;
// The `state` and `reason` fields may be populated if the Mesos agent
// terminates the container. In the absence of any special knowledge,
// executors should propagate this information via the `status` field
// of an `Update` call for the corresponding TaskID.
optional TaskState state = 2;
optional TaskStatus.Reason reason = 3;
// This field will be populated if the task was terminated due to
// a resource limitation.
optional TaskResourceLimitation limitation = 4;
optional string message = 5;
}
// Returns termination information about the standalone or nested container.
message WaitContainer {
// Wait status of the lead process in the container. Note that this
// is the return value of `wait(2)`, so callers must use the `wait(2)`
// family of macros to extract whether the process exited cleanly and
// what the exit code was.
optional int32 exit_status = 1;
// The `state` and `reason` fields may be populated if the Mesos agent
// terminates the container. In the absence of any special knowledge,
// executors should propagate this information via the `status` field
// of an `Update` call for the corresponding TaskID.
optional TaskState state = 2;
optional TaskStatus.Reason reason = 3;
// This field will be populated if the task was terminated due to
// a resource limitation.
optional TaskResourceLimitation limitation = 4;
optional string message = 5;
}
optional Type type = 1 [(gogoproto.nullable) = false];
optional GetHealth get_health = 2;
optional GetFlags get_flags = 3;
optional GetVersion get_version = 4;
optional GetMetrics get_metrics = 5;
optional GetLoggingLevel get_logging_level = 6;
optional ListFiles list_files = 7;
optional ReadFile read_file = 8;
optional GetState get_state = 9;
optional GetContainers get_containers = 10;
optional GetFrameworks get_frameworks = 11;
optional GetExecutors get_executors = 12;
optional GetTasks get_tasks = 13;
optional GetAgent get_agent = 15;
optional GetResourceProviders get_resource_providers = 17;
optional WaitNestedContainer wait_nested_container = 14;
optional WaitContainer wait_container = 16;
}
/**
* Streaming response to `Call::LAUNCH_NESTED_CONTAINER_SESSION` and
* `Call::ATTACH_CONTAINER_OUTPUT`.
*
* This message is also used to stream request data for
* `Call::ATTACH_CONTAINER_INPUT`.
*/
message ProcessIO {
enum Type {
UNKNOWN = 0;
DATA = 1;
CONTROL = 2;
option (gogoproto.goproto_enum_prefix) = true;
}
message Data {
enum Type {
UNKNOWN = 0;
STDIN = 1;
STDOUT = 2;
STDERR = 3;
option (gogoproto.goproto_enum_prefix) = true;
}
optional Type type = 1 [(gogoproto.nullable) = false];
optional bytes data = 2;
}
message Control {
enum Type {
UNKNOWN = 0;
TTY_INFO = 1;
HEARTBEAT = 2;
option (gogoproto.goproto_enum_prefix) = true;
}
message Heartbeat {
optional DurationInfo interval = 1;
}
optional Type type = 1 [(gogoproto.nullable) = false];
optional TTYInfo tty_info = 2 [(gogoproto.customname) = "TTYInfo"];
optional Heartbeat heartbeat = 3;
}
optional Type type = 1 [(gogoproto.nullable) = false];
optional Data data = 2;
optional Control control = 3;
}

View File

@ -0,0 +1,256 @@
package calls
import (
"time"
"github.com/mesos/mesos-go/api/v1/lib"
"github.com/mesos/mesos-go/api/v1/lib/agent"
)
func GetHealth() *agent.Call { return &agent.Call{Type: agent.Call_GET_HEALTH} }
func GetFlags() *agent.Call { return &agent.Call{Type: agent.Call_GET_FLAGS} }
func GetVersion() *agent.Call { return &agent.Call{Type: agent.Call_GET_VERSION} }
func GetMetrics(d *time.Duration) (call *agent.Call) {
call = &agent.Call{
Type: agent.Call_GET_METRICS,
GetMetrics: &agent.Call_GetMetrics{},
}
if d != nil {
call.GetMetrics.Timeout = &mesos.DurationInfo{
Nanoseconds: d.Nanoseconds(),
}
}
return
}
func GetLoggingLevel() *agent.Call { return &agent.Call{Type: agent.Call_GET_LOGGING_LEVEL} }
func SetLoggingLevel(level uint32, d time.Duration) *agent.Call {
return &agent.Call{
Type: agent.Call_SET_LOGGING_LEVEL,
SetLoggingLevel: &agent.Call_SetLoggingLevel{
Duration: mesos.DurationInfo{Nanoseconds: d.Nanoseconds()},
Level: level,
},
}
}
func ListFiles(path string) *agent.Call {
return &agent.Call{
Type: agent.Call_LIST_FILES,
ListFiles: &agent.Call_ListFiles{
Path: path,
},
}
}
func ReadFile(path string, offset uint64) *agent.Call {
return &agent.Call{
Type: agent.Call_READ_FILE,
ReadFile: &agent.Call_ReadFile{
Path: path,
Offset: offset,
},
}
}
func ReadFileWithLength(path string, offset, length uint64) (call *agent.Call) {
call = ReadFile(path, offset)
call.ReadFile.Length = &length
return
}
func GetState() *agent.Call { return &agent.Call{Type: agent.Call_GET_STATE} }
func GetContainers() *agent.Call { return &agent.Call{Type: agent.Call_GET_CONTAINERS} }
func GetFrameworks() *agent.Call { return &agent.Call{Type: agent.Call_GET_FRAMEWORKS} }
func GetExecutors() *agent.Call { return &agent.Call{Type: agent.Call_GET_EXECUTORS} }
func GetTasks() *agent.Call { return &agent.Call{Type: agent.Call_GET_TASKS} }
func GetAgent() *agent.Call { return &agent.Call{Type: agent.Call_GET_AGENT} }
func GetResourceProviders() *agent.Call { return &agent.Call{Type: agent.Call_GET_RESOURCE_PROVIDERS} }
func LaunchNestedContainer(cid mesos.ContainerID, cmd *mesos.CommandInfo, ci *mesos.ContainerInfo) *agent.Call {
return &agent.Call{
Type: agent.Call_LAUNCH_NESTED_CONTAINER,
LaunchNestedContainer: &agent.Call_LaunchNestedContainer{
ContainerID: cid,
Command: cmd,
Container: ci,
},
}
}
func LaunchContainer(cid mesos.ContainerID, cmd *mesos.CommandInfo, ci *mesos.ContainerInfo, r []mesos.Resource) *agent.Call {
return &agent.Call{
Type: agent.Call_LAUNCH_CONTAINER,
LaunchContainer: &agent.Call_LaunchContainer{
ContainerID: cid,
Command: cmd,
Container: ci,
Resources: r,
},
}
}
func WaitNestedContainer(cid mesos.ContainerID) *agent.Call {
return &agent.Call{
Type: agent.Call_WAIT_NESTED_CONTAINER,
WaitNestedContainer: &agent.Call_WaitNestedContainer{
ContainerID: cid,
},
}
}
func WaitContainer(cid mesos.ContainerID) *agent.Call {
return &agent.Call{
Type: agent.Call_WAIT_CONTAINER,
WaitContainer: &agent.Call_WaitContainer{
ContainerID: cid,
},
}
}
func KillNestedContainer(cid mesos.ContainerID) *agent.Call {
return &agent.Call{
Type: agent.Call_KILL_NESTED_CONTAINER,
KillNestedContainer: &agent.Call_KillNestedContainer{
ContainerID: cid,
},
}
}
func KillContainer(cid mesos.ContainerID) *agent.Call {
return &agent.Call{
Type: agent.Call_KILL_CONTAINER,
KillContainer: &agent.Call_KillContainer{
ContainerID: cid,
},
}
}
func RemoveNestedContainer(cid mesos.ContainerID) *agent.Call {
return &agent.Call{
Type: agent.Call_REMOVE_NESTED_CONTAINER,
RemoveNestedContainer: &agent.Call_RemoveNestedContainer{
ContainerID: cid,
},
}
}
func RemoveContainer(cid mesos.ContainerID) *agent.Call {
return &agent.Call{
Type: agent.Call_REMOVE_CONTAINER,
RemoveContainer: &agent.Call_RemoveContainer{
ContainerID: cid,
},
}
}
func LaunchNestedContainerSession(cid mesos.ContainerID, cmd *mesos.CommandInfo, ci *mesos.ContainerInfo) *agent.Call {
return &agent.Call{
Type: agent.Call_LAUNCH_NESTED_CONTAINER_SESSION,
LaunchNestedContainerSession: &agent.Call_LaunchNestedContainerSession{
ContainerID: cid,
Command: cmd,
Container: ci,
},
}
}
func AttachContainerOutput(cid mesos.ContainerID) *agent.Call {
return &agent.Call{
Type: agent.Call_ATTACH_CONTAINER_OUTPUT,
AttachContainerOutput: &agent.Call_AttachContainerOutput{
ContainerID: cid,
},
}
}
// AttachContainerInput returns a Call that is used to initiate attachment to a container's stdin.
// Callers should first send this Call followed by one or more AttachContainerInputXxx calls.
func AttachContainerInput(cid mesos.ContainerID) *agent.Call {
return &agent.Call{
Type: agent.Call_ATTACH_CONTAINER_INPUT,
AttachContainerInput: &agent.Call_AttachContainerInput{
Type: agent.Call_AttachContainerInput_CONTAINER_ID,
ContainerID: &cid,
},
}
}
func AttachContainerInputData(data []byte) *agent.Call {
return &agent.Call{
Type: agent.Call_ATTACH_CONTAINER_INPUT,
AttachContainerInput: &agent.Call_AttachContainerInput{
Type: agent.Call_AttachContainerInput_PROCESS_IO,
ProcessIO: &agent.ProcessIO{
Type: agent.ProcessIO_DATA,
Data: &agent.ProcessIO_Data{
Type: agent.ProcessIO_Data_STDIN,
Data: data,
},
},
},
}
}
func AttachContainerInputTTY(t *mesos.TTYInfo) *agent.Call {
return &agent.Call{
Type: agent.Call_ATTACH_CONTAINER_INPUT,
AttachContainerInput: &agent.Call_AttachContainerInput{
Type: agent.Call_AttachContainerInput_PROCESS_IO,
ProcessIO: &agent.ProcessIO{
Type: agent.ProcessIO_CONTROL,
Control: &agent.ProcessIO_Control{
Type: agent.ProcessIO_Control_TTY_INFO,
TTYInfo: t,
},
},
},
}
}
func AddResourceProviderConfig(rpi mesos.ResourceProviderInfo) *agent.Call {
return &agent.Call{
Type: agent.Call_ADD_RESOURCE_PROVIDER_CONFIG,
AddResourceProviderConfig: &agent.Call_AddResourceProviderConfig{
Info: rpi,
},
}
}
func UpdateResourceProviderConfig(rpi mesos.ResourceProviderInfo) *agent.Call {
return &agent.Call{
Type: agent.Call_UPDATE_RESOURCE_PROVIDER_CONFIG,
UpdateResourceProviderConfig: &agent.Call_UpdateResourceProviderConfig{
Info: rpi,
},
}
}
func RemoveResourceProviderConfig(typ, name string) *agent.Call {
return &agent.Call{
Type: agent.Call_REMOVE_RESOURCE_PROVIDER_CONFIG,
RemoveResourceProviderConfig: &agent.Call_RemoveResourceProviderConfig{
Type: typ,
Name: name,
},
}
}
func PruneImages(excluded []mesos.Image) *agent.Call {
return &agent.Call{
Type: agent.Call_PRUNE_IMAGES,
PruneImages: &agent.Call_PruneImages{
ExcludedImages: excluded,
},
}
}

View File

@ -0,0 +1,129 @@
package calls
// go generate -import github.com/mesos/mesos-go/api/v1/lib/agent -type C:agent.Call
// GENERATED CODE FOLLOWS; DO NOT EDIT.
import (
"context"
"github.com/mesos/mesos-go/api/v1/lib"
"github.com/mesos/mesos-go/api/v1/lib/encoding"
"github.com/mesos/mesos-go/api/v1/lib/agent"
)
type (
// Request generates a Call that's sent to a Mesos agent. Subsequent invocations are expected to
// yield equivalent calls. Intended for use w/ non-streaming requests to an agent.
Request interface {
Call() *agent.Call
}
// RequestFunc is the functional adaptation of Request.
RequestFunc func() *agent.Call
// RequestStreaming generates a Call that's send to a Mesos agent. Subsequent invocations MAY generate
// different Call objects. No more Call objects are expected once a nil is returned to signal the end of
// of the request stream.
RequestStreaming interface {
Request
IsStreaming()
}
// RequestStreamingFunc is the functional adaptation of RequestStreaming.
RequestStreamingFunc func() *agent.Call
// Send issues a Request to a Mesos agent and properly manages Call-specific mechanics.
Sender interface {
Send(context.Context, Request) (mesos.Response, error)
}
// SenderFunc is the functional adaptation of the Sender interface
SenderFunc func(context.Context, Request) (mesos.Response, error)
)
func (f RequestFunc) Call() *agent.Call { return f() }
func (f RequestFunc) Marshaler() encoding.Marshaler {
// avoid returning (*agent.Call)(nil) for interface type
if call := f(); call != nil {
return call
}
return nil
}
func (f RequestStreamingFunc) Push(c ...*agent.Call) RequestStreamingFunc { return Push(f, c...) }
func (f RequestStreamingFunc) Marshaler() encoding.Marshaler {
// avoid returning (*agent.Call)(nil) for interface type
if call := f(); call != nil {
return call
}
return nil
}
func (f RequestStreamingFunc) IsStreaming() {}
func (f RequestStreamingFunc) Call() *agent.Call { return f() }
// Push prepends one or more calls onto a request stream. If no calls are given then the original stream is returned.
func Push(r RequestStreaming, c ...*agent.Call) RequestStreamingFunc {
return func() *agent.Call {
if len(c) == 0 {
return r.Call()
}
head := c[0]
c = c[1:]
return head
}
}
// Empty generates a stream that always returns nil.
func Empty() RequestStreamingFunc { return func() *agent.Call { return nil } }
var (
_ = Request(RequestFunc(nil))
_ = RequestStreaming(RequestStreamingFunc(nil))
_ = Sender(SenderFunc(nil))
)
// NonStreaming returns a RequestFunc that always generates the same Call.
func NonStreaming(c *agent.Call) RequestFunc { return func() *agent.Call { return c } }
// FromChan returns a streaming request that fetches calls from the given channel until it closes.
// If a nil chan is specified then the returned func will always generate nil.
func FromChan(ch <-chan *agent.Call) RequestStreamingFunc {
if ch == nil {
// avoid blocking forever if we're handed a nil chan
return func() *agent.Call { return nil }
}
return func() *agent.Call {
if m, ok := <-ch; ok {
return m
}
return nil
}
}
// Send implements the Sender interface for SenderFunc
func (f SenderFunc) Send(ctx context.Context, r Request) (mesos.Response, error) {
return f(ctx, r)
}
// IgnoreResponse generates a sender that closes any non-nil response received by Mesos.
func IgnoreResponse(s Sender) SenderFunc {
return func(ctx context.Context, r Request) (mesos.Response, error) {
resp, err := s.Send(ctx, r)
if resp != nil {
resp.Close()
}
return nil, err
}
}
// SendNoData is a convenience func that executes the given Call using the provided Sender
// and always drops the response data.
func SendNoData(ctx context.Context, sender Sender, r Request) (err error) {
_, err = IgnoreResponse(sender).Send(ctx, r)
return
}

View File

@ -0,0 +1,3 @@
package calls
//go:generate go run ../../extras/gen/sender.go ../../extras/gen/gen.go -import github.com/mesos/mesos-go/api/v1/lib/agent -type C:agent.Call

71
vendor/github.com/mesos/mesos-go/api/v1/lib/client.go generated vendored Normal file
View File

@ -0,0 +1,71 @@
package mesos
// DEPRECATED in favor of github.com/mesos/mesos-go/api/v1/lib/client
import (
"io"
"github.com/mesos/mesos-go/api/v1/lib/encoding"
)
// A Client represents a Mesos API client which can send Calls and return
// a streaming Decoder from which callers can read Events from, an io.Closer to
// close the event stream on graceful termination and an error in case of failure.
type Client interface {
Do(encoding.Marshaler) (Response, error)
}
// ClientFunc is a functional adapter of the Client interface
type ClientFunc func(encoding.Marshaler) (Response, error)
// Do implements Client
func (cf ClientFunc) Do(m encoding.Marshaler) (Response, error) { return cf(m) }
// Response captures the output of a Mesos API operation. Callers are responsible for invoking
// Close when they're finished processing the response otherwise there may be connection leaks.
type Response interface {
io.Closer
encoding.Decoder
}
// ResponseDecorator optionally modifies the behavior of a Response
type ResponseDecorator interface {
Decorate(Response) Response
}
// ResponseDecoratorFunc is the functional adapter for ResponseDecorator
type ResponseDecoratorFunc func(Response) Response
func (f ResponseDecoratorFunc) Decorate(r Response) Response { return f(r) }
// CloseFunc is the functional adapter for io.Closer
type CloseFunc func() error
// Close implements io.Closer
func (f CloseFunc) Close() error { return f() }
// ResponseWrapper delegates to optional overrides for invocations of Response methods.
type ResponseWrapper struct {
Response Response
Closer io.Closer
Decoder encoding.Decoder
}
func (wrapper *ResponseWrapper) Close() error {
if wrapper.Closer != nil {
return wrapper.Closer.Close()
}
if wrapper.Response != nil {
return wrapper.Response.Close()
}
return nil
}
func (wrapper *ResponseWrapper) Decode(u encoding.Unmarshaler) error {
if wrapper.Decoder != nil {
return wrapper.Decoder.Decode(u)
}
return wrapper.Response.Decode(u)
}
var _ = Response(&ResponseWrapper{})

View File

@ -0,0 +1,54 @@
package client
import (
"github.com/mesos/mesos-go/api/v1/lib/encoding"
)
type (
// ResponseClass indicates the kind of response that a caller is expecting from Mesos.
ResponseClass int
// Request is a non-streaming request from the client to the server.
// Marshaler always returns the same object; the object is sent once to the server and then
// a response is expected.
Request interface {
Marshaler() encoding.Marshaler
}
// RequestStreaming is a streaming request from the client to the server.
// Marshaler returns a new object for upon each invocation, nil when there are no more objects to send.
// Client implementations are expected to differentiate between Request and RequestStreaming either by
// type-switching or by attempting interface conversion.
RequestStreaming interface {
Request
IsStreaming()
}
RequestFunc func() encoding.Marshaler
RequestStreamingFunc func() encoding.Marshaler
)
var (
_ = Request(RequestFunc(nil))
_ = RequestStreaming(RequestStreamingFunc(nil))
)
func (f RequestFunc) Marshaler() encoding.Marshaler { return f() }
func (f RequestStreamingFunc) Marshaler() encoding.Marshaler { return f() }
func (f RequestStreamingFunc) IsStreaming() {}
// RequestSingleton generates a non-streaming Request that always returns the same marshaler
func RequestSingleton(m encoding.Marshaler) Request {
return RequestFunc(func() encoding.Marshaler { return m })
}
const (
ResponseClassSingleton ResponseClass = iota
ResponseClassStreaming
ResponseClassNoData
// ResponseClassAuto should be used with versions of Mesos prior to 1.2.x.
// Otherwise, this type is deprecated and callers should use ResponseClassSingleton
// or ResponseClassStreaming instead.
ResponseClassAuto
)

View File

@ -0,0 +1,17 @@
package debug
import "log"
type Logger bool
func (d Logger) Log(v ...interface{}) {
if d {
log.Print(v...)
}
}
func (d Logger) Logf(s string, v ...interface{}) {
if d {
log.Printf(s, v...)
}
}

3
vendor/github.com/mesos/mesos-go/api/v1/lib/doc.go generated vendored Normal file
View File

@ -0,0 +1,3 @@
// Package mesos presents common v1 HTTP API message types in addition to extension APIs that
// aim to simplify use of the machine-generated code.
package mesos

View File

@ -0,0 +1,33 @@
package codecs
import (
"github.com/mesos/mesos-go/api/v1/lib/encoding"
"github.com/mesos/mesos-go/api/v1/lib/encoding/json"
"github.com/mesos/mesos-go/api/v1/lib/encoding/proto"
)
const (
// MediaTypeProtobuf is the Protobuf serialization format media type.
MediaTypeProtobuf = encoding.MediaType("application/x-protobuf")
// MediaTypeJSON is the JSON serialiation format media type.
MediaTypeJSON = encoding.MediaType("application/json")
NameProtobuf = "protobuf"
NameJSON = "json"
)
// ByMediaType are pre-configured default Codecs, ready to use OOTB
var ByMediaType = map[encoding.MediaType]encoding.Codec{
MediaTypeProtobuf: encoding.Codec{
Name: NameProtobuf,
Type: MediaTypeProtobuf,
NewEncoder: proto.NewEncoder,
NewDecoder: proto.NewDecoder,
},
MediaTypeJSON: encoding.Codec{
Name: NameJSON,
Type: MediaTypeJSON,
NewEncoder: json.NewEncoder,
NewDecoder: json.NewDecoder,
},
}

View File

@ -0,0 +1,34 @@
package framing
type (
// UnmarshalFunc translates bytes to objects
UnmarshalFunc func([]byte, interface{}) error
// Decoder reads and decodes Protobuf messages from an io.Reader.
Decoder interface {
// Decode reads the next encoded message from its input and stores it
// in the value pointed to by m. If m isn't a proto.Message, Decode will panic.
Decode(interface{}) error
}
// DecoderFunc is the functional adaptation of Decoder
DecoderFunc func(interface{}) error
)
func (f DecoderFunc) Decode(m interface{}) error { return f(m) }
var _ = Decoder(DecoderFunc(nil))
// NewDecoder returns a new Decoder that reads from the given frame Reader.
func NewDecoder(r Reader, uf UnmarshalFunc) DecoderFunc {
return func(m interface{}) error {
// Note: the buf returned by ReadFrame will change over time, it can't be sub-sliced
// and then those sub-slices retained. Examination of generated proto code seems to indicate
// that byte buffers are copied vs. referenced by sub-slice (gogo protoc).
frame, err := r.ReadFrame()
if err != nil {
return err
}
return uf(frame, m)
}
}

View File

@ -0,0 +1,70 @@
package framing
import (
"io"
"io/ioutil"
)
type Error string
func (err Error) Error() string { return string(err) }
const (
ErrorUnderrun = Error("frame underrun, unexpected EOF")
ErrorBadSize = Error("bad frame size")
ErrorOversizedFrame = Error("oversized frame, max size exceeded")
)
type (
// Reader generates data frames from some source, returning io.EOF when the end of the input stream is
// detected.
Reader interface {
ReadFrame() (frame []byte, err error)
}
// ReaderFunc is the functional adaptation of Reader.
ReaderFunc func() ([]byte, error)
// Writer sends whole frames to some endpoint; returns io.ErrShortWrite if the frame is only partially written.
Writer interface {
WriteFrame(frame []byte) error
}
// WriterFunc is the functional adaptation of Writer.
WriterFunc func([]byte) error
)
func (f ReaderFunc) ReadFrame() ([]byte, error) { return f() }
func (f WriterFunc) WriteFrame(b []byte) error { return f(b) }
var _ = Reader(ReaderFunc(nil))
var _ = Writer(WriterFunc(nil))
// EOFReaderFunc always returns nil, io.EOF; it implements the ReaderFunc API.
func EOFReaderFunc() ([]byte, error) { return nil, io.EOF }
var _ = ReaderFunc(EOFReaderFunc) // sanity check
// ReadAll returns a reader func that returns the complete contents of `r` in a single frame.
// A zero length frame is treated as an "end of stream" condition, returning io.EOF.
func ReadAll(r io.Reader) ReaderFunc {
return func() (b []byte, err error) {
b, err = ioutil.ReadAll(r)
if len(b) == 0 && err == nil {
err = io.EOF
}
return
}
}
// WriterFor adapts an io.Writer to the Writer interface. All buffers are written to `w` without decoration or
// modification.
func WriterFor(w io.Writer) WriterFunc {
return func(b []byte) error {
n, err := w.Write(b)
if err == nil && n != len(b) {
return io.ErrShortWrite
}
return err
}
}

View File

@ -0,0 +1,28 @@
package json
import (
"encoding/json"
"github.com/mesos/mesos-go/api/v1/lib/encoding"
"github.com/mesos/mesos-go/api/v1/lib/encoding/framing"
)
// NewEncoder returns a new Encoder of Calls to JSON messages written to
// the given io.Writer.
func NewEncoder(s encoding.Sink) encoding.Encoder {
w := s()
return encoding.EncoderFunc(func(m encoding.Marshaler) error {
b, err := json.Marshal(m)
if err != nil {
return err
}
return w.WriteFrame(b)
})
}
// NewDecoder returns a new Decoder of JSON messages read from the given source.
func NewDecoder(s encoding.Source) encoding.Decoder {
r := s()
dec := framing.NewDecoder(r, json.Unmarshal)
return encoding.DecoderFunc(func(u encoding.Unmarshaler) error { return dec.Decode(u) })
}

View File

@ -0,0 +1,4 @@
// Package proto implements protobuf utilities such as functional options to
// construct complex structs and encoders and decoders composable with
// io.ReadWriters.
package proto

View File

@ -0,0 +1,30 @@
package proto
import (
"github.com/gogo/protobuf/proto"
"github.com/mesos/mesos-go/api/v1/lib/encoding"
"github.com/mesos/mesos-go/api/v1/lib/encoding/framing"
)
// NewEncoder returns a new Encoder of Calls to Protobuf messages written to
// the given io.Writer.
func NewEncoder(s encoding.Sink) encoding.Encoder {
w := s()
return encoding.EncoderFunc(func(m encoding.Marshaler) error {
b, err := proto.Marshal(m.(proto.Message))
if err != nil {
return err
}
return w.WriteFrame(b)
})
}
// NewDecoder returns a new Decoder of Protobuf messages read from the given Source.
func NewDecoder(s encoding.Source) encoding.Decoder {
r := s()
var (
uf = func(b []byte, m interface{}) error { return proto.Unmarshal(b, m.(proto.Message)) }
dec = framing.NewDecoder(r, uf)
)
return encoding.DecoderFunc(func(u encoding.Unmarshaler) error { return dec.Decode(u) })
}

View File

@ -0,0 +1,111 @@
package encoding
import (
"encoding/json"
"io"
pb "github.com/gogo/protobuf/proto"
"github.com/mesos/mesos-go/api/v1/lib/encoding/framing"
)
type MediaType string
// ContentType returns the HTTP Content-Type associated with the MediaType
func (m MediaType) ContentType() string { return string(m) }
type (
Source func() framing.Reader
Sink func() framing.Writer
// A Codec composes encoding and decoding of a serialization format.
Codec struct {
Name string
Type MediaType
NewEncoder func(Sink) Encoder
NewDecoder func(Source) Decoder
}
SourceFactory interface {
NewSource(r io.Reader) Source
}
SourceFactoryFunc func(r io.Reader) Source
SinkFactory interface {
NewSink(w io.Writer) Sink
}
SinkFactoryFunc func(w io.Writer) Sink
)
func (f SourceFactoryFunc) NewSource(r io.Reader) Source { return f(r) }
func (f SinkFactoryFunc) NewSink(w io.Writer) Sink { return f(w) }
var (
_ = SourceFactory(SourceFactoryFunc(nil))
_ = SinkFactory(SinkFactoryFunc(nil))
)
// SourceReader returns a Source that buffers all input from the given io.Reader
// and returns the contents in a single frame.
func SourceReader(r io.Reader) Source {
ch := make(chan framing.ReaderFunc, 1)
ch <- framing.ReadAll(r)
return func() framing.Reader {
select {
case f := <-ch:
return f
default:
return framing.ReaderFunc(framing.EOFReaderFunc)
}
}
}
// SinkWriter returns a Sink that sends a frame to an io.Writer with no decoration.
func SinkWriter(w io.Writer) Sink { return func() framing.Writer { return framing.WriterFor(w) } }
// String implements the fmt.Stringer interface.
func (c *Codec) String() string {
if c == nil {
return ""
}
return c.Name
}
type (
// Marshaler composes the supported marshaling formats.
Marshaler interface {
pb.Marshaler
json.Marshaler
}
// Unmarshaler composes the supporter unmarshaling formats.
Unmarshaler interface {
pb.Unmarshaler
json.Unmarshaler
}
// An Encoder encodes a given Marshaler or returns an error in case of failure.
Encoder interface {
Encode(Marshaler) error
}
// EncoderFunc is the functional adapter for Encoder
EncoderFunc func(Marshaler) error
// A Decoder decodes a given Unmarshaler or returns an error in case of failure.
Decoder interface {
Decode(Unmarshaler) error
}
// DecoderFunc is the functional adapter for Decoder
DecoderFunc func(Unmarshaler) error
)
// Decode implements the Decoder interface
func (f DecoderFunc) Decode(u Unmarshaler) error { return f(u) }
// Encode implements the Encoder interface
func (f EncoderFunc) Encode(m Marshaler) error { return f(m) }
var (
_ = Encoder(EncoderFunc(nil))
_ = Decoder(DecoderFunc(nil))
)

26
vendor/github.com/mesos/mesos-go/api/v1/lib/filters.go generated vendored Normal file
View File

@ -0,0 +1,26 @@
package mesos
import "time"
type FilterOpt func(*Filters)
func (f *Filters) With(opts ...FilterOpt) *Filters {
for _, o := range opts {
o(f)
}
return f
}
func RefuseSeconds(d time.Duration) FilterOpt {
return func(f *Filters) {
s := d.Seconds()
f.RefuseSeconds = &s
}
}
func OptionalFilters(fo ...FilterOpt) *Filters {
if len(fo) == 0 {
return nil
}
return (&Filters{}).With(fo...)
}

View File

@ -0,0 +1,35 @@
package mesos
// fixed point scalar math from mesos:src/common/values.cpp
// --
// We manipulate scalar values by converting them from floating point to a
// fixed point representation, doing a calculation, and then converting
// the result back to floating point. We deliberately only preserve three
// decimal digits of precision in the fixed point representation. This
// ensures that client applications see predictable numerical behavior, at
// the expense of sacrificing some precision.
import "math"
func convertToFloat64(f int64) float64 {
// NOTE: We do the conversion from fixed point via integer division
// and then modulus, rather than a single floating point division.
// This ensures that we only apply floating point division to inputs
// in the range [0,999], which is easier to check for correctness.
var (
quotient = float64(f / 1000)
remainder = float64(f%1000) / 1000.0
)
return quotient + remainder
}
func convertToFixed64(f float64) int64 {
return round64(f * 1000)
}
func round64(f float64) int64 {
if math.Abs(f) < 0.5 {
return 0
}
return int64(f + math.Copysign(0.5, f))
}

View File

@ -0,0 +1,161 @@
package apierrors
import (
"io"
"io/ioutil"
"net/http"
)
// Code is a Mesos HTTP v1 API response status code
type Code int
const (
// MsgNotLeader is returned by Do calls that are sent to a non leading Mesos master.
MsgNotLeader = "call sent to a non-leading master"
// MsgAuth is returned by Do calls that are not successfully authenticated.
MsgAuth = "call not authenticated"
// MsgUnsubscribed is returned by Do calls that are sent before a subscription is established.
MsgUnsubscribed = "no subscription established"
// MsgVersion is returned by Do calls that are sent to an incompatible API version.
MsgVersion = "incompatible API version"
// MsgMalformed is returned by Do calls that are malformed.
MsgMalformed = "malformed request"
// MsgMediaType is returned by Do calls that are sent with an unsupported media type.
MsgMediaType = "unsupported media type"
// MsgRateLimit is returned by Do calls that are rate limited. This is a temporary condition
// that should clear.
MsgRateLimit = "rate limited"
// MsgUnavailable is returned by Do calls that are sent to a master or agent that's in recovery, or
// does not yet realize that it's the leader. This is a temporary condition that should clear.
MsgUnavailable = "mesos server unavailable"
// MsgNotFound could happen if the master or agent libprocess has not yet set up http routes.
MsgNotFound = "mesos http endpoint not found"
CodeNotLeader = Code(http.StatusTemporaryRedirect)
CodeNotAuthenticated = Code(http.StatusUnauthorized)
CodeUnsubscribed = Code(http.StatusForbidden)
CodeIncompatibleVersion = Code(http.StatusConflict)
CodeMalformedRequest = Code(http.StatusBadRequest)
CodeUnsupportedMediaType = Code(http.StatusNotAcceptable)
CodeRateLimitExceeded = Code(http.StatusTooManyRequests)
CodeMesosUnavailable = Code(http.StatusServiceUnavailable)
CodeNotFound = Code(http.StatusNotFound)
MaxSizeDetails = 4 * 1024 // MaxSizeDetails limits the length of the details message read from a response body
)
var (
// ErrorTable maps HTTP response codes to their respective Mesos v1 API error messages.
ErrorTable = map[Code]string{
CodeNotLeader: MsgNotLeader,
CodeMalformedRequest: MsgMalformed,
CodeIncompatibleVersion: MsgVersion,
CodeUnsubscribed: MsgUnsubscribed,
CodeNotAuthenticated: MsgAuth,
CodeUnsupportedMediaType: MsgMediaType,
CodeNotFound: MsgNotFound,
CodeMesosUnavailable: MsgUnavailable,
CodeRateLimitExceeded: MsgRateLimit,
}
)
// Error captures HTTP v1 API error codes and messages generated by Mesos.
type Error struct {
code Code // code is the HTTP response status code generated by Mesos
message string // message briefly summarizes the nature of the error, possibly includes details from Mesos
}
// IsError returns true for all HTTP status codes that are not considered informational or successful.
func (code Code) IsError() bool {
return code >= 300
}
// FromResponse returns an `*Error` for a response containing a status code that indicates an error condition.
// The response body (if any) is captured in the Error.Details field.
// Returns nil for nil responses and responses with non-error status codes.
// See IsErrorCode.
func FromResponse(res *http.Response) error {
if res == nil {
return nil
}
code := Code(res.StatusCode)
if !code.IsError() {
// non-error HTTP response codes don't generate errors
return nil
}
var details string
if res.Body != nil {
defer res.Body.Close()
buf, _ := ioutil.ReadAll(io.LimitReader(res.Body, MaxSizeDetails))
details = string(buf)
}
return code.Error(details)
}
// Error generates an error from the given status code and detail string.
func (code Code) Error(details string) error {
if !code.IsError() {
return nil
}
err := &Error{
code: code,
message: ErrorTable[code],
}
if details != "" {
err.message = err.message + ": " + details
}
return err
}
// Error implements error interface
func (e *Error) Error() string { return e.message }
// Temporary returns true if the error is a temporary condition that should eventually clear.
func (e *Error) Temporary() bool {
switch e.code {
// TODO(jdef): NotFound **could** be a temporary error because there's a race at mesos startup in which the
// HTTP server responds before the internal listeners have been initialized. But it could also be reported
// because the client is accessing an invalid endpoint; as of right now, a client cannot distinguish between
// these cases.
// https://issues.apache.org/jira/browse/MESOS-7697
case CodeRateLimitExceeded, CodeMesosUnavailable:
return true
default:
return false
}
}
// CodesIndicatingSubscriptionLoss is a set of apierror.Code entries which each indicate that
// the event subscription stream has been severed between the scheduler and mesos. It's respresented
// as a public map variable so that clients can program additional error codes (if such are discovered)
// without hacking the code of the mesos-go library directly.
var CodesIndicatingSubscriptionLoss = func(codes ...Code) map[Code]struct{} {
result := make(map[Code]struct{}, len(codes))
for _, code := range codes {
result[code] = struct{}{}
}
return result
}(
// expand this list as we discover other errors that guarantee we've lost our event subscription.
CodeUnsubscribed,
)
// SubscriptionLoss returns true if the error indicates that the event subscription stream has been severed
// between mesos and a mesos client.
func (e *Error) SubscriptionLoss() (result bool) {
_, result = CodesIndicatingSubscriptionLoss[e.code]
return
}
// Matches returns true if the given error is an API error with a matching error code
func (code Code) Matches(err error) bool {
if err == nil {
return !code.IsError()
}
apiErr, ok := err.(*Error)
return ok && apiErr.code == code
}

View File

@ -0,0 +1,33 @@
package httpcli
import (
"net/http"
)
// roundTripperFunc is the functional adaptation of http.RoundTripper
type roundTripperFunc func(*http.Request) (*http.Response, error)
// RoundTrip implements RoundTripper for roundTripperFunc
func (f roundTripperFunc) RoundTrip(req *http.Request) (*http.Response, error) { return f(req) }
// BasicAuth generates a functional config option that sets HTTP Basic authentication for a Client
func BasicAuth(username, passwd string) ConfigOpt {
// TODO(jdef) this could be more efficient. according to the stdlib we're not supposed to
// mutate the original Request, so we copy here (including headers). another approach would
// be to generate a functional RequestOpt that adds the right header.
return WrapRoundTripper(func(rt http.RoundTripper) http.RoundTripper {
return roundTripperFunc(func(req *http.Request) (*http.Response, error) {
var h http.Header
if req.Header != nil {
h = make(http.Header, len(req.Header))
for k, v := range req.Header {
h[k] = append(make([]string, 0, len(v)), v...)
}
}
clonedReq := *req
clonedReq.Header = h
clonedReq.SetBasicAuth(username, passwd)
return rt.RoundTrip(&clonedReq)
})
})
}

View File

@ -0,0 +1,614 @@
package httpcli
import (
"bytes"
"context"
"crypto/tls"
"fmt"
"io"
"io/ioutil"
"net"
"net/http"
"sync"
"time"
"github.com/mesos/mesos-go/api/v1/lib"
"github.com/mesos/mesos-go/api/v1/lib/client"
logger "github.com/mesos/mesos-go/api/v1/lib/debug"
"github.com/mesos/mesos-go/api/v1/lib/encoding"
"github.com/mesos/mesos-go/api/v1/lib/encoding/codecs"
"github.com/mesos/mesos-go/api/v1/lib/encoding/framing"
"github.com/mesos/mesos-go/api/v1/lib/httpcli/apierrors"
"github.com/mesos/mesos-go/api/v1/lib/recordio"
)
func noRedirect(req *http.Request, via []*http.Request) error { return http.ErrUseLastResponse }
// ProtocolError is returned when we receive a response from Mesos that is outside of the HTTP API specification.
// Receipt of the following will yield protocol errors:
// - any unexpected non-error HTTP response codes (e.g. 199)
// - any unexpected Content-Type
type ProtocolError string
// Error implements error interface
func (pe ProtocolError) Error() string { return string(pe) }
const (
debug = logger.Logger(false)
mediaTypeRecordIO = encoding.MediaType("application/recordio")
)
// DoFunc sends an HTTP request and returns an HTTP response.
//
// An error is returned if caused by client policy (such as
// http.Client.CheckRedirect), or if there was an HTTP protocol error. A
// non-2xx response doesn't cause an error.
//
// When err is nil, resp always contains a non-nil resp.Body.
//
// Callers should close resp.Body when done reading from it. If resp.Body is
// not closed, an underlying RoundTripper (typically Transport) may not be able
// to re-use a persistent TCP connection to the server for a subsequent
// "keep-alive" request.
//
// The request Body, if non-nil, will be closed by an underlying Transport,
// even on errors.
type DoFunc func(*http.Request) (*http.Response, error)
// Response captures the output of a Mesos HTTP API operation. Callers are responsible for invoking
// Close when they're finished processing the response otherwise there may be connection leaks.
type Response struct {
io.Closer
encoding.Decoder
Header http.Header
}
// ErrorMapperFunc generates an error for the given response.
type ErrorMapperFunc func(*http.Response) error
// ResponseHandler is invoked to process an HTTP response. Callers SHALL invoke Close for
// a non-nil Response, even when errors are returned.
type ResponseHandler func(*http.Response, client.ResponseClass, error) (mesos.Response, error)
// A Client is a Mesos HTTP APIs client.
type Client struct {
url string
do DoFunc
header http.Header
codec encoding.Codec
errorMapper ErrorMapperFunc
requestOpts []RequestOpt
buildRequestFunc func(client.Request, client.ResponseClass, ...RequestOpt) (*http.Request, error)
handleResponse ResponseHandler
}
var (
DefaultCodec = codecs.ByMediaType[codecs.MediaTypeProtobuf]
DefaultHeaders = http.Header{}
// DefaultConfigOpt represents the default client config options.
DefaultConfigOpt = []ConfigOpt{
Transport(func(t *http.Transport) {
// all calls should be ack'd by the server within this interval.
t.ResponseHeaderTimeout = 15 * time.Second
t.MaxIdleConnsPerHost = 2 // don't depend on go's default
}),
}
DefaultErrorMapper = ErrorMapperFunc(apierrors.FromResponse)
)
// New returns a new Client with the given Opts applied.
// Callers are expected to configure the URL, Do, and Codec options prior to
// invoking Do.
func New(opts ...Opt) *Client {
c := &Client{
codec: DefaultCodec,
do: With(DefaultConfigOpt...),
header: cloneHeaders(DefaultHeaders),
errorMapper: DefaultErrorMapper,
}
c.buildRequestFunc = c.buildRequest
c.handleResponse = c.HandleResponse
c.With(opts...)
return c
}
func cloneHeaders(hs http.Header) http.Header {
result := make(http.Header)
for k, v := range hs {
cloned := make([]string, len(v))
copy(cloned, v)
result[k] = cloned
}
return result
}
// Endpoint returns the current Mesos API endpoint URL that the caller is set to invoke
func (c *Client) Endpoint() string {
return c.url
}
// RequestOpt defines a functional option for an http.Request.
type RequestOpt func(*http.Request)
// RequestOpts is a convenience type
type RequestOpts []RequestOpt
// Apply this set of request options to the given HTTP request.
func (opts RequestOpts) Apply(req *http.Request) {
// apply per-request options
for _, o := range opts {
if o != nil {
o(req)
}
}
}
// With applies the given Opts to a Client and returns itself.
func (c *Client) With(opts ...Opt) Opt {
return Opts(opts).Merged().Apply(c)
}
// WithTemporary configures the Client with the temporary option and returns the results of
// invoking f(). Changes made to the Client by the temporary option are reverted before this
// func returns.
func (c *Client) WithTemporary(opt Opt, f func() error) error {
if opt != nil {
undo := c.With(opt)
defer c.With(undo)
}
return f()
}
// Mesos returns a mesos.Client variant backed by this implementation.
// Deprecated.
func (c *Client) Mesos(opts ...RequestOpt) mesos.Client {
return mesos.ClientFunc(func(m encoding.Marshaler) (mesos.Response, error) {
return c.Do(m, opts...)
})
}
func prepareForResponse(rc client.ResponseClass, codec encoding.Codec) (RequestOpts, error) {
// We need to tell Mesos both the content-type and message-content-type that we're expecting, otherwise
// the server may give us validation problems, or else send back a vague content-type (w/o a
// message-content-type). In order to communicate these things we need to understand the desired response
// type from the perspective of the caller --> client.ResponseClass.
var accept RequestOpts
switch rc {
case client.ResponseClassSingleton, client.ResponseClassAuto, client.ResponseClassNoData:
accept = append(accept, Header("Accept", codec.Type.ContentType()))
case client.ResponseClassStreaming:
accept = append(accept, Header("Accept", mediaTypeRecordIO.ContentType()))
accept = append(accept, Header("Message-Accept", codec.Type.ContentType()))
default:
return nil, ProtocolError(fmt.Sprintf("illegal response class requested: %v", rc))
}
return accept, nil
}
// buildRequest is a factory func that generates and returns an http.Request for the
// given marshaler and request options.
func (c *Client) buildRequest(cr client.Request, rc client.ResponseClass, opt ...RequestOpt) (*http.Request, error) {
if crs, ok := cr.(client.RequestStreaming); ok {
return c.buildRequestStream(crs.Marshaler, rc, opt...)
}
accept, err := prepareForResponse(rc, c.codec)
if err != nil {
return nil, err
}
//TODO(jdef): use a pool to allocate these (and reduce garbage)?
// .. or else, use a pipe (like streaming does) to avoid the intermediate buffer?
var body bytes.Buffer
if err := c.codec.NewEncoder(encoding.SinkWriter(&body)).Encode(cr.Marshaler()); err != nil {
return nil, err
}
req, err := http.NewRequest("POST", c.url, &body)
if err != nil {
return nil, err
}
helper := HTTPRequestHelper{req}
return helper.
withOptions(c.requestOpts, opt).
withHeaders(c.header).
withHeader("Content-Type", c.codec.Type.ContentType()).
withHeader("Accept", c.codec.Type.ContentType()).
withOptions(accept).
Request, nil
}
func (c *Client) buildRequestStream(f func() encoding.Marshaler, rc client.ResponseClass, opt ...RequestOpt) (*http.Request, error) {
accept, err := prepareForResponse(rc, c.codec)
if err != nil {
return nil, err
}
var (
pr, pw = io.Pipe()
enc = c.codec.NewEncoder(func() framing.Writer { return recordio.NewWriter(pw) })
)
req, err := http.NewRequest("POST", c.url, pr)
if err != nil {
pw.Close() // ignore error
return nil, err
}
go func() {
var closeOnce sync.Once
defer closeOnce.Do(func() {
pw.Close()
})
for {
m := f()
if m == nil {
// no more messages to send; end of the stream
break
}
err := enc.Encode(m)
if err != nil {
closeOnce.Do(func() {
pw.CloseWithError(err)
})
break
}
}
}()
helper := HTTPRequestHelper{req}
return helper.
withOptions(c.requestOpts, opt).
withHeaders(c.header).
withHeader("Content-Type", mediaTypeRecordIO.ContentType()).
withHeader("Message-Content-Type", c.codec.Type.ContentType()).
withOptions(accept).
Request, nil
}
func validateSuccessfulResponse(codec encoding.Codec, res *http.Response, rc client.ResponseClass) error {
switch res.StatusCode {
case http.StatusOK:
ct := res.Header.Get("Content-Type")
switch rc {
case client.ResponseClassNoData:
if ct != "" {
return ProtocolError(fmt.Sprintf("unexpected content type: %q", ct))
}
case client.ResponseClassSingleton, client.ResponseClassAuto:
if ct != codec.Type.ContentType() {
return ProtocolError(fmt.Sprintf("unexpected content type: %q", ct))
}
case client.ResponseClassStreaming:
if ct != mediaTypeRecordIO.ContentType() {
return ProtocolError(fmt.Sprintf("unexpected content type: %q", ct))
}
ct = res.Header.Get("Message-Content-Type")
if ct != codec.Type.ContentType() {
return ProtocolError(fmt.Sprintf("unexpected message content type: %q", ct))
}
default:
return ProtocolError(fmt.Sprintf("unsupported response-class: %q", rc))
}
case http.StatusAccepted:
// nothing to validate, we're not expecting any response entity in this case.
// TODO(jdef) perhaps check Content-Length == 0 here?
}
return nil
}
func newSourceFactory(rc client.ResponseClass) encoding.SourceFactoryFunc {
switch rc {
case client.ResponseClassNoData:
return nil
case client.ResponseClassSingleton:
return encoding.SourceReader
case client.ResponseClassStreaming, client.ResponseClassAuto:
return recordIOSourceFactory
default:
panic(fmt.Sprintf("unsupported response-class: %q", rc))
}
}
func recordIOSourceFactory(r io.Reader) encoding.Source {
return func() framing.Reader { return recordio.NewReader(r) }
}
// HandleResponse parses an HTTP response from a Mesos service endpoint, transforming the
// raw HTTP response into a mesos.Response.
func (c *Client) HandleResponse(res *http.Response, rc client.ResponseClass, err error) (mesos.Response, error) {
if err != nil {
if res != nil && res.Body != nil {
res.Body.Close()
}
return nil, err
}
result := &Response{
Closer: res.Body,
Header: res.Header,
}
if err = c.errorMapper(res); err != nil {
return result, err
}
err = validateSuccessfulResponse(c.codec, res, rc)
if err != nil {
res.Body.Close()
return nil, err
}
switch res.StatusCode {
case http.StatusOK:
debug.Log("request OK, decoding response")
sf := newSourceFactory(rc)
if sf == nil {
if rc != client.ResponseClassNoData {
panic("nil Source for response that expected data")
}
// we don't expect any data. drain the response body and close it (compliant with golang's expectations
// for http/1.1 keepalive support.
defer res.Body.Close()
_, err = io.Copy(ioutil.Discard, res.Body)
return nil, err
}
result.Decoder = c.codec.NewDecoder(sf.NewSource(res.Body))
case http.StatusAccepted:
debug.Log("request Accepted")
// noop; no decoder for these types of calls
defer res.Body.Close()
_, err = io.Copy(ioutil.Discard, res.Body)
return nil, err
default:
debug.Log("unexpected HTTP status", res.StatusCode)
defer res.Body.Close()
io.Copy(ioutil.Discard, res.Body) // intentionally discard any error here
return nil, ProtocolError(fmt.Sprintf("unexpected mesos HTTP response code: %d", res.StatusCode))
}
return result, nil
}
// Do is deprecated in favor of Send.
func (c *Client) Do(m encoding.Marshaler, opt ...RequestOpt) (res mesos.Response, err error) {
return c.Send(client.RequestSingleton(m), client.ResponseClassAuto, opt...)
}
// Send sends a Call and returns (a) a Response (should be closed when finished) that
// contains a either a streaming or non-streaming Decoder from which callers can read
// objects from, and; (b) an error in case of failure. Callers are expected to *always*
// close a non-nil Response if one is returned. For operations which are successful but
// also for which there are no expected result objects the embedded Decoder will be nil.
// The provided ResponseClass determines whether the client implementation will attempt
// to decode a result as a single obeject or as an object stream. When working with
// versions of Mesos prior to v1.2.x callers MUST use ResponseClassAuto.
func (c *Client) Send(cr client.Request, rc client.ResponseClass, opt ...RequestOpt) (res mesos.Response, err error) {
var (
hreq *http.Request
hres *http.Response
)
hreq, err = c.buildRequestFunc(cr, rc, opt...)
if err == nil {
hres, err = c.do(hreq)
res, err = c.handleResponse(hres, rc, err)
}
return
}
// ErrorMapper returns am Opt that overrides the existing error mapping behavior of the client.
func ErrorMapper(em ErrorMapperFunc) Opt {
return func(c *Client) Opt {
old := c.errorMapper
c.errorMapper = em
return ErrorMapper(old)
}
}
// Endpoint returns an Opt that sets a Client's URL.
func Endpoint(rawurl string) Opt {
return func(c *Client) Opt {
old := c.url
c.url = rawurl
return Endpoint(old)
}
}
// WrapDoer returns an Opt that decorates a Client's DoFunc
func WrapDoer(f func(DoFunc) DoFunc) Opt {
return func(c *Client) Opt {
old := c.do
c.do = f(c.do)
return Do(old)
}
}
// Do returns an Opt that sets a Client's DoFunc
func Do(do DoFunc) Opt {
return func(c *Client) Opt {
old := c.do
c.do = do
return Do(old)
}
}
// Codec returns an Opt that sets a Client's Codec.
func Codec(codec encoding.Codec) Opt {
return func(c *Client) Opt {
old := c.codec
c.codec = codec
return Codec(old)
}
}
// DefaultHeader returns an Opt that adds a header to an Client's headers.
func DefaultHeader(k, v string) Opt {
return func(c *Client) Opt {
old, found := c.header[k]
old = append([]string{}, old...) // clone
c.header.Add(k, v)
return func(c *Client) Opt {
if found {
c.header[k] = old
} else {
c.header.Del(k)
}
return DefaultHeader(k, v)
}
}
}
// HandleResponse returns a functional config option to set the HTTP response handler of the client.
func HandleResponse(f ResponseHandler) Opt {
return func(c *Client) Opt {
old := c.handleResponse
c.handleResponse = f
return HandleResponse(old)
}
}
// RequestOptions returns an Opt that applies the given set of options to every Client request.
func RequestOptions(opts ...RequestOpt) Opt {
if len(opts) == 0 {
return nil
}
return func(c *Client) Opt {
old := append([]RequestOpt{}, c.requestOpts...)
c.requestOpts = opts
return RequestOptions(old...)
}
}
// Header returns an RequestOpt that adds a header value to an HTTP requests's header.
func Header(k, v string) RequestOpt { return func(r *http.Request) { r.Header.Add(k, v) } }
// Close returns a RequestOpt that determines whether to close the underlying connection after sending the request.
func Close(b bool) RequestOpt { return func(r *http.Request) { r.Close = b } }
// Context returns a RequestOpt that sets the request's Context (ctx must be non-nil)
func Context(ctx context.Context) RequestOpt {
return func(r *http.Request) {
r2 := r.WithContext(ctx)
*r = *r2
}
}
type Config struct {
client *http.Client
dialer *net.Dialer
transport *http.Transport
}
type ConfigOpt func(*Config)
// With returns a DoFunc that executes HTTP round-trips.
// The default implementation provides reasonable defaults for timeouts:
// keep-alive, connection, request/response read/write, and TLS handshake.
// Callers can customize configuration by specifying one or more ConfigOpt's.
func With(opt ...ConfigOpt) DoFunc {
var (
dialer = &net.Dialer{
LocalAddr: &net.TCPAddr{IP: net.IPv4zero},
KeepAlive: 30 * time.Second,
Timeout: 5 * time.Second,
}
transport = &http.Transport{
Proxy: http.ProxyFromEnvironment,
Dial: dialer.Dial,
ResponseHeaderTimeout: 5 * time.Second,
TLSClientConfig: &tls.Config{InsecureSkipVerify: false},
TLSHandshakeTimeout: 5 * time.Second,
}
config = &Config{
dialer: dialer,
transport: transport,
client: &http.Client{
Transport: transport,
CheckRedirect: noRedirect, // so we can actually see the 307 redirects
},
}
)
for _, o := range opt {
if o != nil {
o(config)
}
}
return config.client.Do
}
// Timeout returns an ConfigOpt that sets a Config's response header timeout, tls handshake timeout,
// and dialer timeout.
func Timeout(d time.Duration) ConfigOpt {
return func(c *Config) {
c.transport.ResponseHeaderTimeout = d
c.transport.TLSHandshakeTimeout = d
c.dialer.Timeout = d
}
}
// RoundTripper returns a ConfigOpt that sets a Config's round-tripper.
func RoundTripper(rt http.RoundTripper) ConfigOpt {
return func(c *Config) {
c.client.Transport = rt
}
}
// TLSConfig returns a ConfigOpt that sets a Config's TLS configuration.
func TLSConfig(tc *tls.Config) ConfigOpt {
return func(c *Config) {
c.transport.TLSClientConfig = tc
}
}
// Transport returns a ConfigOpt that allows tweaks of the default Config's http.Transport
func Transport(modifyTransport func(*http.Transport)) ConfigOpt {
return func(c *Config) {
if modifyTransport != nil {
modifyTransport(c.transport)
}
}
}
// WrapRoundTripper allows a caller to customize a configuration's HTTP exchanger. Useful
// for authentication protocols that operate over stock HTTP.
func WrapRoundTripper(f func(http.RoundTripper) http.RoundTripper) ConfigOpt {
return func(c *Config) {
if f != nil {
if rt := f(c.client.Transport); rt != nil {
c.client.Transport = rt
}
}
}
}
// HTTPRequestHelper wraps an http.Request and provides utility funcs to simplify code elsewhere
type HTTPRequestHelper struct {
*http.Request
}
func (r *HTTPRequestHelper) withOptions(optsets ...RequestOpts) *HTTPRequestHelper {
for _, opts := range optsets {
opts.Apply(r.Request)
}
return r
}
func (r *HTTPRequestHelper) withHeaders(hh http.Header) *HTTPRequestHelper {
for k, v := range hh {
r.Header[k] = v
debug.Log("request header " + k + ": " + v[0])
}
return r
}
func (r *HTTPRequestHelper) withHeader(key, value string) *HTTPRequestHelper {
r.Header.Set(key, value)
return r
}

View File

@ -0,0 +1,53 @@
package httpcli
type (
// Opt defines a functional option for the HTTP client type. A functional option
// must return an Opt that acts as an "undo" if applied to the same Client.
Opt func(*Client) Opt
// Opts represents a series of functional options
Opts []Opt
)
// Apply is a nil-safe application of an Opt: if the receiver is nil then this func
// simply returns nil, otherwise it returns the result invoking the receiving Opt
// with the given Client.
func (o Opt) Apply(c *Client) (result Opt) {
if o != nil {
result = o(c)
}
return
}
// Merged generates a single Opt that applies all the functional options, in-order
func (opts Opts) Merged() Opt {
if len(opts) == 0 {
return nil
}
return func(c *Client) Opt {
var (
size = len(opts)
undo = make(Opts, size)
)
size-- // make this a zero-based offset
for i, opt := range opts {
if opt != nil {
undo[size-i] = opt(c)
}
}
return undo.Merged()
}
}
// And combines two functional options into a single Opt
func (o Opt) And(other Opt) Opt {
if o == nil {
if other == nil {
return nil
}
return other
}
if other == nil {
return o
}
return Opts{o, other}.Merged()
}

95
vendor/github.com/mesos/mesos-go/api/v1/lib/labels.go generated vendored Normal file
View File

@ -0,0 +1,95 @@
package mesos
import (
"bytes"
"io"
)
type labelList []Label // convenience type, for working with unwrapped Label slices
// Equivalent returns true if left and right have the same labels. Order is not important.
func (left *Labels) Equivalent(right *Labels) bool {
return labelList(left.GetLabels()).Equivalent(labelList(right.GetLabels()))
}
// Equivalent returns true if left and right have the same labels. Order is not important.
func (left labelList) Equivalent(right labelList) bool {
if len(left) != len(right) {
return false
} else {
for i := range left {
found := false
for j := range right {
if left[i].Equivalent(right[j]) {
found = true
break
}
}
if !found {
return false
}
}
return true
}
}
// Equivalent returns true if left and right represent the same Label.
func (left Label) Equivalent(right Label) bool {
if left.Key != right.Key {
return false
}
if left.Value == nil {
return right.Value == nil
} else {
return right.Value != nil && *left.Value == *right.Value
}
}
func (left Label) writeTo(w io.Writer) (n int64, err error) {
write := func(s string) {
if err != nil {
return
}
var n2 int
n2, err = io.WriteString(w, s)
n += int64(n2)
}
write(left.Key)
if s := left.GetValue(); s != "" {
write("=")
write(s)
}
return
}
func (left *Labels) writeTo(w io.Writer) (n int64, err error) {
var (
lab = left.GetLabels()
n2 int
n3 int64
)
for i := range lab {
if i > 0 {
n2, err = io.WriteString(w, ",")
n += int64(n2)
if err != nil {
break
}
}
n3, err = lab[i].writeTo(w)
n += n3
if err != nil {
break
}
}
return
}
func (left *Labels) Format() string {
if left == nil {
return ""
}
var b bytes.Buffer
left.writeTo(&b)
return b.String()
}

72228
vendor/github.com/mesos/mesos-go/api/v1/lib/mesos.pb.go generated vendored Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

3520
vendor/github.com/mesos/mesos-go/api/v1/lib/mesos.proto generated vendored Normal file

File diff suppressed because it is too large Load Diff

253
vendor/github.com/mesos/mesos-go/api/v1/lib/ranges.go generated vendored Normal file
View File

@ -0,0 +1,253 @@
package mesos
import (
"sort"
)
// Ranges represents a list of Ranges.
type Ranges []Value_Range
// NewRanges returns squashed Ranges from the given numbers.
func NewRanges(ns ...uint64) Ranges {
xs := append(uint64s{}, ns...)
sort.Sort(xs)
rs := make(Ranges, len(xs))
for i := range xs {
rs[i].Begin, rs[i].End = xs[i], xs[i]
}
return rs.Squash()
}
// NewPortRanges returns Ranges from the "ports" resource in the
// given *Offer. If that resource isn't provided, nil will be returned.
//
// The returned Ranges are sorted and have all overlapping ranges merged from
// left to right. e.g. [[0, 5], [4, 3], [10, 7]] -> [[0, 5], [7, 10]]
func NewPortRanges(o *Offer) Ranges {
if o == nil {
return Ranges{}
}
var (
r Resource
found bool
)
for i := range o.Resources {
if o.Resources[i].GetName() == "ports" {
r = o.Resources[i]
found = true
break
}
}
if !found {
return Ranges{}
}
offered := r.GetRanges().GetRange()
rs := make(Ranges, len(offered))
for i, r := range offered {
if lo, hi := r.GetBegin(), r.GetEnd(); lo <= hi {
rs[i].Begin, rs[i].End = lo, hi
} else {
rs[i].Begin, rs[i].End = hi, lo
}
}
return rs.Sort().Squash()
}
// These three methods implement sort.Interface
func (rs Ranges) Len() int { return len(rs) }
func (rs Ranges) Swap(i, j int) { rs[i], rs[j] = rs[j], rs[i] }
func (rs Ranges) Less(i, j int) bool {
return rs[i].Begin < rs[j].Begin || (rs[i].Begin == rs[j].Begin && rs[i].End < rs[j].End)
}
// Size returns the sum of the Size of all Ranges.
func (rs Ranges) Size() uint64 {
var sz uint64
for i := range rs {
sz += 1 + (rs[i].End - rs[i].Begin)
}
return sz
}
// Sort sorts the receiving Ranges and returns the result; convenience
func (rs Ranges) Sort() Ranges {
sort.Sort(rs)
return rs
}
// Squash merges overlapping and continuous Ranges. It assumes they're pre-sorted.
func (rs Ranges) Squash() Ranges {
if len(rs) < 2 {
return rs
}
squashed := Ranges{rs[0]}
for i := 1; i < len(rs); i++ {
switch max := squashed[len(squashed)-1].End; {
case 1+max < rs[i].Begin: // no overlap nor continuity: push
squashed = append(squashed, rs[i])
case max <= rs[i].End: // overlap or continuity: squash
squashed[len(squashed)-1].End = rs[i].End
}
}
return squashed
}
// Search performs a binary search for n returning the index of the Range it was
// found at or -1 if not found.
func (rs Ranges) Search(n uint64) int {
for lo, hi := 0, len(rs)-1; lo <= hi; {
switch m := lo + (hi-lo)/2; {
case n < rs[m].Begin:
hi = m - 1
case n > rs[m].End:
lo = m + 1
default:
return m
}
}
return -1
}
// Partition partitions Ranges around n. It returns the partitioned Ranges
// and a boolean indicating if n was found.
func (rs Ranges) Partition(n uint64) (Ranges, bool) {
i := rs.Search(n)
if i < 0 {
return rs, false
}
pn := make(Ranges, 0, len(rs)+1)
switch pn = append(pn, rs[:i]...); {
case rs[i].Begin == rs[i].End: // delete
case rs[i].Begin == n: // increment lower bound
pn = append(pn, Value_Range{rs[i].Begin + 1, rs[i].End})
case rs[i].End == n: // decrement upper bound
pn = append(pn, Value_Range{rs[i].Begin, rs[i].End - 1})
default: // split
pn = append(pn, Value_Range{rs[i].Begin, n - 1}, Value_Range{n + 1, rs[i].End})
}
return append(pn, rs[i+1:]...), true
}
// Remove removes a range from already coalesced ranges.
// The algorithms constructs a new vector of ranges which is then
// Squash'ed into a Ranges instance.
func (rs Ranges) Remove(removal Value_Range) Ranges {
ranges := make([]Value_Range, 0, len(rs))
for _, r := range rs {
// skip if the entire range is subsumed by removal
if r.Begin >= removal.Begin && r.End <= removal.End {
continue
}
// divide if the range subsumes the removal
if r.Begin < removal.Begin && r.End > removal.End {
ranges = append(ranges,
Value_Range{r.Begin, removal.Begin - 1},
Value_Range{removal.End + 1, r.End},
)
continue
}
// add the full range if there's no intersection
if r.End < removal.Begin || r.Begin > removal.End {
ranges = append(ranges, r)
continue
}
// trim if the range does intersect
if r.End > removal.End {
ranges = append(ranges, Value_Range{removal.End + 1, r.End})
} else {
if r.Begin >= removal.Begin {
// should never happen
panic("r.Begin >= removal.Begin")
}
ranges = append(ranges, Value_Range{r.Begin, removal.Begin - 1})
}
}
return Ranges(ranges).Squash()
}
// Compare assumes that both Ranges are already in sort-order.
// Returns 0 if rs and right are equivalent, -1 if rs is a subset of right, or else 1
func (rs Ranges) Compare(right Ranges) int {
x, y, result := rs.equiv(right)
if result {
return 0
}
for _, a := range x {
// make sure that this range is a subset of a range in y
matched := false
for _, b := range y {
if a.Begin >= b.Begin && a.End <= b.End {
matched = true
break
}
}
if !matched {
return 1
}
}
return -1
}
// Equivalent assumes that both Ranges are already in sort-order.
func (rs Ranges) Equivalent(right Ranges) (result bool) {
_, _, result = rs.equiv(right)
return
}
// Equivalent assumes that both Ranges are already in sort-order.
func (rs Ranges) equiv(right Ranges) (_, _ Ranges, _ bool) {
// we need to squash rs and right but don't want to change the originals
switch len(rs) {
case 0:
case 1:
rs = Ranges{rs[0]}
default:
rs = Ranges(append([]Value_Range{rs[0], rs[1]}, rs[2:]...)).Sort().Squash()
}
switch len(right) {
case 0:
case 1:
right = Ranges{right[0]}
default:
right = Ranges(append([]Value_Range{right[0], right[1]}, right[2:]...)).Sort().Squash()
}
return rs, right, (&Value_Ranges{Range: rs}).Equal(&Value_Ranges{Range: right})
}
func (rs Ranges) Clone() Ranges {
if len(rs) == 0 {
return nil
}
x := make(Ranges, len(rs))
copy(x, rs)
return x
}
// Min returns the minimum number in Ranges. It will panic on empty Ranges.
func (rs Ranges) Min() uint64 { return rs[0].Begin }
// Max returns the maximum number in Ranges. It will panic on empty Ranges.
func (rs Ranges) Max() uint64 { return rs[len(rs)-1].End }
// resource returns a *Resource with the given name and Ranges.
func (rs Ranges) resource(name string) Resource {
vr := make([]Value_Range, len(rs))
copy(vr, rs)
return Resource{
Name: name,
Type: RANGES.Enum(),
Ranges: &Value_Ranges{Range: vr},
}
}
// uint64s is an utility used to sort a slice of uint64s
type uint64s []uint64
// These three methods implement sort.Interface
func (ns uint64s) Len() int { return len(ns) }
func (ns uint64s) Less(i, j int) bool { return ns[i] < ns[j] }
func (ns uint64s) Swap(i, j int) { ns[i], ns[j] = ns[j], ns[i] }

View File

@ -0,0 +1,5 @@
// Package recordio implements the Mesos variant of RecordIO framing, whereby
// each record is prefixed by a line that indicates the length of the record in
// decimal ASCII. The bytes of the record immediately follow the length-line.
// Zero-length records are allowed.
package recordio

View File

@ -0,0 +1,145 @@
package recordio
import (
"bufio"
"bytes"
"io"
logger "github.com/mesos/mesos-go/api/v1/lib/debug"
"github.com/mesos/mesos-go/api/v1/lib/encoding/framing"
)
const debug = logger.Logger(false)
type (
Opt func(*reader)
reader struct {
*bufio.Scanner
pend int
splitf func(data []byte, atEOF bool) (int, []byte, error)
maxf int // max frame size
}
)
// NewReader returns a reader that parses frames from a recordio stream.
func NewReader(read io.Reader, opt ...Opt) framing.Reader {
debug.Log("new frame reader")
r := &reader{Scanner: bufio.NewScanner(read)}
r.Split(func(data []byte, atEOF bool) (int, []byte, error) {
// Scanner panics if we invoke Split after scanning has started,
// use this proxy func as a work-around.
return r.splitf(data, atEOF)
})
buf := make([]byte, 16*1024)
r.Buffer(buf, 1<<22) // 1<<22 == max protobuf size
r.splitf = r.splitSize
// apply options
for _, f := range opt {
if f != nil {
f(r)
}
}
return r
}
// MaxMessageSize returns a functional option that configures the internal Scanner's buffer and max token (message)
// length, in bytes.
func MaxMessageSize(max int) Opt {
return func(r *reader) {
buf := make([]byte, max>>1)
r.Buffer(buf, max)
r.maxf = max
}
}
func (r *reader) splitSize(data []byte, atEOF bool) (int, []byte, error) {
const maxTokenLength = 20 // textual length of largest uint64 number
if atEOF {
x := len(data)
switch {
case x == 0:
debug.Log("EOF and empty frame, returning io.EOF")
return 0, nil, io.EOF
case x < 2: // min frame size
debug.Log("remaining data less than min total frame length")
return 0, nil, framing.ErrorUnderrun
}
// otherwise, we may have a valid frame...
}
debug.Log("len(data)=", len(data))
adv := 0
for {
i := 0
for ; i < maxTokenLength && i < len(data) && data[i] != '\n'; i++ {
}
debug.Log("i=", i)
if i == len(data) {
debug.Log("need more input")
return 0, nil, nil // need more input
}
if i == maxTokenLength && data[i] != '\n' {
debug.Log("frame size: max token length exceeded")
return 0, nil, framing.ErrorBadSize
}
n, err := ParseUintBytes(bytes.TrimSpace(data[:i]), 10, 64)
if err != nil {
debug.Log("failed to parse frame size field:", err)
return 0, nil, framing.ErrorBadSize
}
if r.maxf != 0 && int(n) > r.maxf {
debug.Log("frame size max length exceeded:", n)
return 0, nil, framing.ErrorOversizedFrame
}
if n == 0 {
// special case... don't invoke splitData, just parse the next size header
adv += i + 1
data = data[i+1:]
continue
}
r.pend = int(n)
r.splitf = r.splitFrame
debug.Logf("split next frame: %d, %d", n, adv+i+1)
return adv + i + 1, data[:0], nil // returning a nil token screws up the Scanner, so return empty
}
}
func (r *reader) splitFrame(data []byte, atEOF bool) (advance int, token []byte, err error) {
x := len(data)
debug.Log("splitFrame:x=", x, ",eof=", atEOF)
if atEOF {
if x < r.pend {
return 0, nil, framing.ErrorUnderrun
}
}
if r.pend == 0 {
panic("asked to read frame data, but no data left in frame")
}
if x < int(r.pend) {
// need more data
return 0, nil, nil
}
r.splitf = r.splitSize
adv := int(r.pend)
r.pend = 0
return adv, data[:adv], nil
}
// ReadFrame implements framing.Reader
func (r *reader) ReadFrame() (tok []byte, err error) {
for r.Scan() {
b := r.Bytes()
if len(b) == 0 {
continue
}
tok = b
debug.Log("len(tok)", len(tok))
break
}
// either scan failed, or it succeeded and we have a token...
err = r.Err()
if err == nil && len(tok) == 0 {
err = io.EOF
}
return
}

View File

@ -0,0 +1,117 @@
/*
Copyright 2013 The Camlistore Authors
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 recordio
import (
"errors"
"strconv"
)
// 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<<uint(bitSize) - 1
for i := 0; i < len(s); i++ {
var v byte
d := s[i]
switch {
case '0' <= d && d <= '9':
v = d - '0'
case 'a' <= d && d <= 'z':
v = d - 'a' + 10
case 'A' <= d && d <= 'Z':
v = d - 'A' + 10
default:
n = 0
err = strconv.ErrSyntax
goto Error
}
if int(v) >= 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
}

View File

@ -0,0 +1,34 @@
package recordio
import (
"io"
"strconv"
)
var lf = []byte{'\n'}
type Writer struct {
out io.Writer
}
func NewWriter(out io.Writer) *Writer {
return &Writer{out}
}
func (w *Writer) writeBuffer(b []byte, err error) error {
if err != nil {
return err
}
n, err := w.out.Write(b)
if err == nil && n != len(b) {
return io.ErrShortWrite
}
return err
}
func (w *Writer) WriteFrame(b []byte) (err error) {
err = w.writeBuffer(([]byte)(strconv.Itoa(len(b))), err)
err = w.writeBuffer(lf, err)
err = w.writeBuffer(b, err)
return
}

1145
vendor/github.com/mesos/mesos-go/api/v1/lib/resources.go generated vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,82 @@
package roles
import (
"fmt"
"strings"
"unicode"
)
// Role is a deprecated type.
type Role string
const defaultRole = Role("*")
func (r Role) IsDefault() bool {
return r == defaultRole
}
func (r Role) Assign() func(interface{}) {
return func(v interface{}) {
type roler interface {
WithRole(string)
}
if ri, ok := v.(roler); ok {
ri.WithRole(string(r))
}
}
}
func (r Role) Proto() *string {
s := string(r)
return &s
}
// IsStrictSubroleOf returns true if left is a strict subrole of right.
func IsStrictSubroleOf(left, right string) bool {
return len(left) > len(right) && left[len(right)] == '/' && strings.HasPrefix(left, right)
}
var illegalComponents = map[string]struct{}{
".": struct{}{},
"..": struct{}{},
"*": struct{}{},
}
func Parse(s string) (string, error) {
if s == string(defaultRole) {
return s, nil
}
if strings.HasPrefix(s, "/") {
return "", fmt.Errorf("role %q cannot start with a slash", s)
}
if strings.HasSuffix(s, "/") {
return "", fmt.Errorf("role %q cannot end with a slash", s)
}
// validate each component in the role path
for _, part := range strings.Split(s, "/") {
if part == "" {
return "", fmt.Errorf("role %q cannot contain two adjacent slashes", s)
}
if bad, found := illegalComponents[part]; found {
return "", fmt.Errorf("role %q cannot contain %q as a component", s, bad)
}
if strings.HasPrefix(part, "-") {
return "", fmt.Errorf("role component %q is invalid because it begins with a dash", part)
}
if strings.IndexFunc(part, func(r rune) bool { return unicode.IsSpace(r) || unicode.IsControl(r) }) > -1 {
return "", fmt.Errorf("role component %q is invalid because it contains backspace or whitespace", part)
}
}
return s, nil
}
func Validate(roles ...string) error {
for i := range roles {
_, err := Parse(roles[i])
if err != nil {
return err
}
}
return nil
}

142
vendor/github.com/mesos/mesos-go/api/v1/lib/values.go generated vendored Normal file
View File

@ -0,0 +1,142 @@
package mesos
func (left *Value_Scalar) Compare(right *Value_Scalar) int {
var (
a = convertToFixed64(left.GetValue())
b = convertToFixed64(right.GetValue())
)
if a < b {
return -1
}
if a > b {
return 1
}
return 0
}
func (left *Value_Ranges) Compare(right *Value_Ranges) int {
return Ranges(left.GetRange()).Compare(right.GetRange())
}
func (left *Value_Set) Compare(right *Value_Set) int {
i, j := left.GetItem(), right.GetItem()
if len(i) <= len(j) {
b := make(map[string]struct{}, len(j))
for _, x := range j {
b[x] = struct{}{}
}
// make sure that each item on the left exists on the right,
// otherwise left is not a subset of right.
a := make(map[string]struct{}, len(i))
for _, x := range i {
if _, ok := b[x]; !ok {
return 1
}
a[x] = struct{}{}
}
// if every item on the right also exists on the left, then
// the sets are equal, otherwise left < right
for x := range b {
if _, ok := a[x]; !ok {
return -1
}
}
return 0
}
return 1
}
func (left *Value_Set) Add(right *Value_Set) *Value_Set {
lefty := left.GetItem()
righty := right.GetItem()
c := len(lefty) + len(righty)
if c == 0 {
return nil
}
m := make(map[string]struct{}, c)
for _, v := range lefty {
m[v] = struct{}{}
}
for _, v := range righty {
m[v] = struct{}{}
}
x := make([]string, 0, len(m))
for v := range m {
x = append(x, v)
}
return &Value_Set{Item: x}
}
func (left *Value_Set) Subtract(right *Value_Set) *Value_Set {
// for each item in right, remove it from left
lefty := left.GetItem()
righty := right.GetItem()
if c := len(lefty); c == 0 {
return nil
} else if len(righty) == 0 {
x := make([]string, c)
copy(x, lefty)
return &Value_Set{Item: x}
}
a := make(map[string]struct{}, len(lefty))
for _, x := range lefty {
a[x] = struct{}{}
}
for _, x := range righty {
delete(a, x)
}
if len(a) == 0 {
return nil
}
i := 0
for k := range a {
lefty[i] = k
i++
}
return &Value_Set{Item: lefty[:len(a)]}
}
func (left *Value_Ranges) Add(right *Value_Ranges) *Value_Ranges {
a, b := Ranges(left.GetRange()), Ranges(right.GetRange())
c := len(a) + len(b)
if c == 0 {
return nil
}
x := make(Ranges, c)
if len(a) > 0 {
copy(x, a)
}
if len(b) > 0 {
copy(x[len(a):], b)
}
return &Value_Ranges{
Range: x.Sort().Squash(),
}
}
func (left *Value_Ranges) Subtract(right *Value_Ranges) *Value_Ranges {
a, b := Ranges(left.GetRange()), Ranges(right.GetRange())
if len(a) > 1 {
x := make(Ranges, len(a))
copy(x, a)
a = x.Sort().Squash()
}
for _, r := range b {
a = a.Remove(r)
}
if len(a) == 0 {
return nil
}
return &Value_Ranges{Range: a}
}
func (left *Value_Scalar) Add(right *Value_Scalar) *Value_Scalar {
sum := convertToFixed64(left.GetValue()) + convertToFixed64(right.GetValue())
return &Value_Scalar{Value: convertToFloat64(sum)}
}
func (left *Value_Scalar) Subtract(right *Value_Scalar) *Value_Scalar {
diff := convertToFixed64(left.GetValue()) - convertToFixed64(right.GetValue())
return &Value_Scalar{Value: convertToFloat64(diff)}
}

202
vendor/github.com/pquerna/ffjson/LICENSE generated vendored Normal file
View File

@ -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.

8
vendor/github.com/pquerna/ffjson/NOTICE generated vendored Normal file
View File

@ -0,0 +1,8 @@
ffjson
Copyright (c) 2014, Paul Querna
This product includes software developed by
Paul Querna (http://paul.querna.org/).
Portions of this software were developed as
part of Go, Copyright (c) 2012 The Go Authors.

421
vendor/github.com/pquerna/ffjson/fflib/v1/buffer.go generated vendored Normal file
View File

@ -0,0 +1,421 @@
// 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.
package v1
// Simple byte buffer for marshaling data.
import (
"bytes"
"encoding/json"
"errors"
"io"
"unicode/utf8"
)
type grower interface {
Grow(n int)
}
type truncater interface {
Truncate(n int)
Reset()
}
type bytesReader interface {
Bytes() []byte
String() string
}
type runeWriter interface {
WriteRune(r rune) (n int, err error)
}
type stringWriter interface {
WriteString(s string) (n int, err error)
}
type lener interface {
Len() int
}
type rewinder interface {
Rewind(n int) (err error)
}
type encoder interface {
Encode(interface{}) error
}
// TODO(pquerna): continue to reduce these interfaces
type EncodingBuffer interface {
io.Writer
io.WriterTo
io.ByteWriter
stringWriter
truncater
grower
rewinder
encoder
}
type DecodingBuffer interface {
io.ReadWriter
io.ByteWriter
stringWriter
runeWriter
truncater
grower
bytesReader
lener
}
// A Buffer is a variable-sized buffer of bytes with Read and Write methods.
// The zero value for Buffer is an empty buffer ready to use.
type Buffer struct {
buf []byte // contents are the bytes buf[off : len(buf)]
off int // read at &buf[off], write at &buf[len(buf)]
runeBytes [utf8.UTFMax]byte // avoid allocation of slice on each WriteByte or Rune
encoder *json.Encoder
skipTrailingByte bool
}
// ErrTooLarge is passed to panic if memory cannot be allocated to store data in a buffer.
var ErrTooLarge = errors.New("fflib.v1.Buffer: too large")
// Bytes returns a slice of the contents of the unread portion of the buffer;
// len(b.Bytes()) == b.Len(). If the caller changes the contents of the
// returned slice, the contents of the buffer will change provided there
// are no intervening method calls on the Buffer.
func (b *Buffer) Bytes() []byte { return b.buf[b.off:] }
// String returns the contents of the unread portion of the buffer
// as a string. If the Buffer is a nil pointer, it returns "<nil>".
func (b *Buffer) String() string {
if b == nil {
// Special case, useful in debugging.
return "<nil>"
}
return string(b.buf[b.off:])
}
// Len returns the number of bytes of the unread portion of the buffer;
// b.Len() == len(b.Bytes()).
func (b *Buffer) Len() int { return len(b.buf) - b.off }
// Truncate discards all but the first n unread bytes from the buffer.
// It panics if n is negative or greater than the length of the buffer.
func (b *Buffer) Truncate(n int) {
if n == 0 {
b.off = 0
b.buf = b.buf[0:0]
} else {
b.buf = b.buf[0 : b.off+n]
}
}
// Reset resets the buffer so it has no content.
// b.Reset() is the same as b.Truncate(0).
func (b *Buffer) Reset() { b.Truncate(0) }
// grow grows the buffer to guarantee space for n more bytes.
// It returns the index where bytes should be written.
// If the buffer can't grow it will panic with ErrTooLarge.
func (b *Buffer) grow(n int) int {
// If we have no buffer, get one from the pool
m := b.Len()
if m == 0 {
if b.buf == nil {
b.buf = makeSlice(2 * n)
b.off = 0
} else if b.off != 0 {
// If buffer is empty, reset to recover space.
b.Truncate(0)
}
}
if len(b.buf)+n > cap(b.buf) {
var buf []byte
if m+n <= cap(b.buf)/2 {
// We can slide things down instead of allocating a new
// slice. We only need m+n <= cap(b.buf) to slide, but
// we instead let capacity get twice as large so we
// don't spend all our time copying.
copy(b.buf[:], b.buf[b.off:])
buf = b.buf[:m]
} else {
// not enough space anywhere
buf = makeSlice(2*cap(b.buf) + n)
copy(buf, b.buf[b.off:])
Pool(b.buf)
b.buf = buf
}
b.off = 0
}
b.buf = b.buf[0 : b.off+m+n]
return b.off + m
}
// Grow grows the buffer's capacity, if necessary, to guarantee space for
// another n bytes. After Grow(n), at least n bytes can be written to the
// buffer without another allocation.
// If n is negative, Grow will panic.
// If the buffer can't grow it will panic with ErrTooLarge.
func (b *Buffer) Grow(n int) {
if n < 0 {
panic("bytes.Buffer.Grow: negative count")
}
m := b.grow(n)
b.buf = b.buf[0:m]
}
// Write appends the contents of p to the buffer, growing the buffer as
// needed. The return value n is the length of p; err is always nil. If the
// buffer becomes too large, Write will panic with ErrTooLarge.
func (b *Buffer) Write(p []byte) (n int, err error) {
if b.skipTrailingByte {
p = p[:len(p)-1]
}
m := b.grow(len(p))
return copy(b.buf[m:], p), nil
}
// WriteString appends the contents of s to the buffer, growing the buffer as
// needed. The return value n is the length of s; err is always nil. If the
// buffer becomes too large, WriteString will panic with ErrTooLarge.
func (b *Buffer) WriteString(s string) (n int, err error) {
m := b.grow(len(s))
return copy(b.buf[m:], s), nil
}
// MinRead is the minimum slice size passed to a Read call by
// Buffer.ReadFrom. As long as the Buffer has at least MinRead bytes beyond
// what is required to hold the contents of r, ReadFrom will not grow the
// underlying buffer.
const minRead = 512
// ReadFrom reads data from r until EOF and appends it to the buffer, growing
// the buffer as needed. The return value n is the number of bytes read. Any
// error except io.EOF encountered during the read is also returned. If the
// buffer becomes too large, ReadFrom will panic with ErrTooLarge.
func (b *Buffer) ReadFrom(r io.Reader) (n int64, err error) {
// If buffer is empty, reset to recover space.
if b.off >= len(b.buf) {
b.Truncate(0)
}
for {
if free := cap(b.buf) - len(b.buf); free < minRead {
// not enough space at end
newBuf := b.buf
if b.off+free < minRead {
// not enough space using beginning of buffer;
// double buffer capacity
newBuf = makeSlice(2*cap(b.buf) + minRead)
}
copy(newBuf, b.buf[b.off:])
Pool(b.buf)
b.buf = newBuf[:len(b.buf)-b.off]
b.off = 0
}
m, e := r.Read(b.buf[len(b.buf):cap(b.buf)])
b.buf = b.buf[0 : len(b.buf)+m]
n += int64(m)
if e == io.EOF {
break
}
if e != nil {
return n, e
}
}
return n, nil // err is EOF, so return nil explicitly
}
// WriteTo writes data to w until the buffer is drained or an error occurs.
// The return value n is the number of bytes written; it always fits into an
// int, but it is int64 to match the io.WriterTo interface. Any error
// encountered during the write is also returned.
func (b *Buffer) WriteTo(w io.Writer) (n int64, err error) {
if b.off < len(b.buf) {
nBytes := b.Len()
m, e := w.Write(b.buf[b.off:])
if m > nBytes {
panic("bytes.Buffer.WriteTo: invalid Write count")
}
b.off += m
n = int64(m)
if e != nil {
return n, e
}
// all bytes should have been written, by definition of
// Write method in io.Writer
if m != nBytes {
return n, io.ErrShortWrite
}
}
// Buffer is now empty; reset.
b.Truncate(0)
return
}
// WriteByte appends the byte c to the buffer, growing the buffer as needed.
// The returned error is always nil, but is included to match bufio.Writer's
// WriteByte. If the buffer becomes too large, WriteByte will panic with
// ErrTooLarge.
func (b *Buffer) WriteByte(c byte) error {
m := b.grow(1)
b.buf[m] = c
return nil
}
func (b *Buffer) Rewind(n int) error {
b.buf = b.buf[:len(b.buf)-n]
return nil
}
func (b *Buffer) Encode(v interface{}) error {
if b.encoder == nil {
b.encoder = json.NewEncoder(b)
}
b.skipTrailingByte = true
err := b.encoder.Encode(v)
b.skipTrailingByte = false
return err
}
// WriteRune appends the UTF-8 encoding of Unicode code point r to the
// buffer, returning its length and an error, which is always nil but is
// included to match bufio.Writer's WriteRune. The buffer is grown as needed;
// if it becomes too large, WriteRune will panic with ErrTooLarge.
func (b *Buffer) WriteRune(r rune) (n int, err error) {
if r < utf8.RuneSelf {
b.WriteByte(byte(r))
return 1, nil
}
n = utf8.EncodeRune(b.runeBytes[0:], r)
b.Write(b.runeBytes[0:n])
return n, nil
}
// Read reads the next len(p) bytes from the buffer or until the buffer
// is drained. The return value n is the number of bytes read. If the
// buffer has no data to return, err is io.EOF (unless len(p) is zero);
// otherwise it is nil.
func (b *Buffer) Read(p []byte) (n int, err error) {
if b.off >= len(b.buf) {
// Buffer is empty, reset to recover space.
b.Truncate(0)
if len(p) == 0 {
return
}
return 0, io.EOF
}
n = copy(p, b.buf[b.off:])
b.off += n
return
}
// Next returns a slice containing the next n bytes from the buffer,
// advancing the buffer as if the bytes had been returned by Read.
// If there are fewer than n bytes in the buffer, Next returns the entire buffer.
// The slice is only valid until the next call to a read or write method.
func (b *Buffer) Next(n int) []byte {
m := b.Len()
if n > m {
n = m
}
data := b.buf[b.off : b.off+n]
b.off += n
return data
}
// ReadByte reads and returns the next byte from the buffer.
// If no byte is available, it returns error io.EOF.
func (b *Buffer) ReadByte() (c byte, err error) {
if b.off >= len(b.buf) {
// Buffer is empty, reset to recover space.
b.Truncate(0)
return 0, io.EOF
}
c = b.buf[b.off]
b.off++
return c, nil
}
// ReadRune reads and returns the next UTF-8-encoded
// Unicode code point from the buffer.
// If no bytes are available, the error returned is io.EOF.
// If the bytes are an erroneous UTF-8 encoding, it
// consumes one byte and returns U+FFFD, 1.
func (b *Buffer) ReadRune() (r rune, size int, err error) {
if b.off >= len(b.buf) {
// Buffer is empty, reset to recover space.
b.Truncate(0)
return 0, 0, io.EOF
}
c := b.buf[b.off]
if c < utf8.RuneSelf {
b.off++
return rune(c), 1, nil
}
r, n := utf8.DecodeRune(b.buf[b.off:])
b.off += n
return r, n, nil
}
// ReadBytes reads until the first occurrence of delim in the input,
// returning a slice containing the data up to and including the delimiter.
// If ReadBytes encounters an error before finding a delimiter,
// it returns the data read before the error and the error itself (often io.EOF).
// ReadBytes returns err != nil if and only if the returned data does not end in
// delim.
func (b *Buffer) ReadBytes(delim byte) (line []byte, err error) {
slice, err := b.readSlice(delim)
// return a copy of slice. The buffer's backing array may
// be overwritten by later calls.
line = append(line, slice...)
return
}
// readSlice is like ReadBytes but returns a reference to internal buffer data.
func (b *Buffer) readSlice(delim byte) (line []byte, err error) {
i := bytes.IndexByte(b.buf[b.off:], delim)
end := b.off + i + 1
if i < 0 {
end = len(b.buf)
err = io.EOF
}
line = b.buf[b.off:end]
b.off = end
return line, err
}
// ReadString reads until the first occurrence of delim in the input,
// returning a string containing the data up to and including the delimiter.
// If ReadString encounters an error before finding a delimiter,
// it returns the data read before the error and the error itself (often io.EOF).
// ReadString returns err != nil if and only if the returned data does not end
// in delim.
func (b *Buffer) ReadString(delim byte) (line string, err error) {
slice, err := b.readSlice(delim)
return string(slice), err
}
// NewBuffer creates and initializes a new Buffer using buf as its initial
// contents. It is intended to prepare a Buffer to read existing data. It
// can also be used to size the internal buffer for writing. To do that,
// buf should have the desired capacity but a length of zero.
//
// In most cases, new(Buffer) (or just declaring a Buffer variable) is
// sufficient to initialize a Buffer.
func NewBuffer(buf []byte) *Buffer { return &Buffer{buf: buf} }
// NewBufferString creates and initializes a new Buffer using string s as its
// initial contents. It is intended to prepare a buffer to read an existing
// string.
//
// In most cases, new(Buffer) (or just declaring a Buffer variable) is
// sufficient to initialize a Buffer.
func NewBufferString(s string) *Buffer {
return &Buffer{buf: []byte(s)}
}

View File

@ -0,0 +1,11 @@
// +build !go1.3
package v1
// Stub version of buffer_pool.go for Go 1.2, which doesn't have sync.Pool.
func Pool(b []byte) {}
func makeSlice(n int) []byte {
return make([]byte, n)
}

View File

@ -0,0 +1,105 @@
// 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 go1.3
package v1
// Allocation pools for Buffers.
import "sync"
var pools [14]sync.Pool
var pool64 *sync.Pool
func init() {
var i uint
// TODO(pquerna): add science here around actual pool sizes.
for i = 6; i < 20; i++ {
n := 1 << i
pools[poolNum(n)].New = func() interface{} { return make([]byte, 0, n) }
}
pool64 = &pools[0]
}
// This returns the pool number that will give a buffer of
// at least 'i' bytes.
func poolNum(i int) int {
// TODO(pquerna): convert to log2 w/ bsr asm instruction:
// <https://groups.google.com/forum/#!topic/golang-nuts/uAb5J1_y7ns>
if i <= 64 {
return 0
} else if i <= 128 {
return 1
} else if i <= 256 {
return 2
} else if i <= 512 {
return 3
} else if i <= 1024 {
return 4
} else if i <= 2048 {
return 5
} else if i <= 4096 {
return 6
} else if i <= 8192 {
return 7
} else if i <= 16384 {
return 8
} else if i <= 32768 {
return 9
} else if i <= 65536 {
return 10
} else if i <= 131072 {
return 11
} else if i <= 262144 {
return 12
} else if i <= 524288 {
return 13
} else {
return -1
}
}
// Send a buffer to the Pool to reuse for other instances.
// You may no longer utilize the content of the buffer, since it may be used
// by other goroutines.
func Pool(b []byte) {
if b == nil {
return
}
c := cap(b)
// Our smallest buffer is 64 bytes, so we discard smaller buffers.
if c < 64 {
return
}
// We need to put the incoming buffer into the NEXT buffer,
// since a buffer guarantees AT LEAST the number of bytes available
// that is the top of this buffer.
// That is the reason for dividing the cap by 2, so it gets into the NEXT bucket.
// We add 2 to avoid rounding down if size is exactly power of 2.
pn := poolNum((c + 2) >> 1)
if pn != -1 {
pools[pn].Put(b[0:0])
}
// if we didn't have a slot for this []byte, we just drop it and let the GC
// take care of it.
}
// makeSlice allocates a slice of size n -- it will attempt to use a pool'ed
// instance whenever possible.
func makeSlice(n int) []byte {
if n <= 64 {
return pool64.Get().([]byte)[0:n]
}
pn := poolNum(n)
if pn != -1 {
return pools[pn].Get().([]byte)[0:n]
} else {
return make([]byte, n)
}
}

88
vendor/github.com/pquerna/ffjson/fflib/v1/bytenum.go generated vendored Normal file
View File

@ -0,0 +1,88 @@
/**
* Copyright 2014 Paul Querna
*
* 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.
*
*/
/* Portions of this file are on Go stdlib's strconv/iota.go */
// 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.
package v1
import (
"github.com/pquerna/ffjson/fflib/v1/internal"
)
func ParseFloat(s []byte, bitSize int) (f float64, err error) {
return internal.ParseFloat(s, bitSize)
}
// ParseUint is like ParseInt but for unsigned numbers, and oeprating on []byte
func ParseUint(s []byte, base int, bitSize int) (n uint64, err error) {
if len(s) == 1 {
switch s[0] {
case '0':
return 0, nil
case '1':
return 1, nil
case '2':
return 2, nil
case '3':
return 3, nil
case '4':
return 4, nil
case '5':
return 5, nil
case '6':
return 6, nil
case '7':
return 7, nil
case '8':
return 8, nil
case '9':
return 9, nil
}
}
return internal.ParseUint(s, base, bitSize)
}
func ParseInt(s []byte, base int, bitSize int) (i int64, err error) {
if len(s) == 1 {
switch s[0] {
case '0':
return 0, nil
case '1':
return 1, nil
case '2':
return 2, nil
case '3':
return 3, nil
case '4':
return 4, nil
case '5':
return 5, nil
case '6':
return 6, nil
case '7':
return 7, nil
case '8':
return 8, nil
case '9':
return 9, nil
}
}
return internal.ParseInt(s, base, bitSize)
}

378
vendor/github.com/pquerna/ffjson/fflib/v1/decimal.go generated vendored Normal file
View File

@ -0,0 +1,378 @@
// 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.
// Multiprecision decimal numbers.
// For floating-point formatting only; not general purpose.
// Only operations are assign and (binary) left/right shift.
// Can do binary floating point in multiprecision decimal precisely
// because 2 divides 10; cannot do decimal floating point
// in multiprecision binary precisely.
package v1
type decimal struct {
d [800]byte // digits
nd int // number of digits used
dp int // decimal point
neg bool
trunc bool // discarded nonzero digits beyond d[:nd]
}
func (a *decimal) String() string {
n := 10 + a.nd
if a.dp > 0 {
n += a.dp
}
if a.dp < 0 {
n += -a.dp
}
buf := make([]byte, n)
w := 0
switch {
case a.nd == 0:
return "0"
case a.dp <= 0:
// zeros fill space between decimal point and digits
buf[w] = '0'
w++
buf[w] = '.'
w++
w += digitZero(buf[w : w+-a.dp])
w += copy(buf[w:], a.d[0:a.nd])
case a.dp < a.nd:
// decimal point in middle of digits
w += copy(buf[w:], a.d[0:a.dp])
buf[w] = '.'
w++
w += copy(buf[w:], a.d[a.dp:a.nd])
default:
// zeros fill space between digits and decimal point
w += copy(buf[w:], a.d[0:a.nd])
w += digitZero(buf[w : w+a.dp-a.nd])
}
return string(buf[0:w])
}
func digitZero(dst []byte) int {
for i := range dst {
dst[i] = '0'
}
return len(dst)
}
// trim trailing zeros from number.
// (They are meaningless; the decimal point is tracked
// independent of the number of digits.)
func trim(a *decimal) {
for a.nd > 0 && a.d[a.nd-1] == '0' {
a.nd--
}
if a.nd == 0 {
a.dp = 0
}
}
// Assign v to a.
func (a *decimal) Assign(v uint64) {
var buf [24]byte
// Write reversed decimal in buf.
n := 0
for v > 0 {
v1 := v / 10
v -= 10 * v1
buf[n] = byte(v + '0')
n++
v = v1
}
// Reverse again to produce forward decimal in a.d.
a.nd = 0
for n--; n >= 0; n-- {
a.d[a.nd] = buf[n]
a.nd++
}
a.dp = a.nd
trim(a)
}
// Maximum shift that we can do in one pass without overflow.
// Signed int has 31 bits, and we have to be able to accommodate 9<<k.
const maxShift = 27
// Binary shift right (* 2) by k bits. k <= maxShift to avoid overflow.
func rightShift(a *decimal, k uint) {
r := 0 // read pointer
w := 0 // write pointer
// Pick up enough leading digits to cover first shift.
n := 0
for ; n>>k == 0; r++ {
if r >= a.nd {
if n == 0 {
// a == 0; shouldn't get here, but handle anyway.
a.nd = 0
return
}
for n>>k == 0 {
n = n * 10
r++
}
break
}
c := int(a.d[r])
n = n*10 + c - '0'
}
a.dp -= r - 1
// Pick up a digit, put down a digit.
for ; r < a.nd; r++ {
c := int(a.d[r])
dig := n >> k
n -= dig << k
a.d[w] = byte(dig + '0')
w++
n = n*10 + c - '0'
}
// Put down extra digits.
for n > 0 {
dig := n >> k
n -= dig << k
if w < len(a.d) {
a.d[w] = byte(dig + '0')
w++
} else if dig > 0 {
a.trunc = true
}
n = n * 10
}
a.nd = w
trim(a)
}
// Cheat sheet for left shift: table indexed by shift count giving
// number of new digits that will be introduced by that shift.
//
// For example, leftcheats[4] = {2, "625"}. That means that
// if we are shifting by 4 (multiplying by 16), it will add 2 digits
// when the string prefix is "625" through "999", and one fewer digit
// if the string prefix is "000" through "624".
//
// Credit for this trick goes to Ken.
type leftCheat struct {
delta int // number of new digits
cutoff string // minus one digit if original < a.
}
var leftcheats = []leftCheat{
// Leading digits of 1/2^i = 5^i.
// 5^23 is not an exact 64-bit floating point number,
// so have to use bc for the math.
/*
seq 27 | sed 's/^/5^/' | bc |
awk 'BEGIN{ print "\tleftCheat{ 0, \"\" }," }
{
log2 = log(2)/log(10)
printf("\tleftCheat{ %d, \"%s\" },\t// * %d\n",
int(log2*NR+1), $0, 2**NR)
}'
*/
{0, ""},
{1, "5"}, // * 2
{1, "25"}, // * 4
{1, "125"}, // * 8
{2, "625"}, // * 16
{2, "3125"}, // * 32
{2, "15625"}, // * 64
{3, "78125"}, // * 128
{3, "390625"}, // * 256
{3, "1953125"}, // * 512
{4, "9765625"}, // * 1024
{4, "48828125"}, // * 2048
{4, "244140625"}, // * 4096
{4, "1220703125"}, // * 8192
{5, "6103515625"}, // * 16384
{5, "30517578125"}, // * 32768
{5, "152587890625"}, // * 65536
{6, "762939453125"}, // * 131072
{6, "3814697265625"}, // * 262144
{6, "19073486328125"}, // * 524288
{7, "95367431640625"}, // * 1048576
{7, "476837158203125"}, // * 2097152
{7, "2384185791015625"}, // * 4194304
{7, "11920928955078125"}, // * 8388608
{8, "59604644775390625"}, // * 16777216
{8, "298023223876953125"}, // * 33554432
{8, "1490116119384765625"}, // * 67108864
{9, "7450580596923828125"}, // * 134217728
}
// Is the leading prefix of b lexicographically less than s?
func prefixIsLessThan(b []byte, s string) bool {
for i := 0; i < len(s); i++ {
if i >= len(b) {
return true
}
if b[i] != s[i] {
return b[i] < s[i]
}
}
return false
}
// Binary shift left (/ 2) by k bits. k <= maxShift to avoid overflow.
func leftShift(a *decimal, k uint) {
delta := leftcheats[k].delta
if prefixIsLessThan(a.d[0:a.nd], leftcheats[k].cutoff) {
delta--
}
r := a.nd // read index
w := a.nd + delta // write index
n := 0
// Pick up a digit, put down a digit.
for r--; r >= 0; r-- {
n += (int(a.d[r]) - '0') << k
quo := n / 10
rem := n - 10*quo
w--
if w < len(a.d) {
a.d[w] = byte(rem + '0')
} else if rem != 0 {
a.trunc = true
}
n = quo
}
// Put down extra digits.
for n > 0 {
quo := n / 10
rem := n - 10*quo
w--
if w < len(a.d) {
a.d[w] = byte(rem + '0')
} else if rem != 0 {
a.trunc = true
}
n = quo
}
a.nd += delta
if a.nd >= len(a.d) {
a.nd = len(a.d)
}
a.dp += delta
trim(a)
}
// Binary shift left (k > 0) or right (k < 0).
func (a *decimal) Shift(k int) {
switch {
case a.nd == 0:
// nothing to do: a == 0
case k > 0:
for k > maxShift {
leftShift(a, maxShift)
k -= maxShift
}
leftShift(a, uint(k))
case k < 0:
for k < -maxShift {
rightShift(a, maxShift)
k += maxShift
}
rightShift(a, uint(-k))
}
}
// If we chop a at nd digits, should we round up?
func shouldRoundUp(a *decimal, nd int) bool {
if nd < 0 || nd >= a.nd {
return false
}
if a.d[nd] == '5' && nd+1 == a.nd { // exactly halfway - round to even
// if we truncated, a little higher than what's recorded - always round up
if a.trunc {
return true
}
return nd > 0 && (a.d[nd-1]-'0')%2 != 0
}
// not halfway - digit tells all
return a.d[nd] >= '5'
}
// Round a to nd digits (or fewer).
// If nd is zero, it means we're rounding
// just to the left of the digits, as in
// 0.09 -> 0.1.
func (a *decimal) Round(nd int) {
if nd < 0 || nd >= a.nd {
return
}
if shouldRoundUp(a, nd) {
a.RoundUp(nd)
} else {
a.RoundDown(nd)
}
}
// Round a down to nd digits (or fewer).
func (a *decimal) RoundDown(nd int) {
if nd < 0 || nd >= a.nd {
return
}
a.nd = nd
trim(a)
}
// Round a up to nd digits (or fewer).
func (a *decimal) RoundUp(nd int) {
if nd < 0 || nd >= a.nd {
return
}
// round up
for i := nd - 1; i >= 0; i-- {
c := a.d[i]
if c < '9' { // can stop after this digit
a.d[i]++
a.nd = i + 1
return
}
}
// Number is all 9s.
// Change to single 1 with adjusted decimal point.
a.d[0] = '1'
a.nd = 1
a.dp++
}
// Extract integer part, rounded appropriately.
// No guarantees about overflow.
func (a *decimal) RoundedInteger() uint64 {
if a.dp > 20 {
return 0xFFFFFFFFFFFFFFFF
}
var i int
n := uint64(0)
for i = 0; i < a.dp && i < a.nd; i++ {
n = n*10 + uint64(a.d[i]-'0')
}
for ; i < a.dp; i++ {
n *= 10
}
if shouldRoundUp(a, a.dp) {
n++
}
return n
}

668
vendor/github.com/pquerna/ffjson/fflib/v1/extfloat.go generated vendored Normal file
View File

@ -0,0 +1,668 @@
// 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 v1
// An extFloat represents an extended floating-point number, with more
// precision than a float64. It does not try to save bits: the
// number represented by the structure is mant*(2^exp), with a negative
// sign if neg is true.
type extFloat struct {
mant uint64
exp int
neg bool
}
// Powers of ten taken from double-conversion library.
// http://code.google.com/p/double-conversion/
const (
firstPowerOfTen = -348
stepPowerOfTen = 8
)
var smallPowersOfTen = [...]extFloat{
{1 << 63, -63, false}, // 1
{0xa << 60, -60, false}, // 1e1
{0x64 << 57, -57, false}, // 1e2
{0x3e8 << 54, -54, false}, // 1e3
{0x2710 << 50, -50, false}, // 1e4
{0x186a0 << 47, -47, false}, // 1e5
{0xf4240 << 44, -44, false}, // 1e6
{0x989680 << 40, -40, false}, // 1e7
}
var powersOfTen = [...]extFloat{
{0xfa8fd5a0081c0288, -1220, false}, // 10^-348
{0xbaaee17fa23ebf76, -1193, false}, // 10^-340
{0x8b16fb203055ac76, -1166, false}, // 10^-332
{0xcf42894a5dce35ea, -1140, false}, // 10^-324
{0x9a6bb0aa55653b2d, -1113, false}, // 10^-316
{0xe61acf033d1a45df, -1087, false}, // 10^-308
{0xab70fe17c79ac6ca, -1060, false}, // 10^-300
{0xff77b1fcbebcdc4f, -1034, false}, // 10^-292
{0xbe5691ef416bd60c, -1007, false}, // 10^-284
{0x8dd01fad907ffc3c, -980, false}, // 10^-276
{0xd3515c2831559a83, -954, false}, // 10^-268
{0x9d71ac8fada6c9b5, -927, false}, // 10^-260
{0xea9c227723ee8bcb, -901, false}, // 10^-252
{0xaecc49914078536d, -874, false}, // 10^-244
{0x823c12795db6ce57, -847, false}, // 10^-236
{0xc21094364dfb5637, -821, false}, // 10^-228
{0x9096ea6f3848984f, -794, false}, // 10^-220
{0xd77485cb25823ac7, -768, false}, // 10^-212
{0xa086cfcd97bf97f4, -741, false}, // 10^-204
{0xef340a98172aace5, -715, false}, // 10^-196
{0xb23867fb2a35b28e, -688, false}, // 10^-188
{0x84c8d4dfd2c63f3b, -661, false}, // 10^-180
{0xc5dd44271ad3cdba, -635, false}, // 10^-172
{0x936b9fcebb25c996, -608, false}, // 10^-164
{0xdbac6c247d62a584, -582, false}, // 10^-156
{0xa3ab66580d5fdaf6, -555, false}, // 10^-148
{0xf3e2f893dec3f126, -529, false}, // 10^-140
{0xb5b5ada8aaff80b8, -502, false}, // 10^-132
{0x87625f056c7c4a8b, -475, false}, // 10^-124
{0xc9bcff6034c13053, -449, false}, // 10^-116
{0x964e858c91ba2655, -422, false}, // 10^-108
{0xdff9772470297ebd, -396, false}, // 10^-100
{0xa6dfbd9fb8e5b88f, -369, false}, // 10^-92
{0xf8a95fcf88747d94, -343, false}, // 10^-84
{0xb94470938fa89bcf, -316, false}, // 10^-76
{0x8a08f0f8bf0f156b, -289, false}, // 10^-68
{0xcdb02555653131b6, -263, false}, // 10^-60
{0x993fe2c6d07b7fac, -236, false}, // 10^-52
{0xe45c10c42a2b3b06, -210, false}, // 10^-44
{0xaa242499697392d3, -183, false}, // 10^-36
{0xfd87b5f28300ca0e, -157, false}, // 10^-28
{0xbce5086492111aeb, -130, false}, // 10^-20
{0x8cbccc096f5088cc, -103, false}, // 10^-12
{0xd1b71758e219652c, -77, false}, // 10^-4
{0x9c40000000000000, -50, false}, // 10^4
{0xe8d4a51000000000, -24, false}, // 10^12
{0xad78ebc5ac620000, 3, false}, // 10^20
{0x813f3978f8940984, 30, false}, // 10^28
{0xc097ce7bc90715b3, 56, false}, // 10^36
{0x8f7e32ce7bea5c70, 83, false}, // 10^44
{0xd5d238a4abe98068, 109, false}, // 10^52
{0x9f4f2726179a2245, 136, false}, // 10^60
{0xed63a231d4c4fb27, 162, false}, // 10^68
{0xb0de65388cc8ada8, 189, false}, // 10^76
{0x83c7088e1aab65db, 216, false}, // 10^84
{0xc45d1df942711d9a, 242, false}, // 10^92
{0x924d692ca61be758, 269, false}, // 10^100
{0xda01ee641a708dea, 295, false}, // 10^108
{0xa26da3999aef774a, 322, false}, // 10^116
{0xf209787bb47d6b85, 348, false}, // 10^124
{0xb454e4a179dd1877, 375, false}, // 10^132
{0x865b86925b9bc5c2, 402, false}, // 10^140
{0xc83553c5c8965d3d, 428, false}, // 10^148
{0x952ab45cfa97a0b3, 455, false}, // 10^156
{0xde469fbd99a05fe3, 481, false}, // 10^164
{0xa59bc234db398c25, 508, false}, // 10^172
{0xf6c69a72a3989f5c, 534, false}, // 10^180
{0xb7dcbf5354e9bece, 561, false}, // 10^188
{0x88fcf317f22241e2, 588, false}, // 10^196
{0xcc20ce9bd35c78a5, 614, false}, // 10^204
{0x98165af37b2153df, 641, false}, // 10^212
{0xe2a0b5dc971f303a, 667, false}, // 10^220
{0xa8d9d1535ce3b396, 694, false}, // 10^228
{0xfb9b7cd9a4a7443c, 720, false}, // 10^236
{0xbb764c4ca7a44410, 747, false}, // 10^244
{0x8bab8eefb6409c1a, 774, false}, // 10^252
{0xd01fef10a657842c, 800, false}, // 10^260
{0x9b10a4e5e9913129, 827, false}, // 10^268
{0xe7109bfba19c0c9d, 853, false}, // 10^276
{0xac2820d9623bf429, 880, false}, // 10^284
{0x80444b5e7aa7cf85, 907, false}, // 10^292
{0xbf21e44003acdd2d, 933, false}, // 10^300
{0x8e679c2f5e44ff8f, 960, false}, // 10^308
{0xd433179d9c8cb841, 986, false}, // 10^316
{0x9e19db92b4e31ba9, 1013, false}, // 10^324
{0xeb96bf6ebadf77d9, 1039, false}, // 10^332
{0xaf87023b9bf0ee6b, 1066, false}, // 10^340
}
// floatBits returns the bits of the float64 that best approximates
// the extFloat passed as receiver. Overflow is set to true if
// the resulting float64 is ±Inf.
func (f *extFloat) floatBits(flt *floatInfo) (bits uint64, overflow bool) {
f.Normalize()
exp := f.exp + 63
// Exponent too small.
if exp < flt.bias+1 {
n := flt.bias + 1 - exp
f.mant >>= uint(n)
exp += n
}
// Extract 1+flt.mantbits bits from the 64-bit mantissa.
mant := f.mant >> (63 - flt.mantbits)
if f.mant&(1<<(62-flt.mantbits)) != 0 {
// Round up.
mant += 1
}
// Rounding might have added a bit; shift down.
if mant == 2<<flt.mantbits {
mant >>= 1
exp++
}
// Infinities.
if exp-flt.bias >= 1<<flt.expbits-1 {
// ±Inf
mant = 0
exp = 1<<flt.expbits - 1 + flt.bias
overflow = true
} else if mant&(1<<flt.mantbits) == 0 {
// Denormalized?
exp = flt.bias
}
// Assemble bits.
bits = mant & (uint64(1)<<flt.mantbits - 1)
bits |= uint64((exp-flt.bias)&(1<<flt.expbits-1)) << flt.mantbits
if f.neg {
bits |= 1 << (flt.mantbits + flt.expbits)
}
return
}
// AssignComputeBounds sets f to the floating point value
// defined by mant, exp and precision given by flt. It returns
// lower, upper such that any number in the closed interval
// [lower, upper] is converted back to the same floating point number.
func (f *extFloat) AssignComputeBounds(mant uint64, exp int, neg bool, flt *floatInfo) (lower, upper extFloat) {
f.mant = mant
f.exp = exp - int(flt.mantbits)
f.neg = neg
if f.exp <= 0 && mant == (mant>>uint(-f.exp))<<uint(-f.exp) {
// An exact integer
f.mant >>= uint(-f.exp)
f.exp = 0
return *f, *f
}
expBiased := exp - flt.bias
upper = extFloat{mant: 2*f.mant + 1, exp: f.exp - 1, neg: f.neg}
if mant != 1<<flt.mantbits || expBiased == 1 {
lower = extFloat{mant: 2*f.mant - 1, exp: f.exp - 1, neg: f.neg}
} else {
lower = extFloat{mant: 4*f.mant - 1, exp: f.exp - 2, neg: f.neg}
}
return
}
// Normalize normalizes f so that the highest bit of the mantissa is
// set, and returns the number by which the mantissa was left-shifted.
func (f *extFloat) Normalize() (shift uint) {
mant, exp := f.mant, f.exp
if mant == 0 {
return 0
}
if mant>>(64-32) == 0 {
mant <<= 32
exp -= 32
}
if mant>>(64-16) == 0 {
mant <<= 16
exp -= 16
}
if mant>>(64-8) == 0 {
mant <<= 8
exp -= 8
}
if mant>>(64-4) == 0 {
mant <<= 4
exp -= 4
}
if mant>>(64-2) == 0 {
mant <<= 2
exp -= 2
}
if mant>>(64-1) == 0 {
mant <<= 1
exp -= 1
}
shift = uint(f.exp - exp)
f.mant, f.exp = mant, exp
return
}
// Multiply sets f to the product f*g: the result is correctly rounded,
// but not normalized.
func (f *extFloat) Multiply(g extFloat) {
fhi, flo := f.mant>>32, uint64(uint32(f.mant))
ghi, glo := g.mant>>32, uint64(uint32(g.mant))
// Cross products.
cross1 := fhi * glo
cross2 := flo * ghi
// f.mant*g.mant is fhi*ghi << 64 + (cross1+cross2) << 32 + flo*glo
f.mant = fhi*ghi + (cross1 >> 32) + (cross2 >> 32)
rem := uint64(uint32(cross1)) + uint64(uint32(cross2)) + ((flo * glo) >> 32)
// Round up.
rem += (1 << 31)
f.mant += (rem >> 32)
f.exp = f.exp + g.exp + 64
}
var uint64pow10 = [...]uint64{
1, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
}
// AssignDecimal sets f to an approximate value mantissa*10^exp. It
// returns true if the value represented by f is guaranteed to be the
// best approximation of d after being rounded to a float64 or
// float32 depending on flt.
func (f *extFloat) AssignDecimal(mantissa uint64, exp10 int, neg bool, trunc bool, flt *floatInfo) (ok bool) {
const uint64digits = 19
const errorscale = 8
errors := 0 // An upper bound for error, computed in errorscale*ulp.
if trunc {
// the decimal number was truncated.
errors += errorscale / 2
}
f.mant = mantissa
f.exp = 0
f.neg = neg
// Multiply by powers of ten.
i := (exp10 - firstPowerOfTen) / stepPowerOfTen
if exp10 < firstPowerOfTen || i >= len(powersOfTen) {
return false
}
adjExp := (exp10 - firstPowerOfTen) % stepPowerOfTen
// We multiply by exp%step
if adjExp < uint64digits && mantissa < uint64pow10[uint64digits-adjExp] {
// We can multiply the mantissa exactly.
f.mant *= uint64pow10[adjExp]
f.Normalize()
} else {
f.Normalize()
f.Multiply(smallPowersOfTen[adjExp])
errors += errorscale / 2
}
// We multiply by 10 to the exp - exp%step.
f.Multiply(powersOfTen[i])
if errors > 0 {
errors += 1
}
errors += errorscale / 2
// Normalize
shift := f.Normalize()
errors <<= shift
// Now f is a good approximation of the decimal.
// Check whether the error is too large: that is, if the mantissa
// is perturbated by the error, the resulting float64 will change.
// The 64 bits mantissa is 1 + 52 bits for float64 + 11 extra bits.
//
// In many cases the approximation will be good enough.
denormalExp := flt.bias - 63
var extrabits uint
if f.exp <= denormalExp {
// f.mant * 2^f.exp is smaller than 2^(flt.bias+1).
extrabits = uint(63 - flt.mantbits + 1 + uint(denormalExp-f.exp))
} else {
extrabits = uint(63 - flt.mantbits)
}
halfway := uint64(1) << (extrabits - 1)
mant_extra := f.mant & (1<<extrabits - 1)
// Do a signed comparison here! If the error estimate could make
// the mantissa round differently for the conversion to double,
// then we can't give a definite answer.
if int64(halfway)-int64(errors) < int64(mant_extra) &&
int64(mant_extra) < int64(halfway)+int64(errors) {
return false
}
return true
}
// Frexp10 is an analogue of math.Frexp for decimal powers. It scales
// f by an approximate power of ten 10^-exp, and returns exp10, so
// that f*10^exp10 has the same value as the old f, up to an ulp,
// as well as the index of 10^-exp in the powersOfTen table.
func (f *extFloat) frexp10() (exp10, index int) {
// The constants expMin and expMax constrain the final value of the
// binary exponent of f. We want a small integral part in the result
// because finding digits of an integer requires divisions, whereas
// digits of the fractional part can be found by repeatedly multiplying
// by 10.
const expMin = -60
const expMax = -32
// Find power of ten such that x * 10^n has a binary exponent
// between expMin and expMax.
approxExp10 := ((expMin+expMax)/2 - f.exp) * 28 / 93 // log(10)/log(2) is close to 93/28.
i := (approxExp10 - firstPowerOfTen) / stepPowerOfTen
Loop:
for {
exp := f.exp + powersOfTen[i].exp + 64
switch {
case exp < expMin:
i++
case exp > expMax:
i--
default:
break Loop
}
}
// Apply the desired decimal shift on f. It will have exponent
// in the desired range. This is multiplication by 10^-exp10.
f.Multiply(powersOfTen[i])
return -(firstPowerOfTen + i*stepPowerOfTen), i
}
// frexp10Many applies a common shift by a power of ten to a, b, c.
func frexp10Many(a, b, c *extFloat) (exp10 int) {
exp10, i := c.frexp10()
a.Multiply(powersOfTen[i])
b.Multiply(powersOfTen[i])
return
}
// FixedDecimal stores in d the first n significant digits
// of the decimal representation of f. It returns false
// if it cannot be sure of the answer.
func (f *extFloat) FixedDecimal(d *decimalSlice, n int) bool {
if f.mant == 0 {
d.nd = 0
d.dp = 0
d.neg = f.neg
return true
}
if n == 0 {
panic("strconv: internal error: extFloat.FixedDecimal called with n == 0")
}
// Multiply by an appropriate power of ten to have a reasonable
// number to process.
f.Normalize()
exp10, _ := f.frexp10()
shift := uint(-f.exp)
integer := uint32(f.mant >> shift)
fraction := f.mant - (uint64(integer) << shift)
ε := uint64(1) // ε is the uncertainty we have on the mantissa of f.
// Write exactly n digits to d.
needed := n // how many digits are left to write.
integerDigits := 0 // the number of decimal digits of integer.
pow10 := uint64(1) // the power of ten by which f was scaled.
for i, pow := 0, uint64(1); i < 20; i++ {
if pow > uint64(integer) {
integerDigits = i
break
}
pow *= 10
}
rest := integer
if integerDigits > needed {
// the integral part is already large, trim the last digits.
pow10 = uint64pow10[integerDigits-needed]
integer /= uint32(pow10)
rest -= integer * uint32(pow10)
} else {
rest = 0
}
// Write the digits of integer: the digits of rest are omitted.
var buf [32]byte
pos := len(buf)
for v := integer; v > 0; {
v1 := v / 10
v -= 10 * v1
pos--
buf[pos] = byte(v + '0')
v = v1
}
for i := pos; i < len(buf); i++ {
d.d[i-pos] = buf[i]
}
nd := len(buf) - pos
d.nd = nd
d.dp = integerDigits + exp10
needed -= nd
if needed > 0 {
if rest != 0 || pow10 != 1 {
panic("strconv: internal error, rest != 0 but needed > 0")
}
// Emit digits for the fractional part. Each time, 10*fraction
// fits in a uint64 without overflow.
for needed > 0 {
fraction *= 10
ε *= 10 // the uncertainty scales as we multiply by ten.
if 2*ε > 1<<shift {
// the error is so large it could modify which digit to write, abort.
return false
}
digit := fraction >> shift
d.d[nd] = byte(digit + '0')
fraction -= digit << shift
nd++
needed--
}
d.nd = nd
}
// We have written a truncation of f (a numerator / 10^d.dp). The remaining part
// can be interpreted as a small number (< 1) to be added to the last digit of the
// numerator.
//
// If rest > 0, the amount is:
// (rest<<shift | fraction) / (pow10 << shift)
// fraction being known with a ±ε uncertainty.
// The fact that n > 0 guarantees that pow10 << shift does not overflow a uint64.
//
// If rest = 0, pow10 == 1 and the amount is
// fraction / (1 << shift)
// fraction being known with a ±ε uncertainty.
//
// We pass this information to the rounding routine for adjustment.
ok := adjustLastDigitFixed(d, uint64(rest)<<shift|fraction, pow10, shift, ε)
if !ok {
return false
}
// Trim trailing zeros.
for i := d.nd - 1; i >= 0; i-- {
if d.d[i] != '0' {
d.nd = i + 1
break
}
}
return true
}
// adjustLastDigitFixed assumes d contains the representation of the integral part
// of some number, whose fractional part is num / (den << shift). The numerator
// num is only known up to an uncertainty of size ε, assumed to be less than
// (den << shift)/2.
//
// It will increase the last digit by one to account for correct rounding, typically
// when the fractional part is greater than 1/2, and will return false if ε is such
// that no correct answer can be given.
func adjustLastDigitFixed(d *decimalSlice, num, den uint64, shift uint, ε uint64) bool {
if num > den<<shift {
panic("strconv: num > den<<shift in adjustLastDigitFixed")
}
if 2*ε > den<<shift {
panic("strconv: ε > (den<<shift)/2")
}
if 2*(num+ε) < den<<shift {
return true
}
if 2*(num-ε) > den<<shift {
// increment d by 1.
i := d.nd - 1
for ; i >= 0; i-- {
if d.d[i] == '9' {
d.nd--
} else {
break
}
}
if i < 0 {
d.d[0] = '1'
d.nd = 1
d.dp++
} else {
d.d[i]++
}
return true
}
return false
}
// ShortestDecimal stores in d the shortest decimal representation of f
// which belongs to the open interval (lower, upper), where f is supposed
// to lie. It returns false whenever the result is unsure. The implementation
// uses the Grisu3 algorithm.
func (f *extFloat) ShortestDecimal(d *decimalSlice, lower, upper *extFloat) bool {
if f.mant == 0 {
d.nd = 0
d.dp = 0
d.neg = f.neg
return true
}
if f.exp == 0 && *lower == *f && *lower == *upper {
// an exact integer.
var buf [24]byte
n := len(buf) - 1
for v := f.mant; v > 0; {
v1 := v / 10
v -= 10 * v1
buf[n] = byte(v + '0')
n--
v = v1
}
nd := len(buf) - n - 1
for i := 0; i < nd; i++ {
d.d[i] = buf[n+1+i]
}
d.nd, d.dp = nd, nd
for d.nd > 0 && d.d[d.nd-1] == '0' {
d.nd--
}
if d.nd == 0 {
d.dp = 0
}
d.neg = f.neg
return true
}
upper.Normalize()
// Uniformize exponents.
if f.exp > upper.exp {
f.mant <<= uint(f.exp - upper.exp)
f.exp = upper.exp
}
if lower.exp > upper.exp {
lower.mant <<= uint(lower.exp - upper.exp)
lower.exp = upper.exp
}
exp10 := frexp10Many(lower, f, upper)
// Take a safety margin due to rounding in frexp10Many, but we lose precision.
upper.mant++
lower.mant--
// The shortest representation of f is either rounded up or down, but
// in any case, it is a truncation of upper.
shift := uint(-upper.exp)
integer := uint32(upper.mant >> shift)
fraction := upper.mant - (uint64(integer) << shift)
// How far we can go down from upper until the result is wrong.
allowance := upper.mant - lower.mant
// How far we should go to get a very precise result.
targetDiff := upper.mant - f.mant
// Count integral digits: there are at most 10.
var integerDigits int
for i, pow := 0, uint64(1); i < 20; i++ {
if pow > uint64(integer) {
integerDigits = i
break
}
pow *= 10
}
for i := 0; i < integerDigits; i++ {
pow := uint64pow10[integerDigits-i-1]
digit := integer / uint32(pow)
d.d[i] = byte(digit + '0')
integer -= digit * uint32(pow)
// evaluate whether we should stop.
if currentDiff := uint64(integer)<<shift + fraction; currentDiff < allowance {
d.nd = i + 1
d.dp = integerDigits + exp10
d.neg = f.neg
// Sometimes allowance is so large the last digit might need to be
// decremented to get closer to f.
return adjustLastDigit(d, currentDiff, targetDiff, allowance, pow<<shift, 2)
}
}
d.nd = integerDigits
d.dp = d.nd + exp10
d.neg = f.neg
// Compute digits of the fractional part. At each step fraction does not
// overflow. The choice of minExp implies that fraction is less than 2^60.
var digit int
multiplier := uint64(1)
for {
fraction *= 10
multiplier *= 10
digit = int(fraction >> shift)
d.d[d.nd] = byte(digit + '0')
d.nd++
fraction -= uint64(digit) << shift
if fraction < allowance*multiplier {
// We are in the admissible range. Note that if allowance is about to
// overflow, that is, allowance > 2^64/10, the condition is automatically
// true due to the limited range of fraction.
return adjustLastDigit(d,
fraction, targetDiff*multiplier, allowance*multiplier,
1<<shift, multiplier*2)
}
}
}
// adjustLastDigit modifies d = x-currentDiff*ε, to get closest to
// d = x-targetDiff*ε, without becoming smaller than x-maxDiff*ε.
// It assumes that a decimal digit is worth ulpDecimal*ε, and that
// all data is known with a error estimate of ulpBinary*ε.
func adjustLastDigit(d *decimalSlice, currentDiff, targetDiff, maxDiff, ulpDecimal, ulpBinary uint64) bool {
if ulpDecimal < 2*ulpBinary {
// Approximation is too wide.
return false
}
for currentDiff+ulpDecimal/2+ulpBinary < targetDiff {
d.d[d.nd-1]--
currentDiff += ulpDecimal
}
if currentDiff+ulpDecimal <= targetDiff+ulpDecimal/2+ulpBinary {
// we have two choices, and don't know what to do.
return false
}
if currentDiff < ulpBinary || currentDiff > maxDiff-ulpBinary {
// we went too far
return false
}
if d.nd == 1 && d.d[0] == '0' {
// the number has actually reached zero.
d.nd = 0
d.dp = 0
}
return true
}

121
vendor/github.com/pquerna/ffjson/fflib/v1/fold.go generated vendored Normal file
View File

@ -0,0 +1,121 @@
/**
* Copyright 2014 Paul Querna
*
* 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.
*
*/
/* Portions of this file are on Go stdlib's encoding/json/fold.go */
// 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.
package v1
import (
"unicode/utf8"
)
const (
caseMask = ^byte(0x20) // Mask to ignore case in ASCII.
kelvin = '\u212a'
smallLongEss = '\u017f'
)
// equalFoldRight is a specialization of bytes.EqualFold when s is
// known to be all ASCII (including punctuation), but contains an 's',
// 'S', 'k', or 'K', requiring a Unicode fold on the bytes in t.
// See comments on foldFunc.
func EqualFoldRight(s, t []byte) bool {
for _, sb := range s {
if len(t) == 0 {
return false
}
tb := t[0]
if tb < utf8.RuneSelf {
if sb != tb {
sbUpper := sb & caseMask
if 'A' <= sbUpper && sbUpper <= 'Z' {
if sbUpper != tb&caseMask {
return false
}
} else {
return false
}
}
t = t[1:]
continue
}
// sb is ASCII and t is not. t must be either kelvin
// sign or long s; sb must be s, S, k, or K.
tr, size := utf8.DecodeRune(t)
switch sb {
case 's', 'S':
if tr != smallLongEss {
return false
}
case 'k', 'K':
if tr != kelvin {
return false
}
default:
return false
}
t = t[size:]
}
if len(t) > 0 {
return false
}
return true
}
// asciiEqualFold is a specialization of bytes.EqualFold for use when
// s is all ASCII (but may contain non-letters) and contains no
// special-folding letters.
// See comments on foldFunc.
func AsciiEqualFold(s, t []byte) bool {
if len(s) != len(t) {
return false
}
for i, sb := range s {
tb := t[i]
if sb == tb {
continue
}
if ('a' <= sb && sb <= 'z') || ('A' <= sb && sb <= 'Z') {
if sb&caseMask != tb&caseMask {
return false
}
} else {
return false
}
}
return true
}
// simpleLetterEqualFold is a specialization of bytes.EqualFold for
// use when s is all ASCII letters (no underscores, etc) and also
// doesn't contain 'k', 'K', 's', or 'S'.
// See comments on foldFunc.
func SimpleLetterEqualFold(s, t []byte) bool {
if len(s) != len(t) {
return false
}
for i, b := range s {
if b&caseMask != t[i]&caseMask {
return false
}
}
return true
}

542
vendor/github.com/pquerna/ffjson/fflib/v1/ftoa.go generated vendored Normal file
View File

@ -0,0 +1,542 @@
package v1
/**
* Copyright 2015 Paul Querna, Klaus Post
*
* 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.
*
*/
/* Most of this file are on Go stdlib's strconv/ftoa.go */
// 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.
import "math"
// TODO: move elsewhere?
type floatInfo struct {
mantbits uint
expbits uint
bias int
}
var optimize = true // can change for testing
var float32info = floatInfo{23, 8, -127}
var float64info = floatInfo{52, 11, -1023}
// AppendFloat appends the string form of the floating-point number f,
// as generated by FormatFloat
func AppendFloat(dst EncodingBuffer, val float64, fmt byte, prec, bitSize int) {
var bits uint64
var flt *floatInfo
switch bitSize {
case 32:
bits = uint64(math.Float32bits(float32(val)))
flt = &float32info
case 64:
bits = math.Float64bits(val)
flt = &float64info
default:
panic("strconv: illegal AppendFloat/FormatFloat bitSize")
}
neg := bits>>(flt.expbits+flt.mantbits) != 0
exp := int(bits>>flt.mantbits) & (1<<flt.expbits - 1)
mant := bits & (uint64(1)<<flt.mantbits - 1)
switch exp {
case 1<<flt.expbits - 1:
// Inf, NaN
var s string
switch {
case mant != 0:
s = "NaN"
case neg:
s = "-Inf"
default:
s = "+Inf"
}
dst.WriteString(s)
return
case 0:
// denormalized
exp++
default:
// add implicit top bit
mant |= uint64(1) << flt.mantbits
}
exp += flt.bias
// Pick off easy binary format.
if fmt == 'b' {
fmtB(dst, neg, mant, exp, flt)
return
}
if !optimize {
bigFtoa(dst, prec, fmt, neg, mant, exp, flt)
return
}
var digs decimalSlice
ok := false
// Negative precision means "only as much as needed to be exact."
shortest := prec < 0
if shortest {
// Try Grisu3 algorithm.
f := new(extFloat)
lower, upper := f.AssignComputeBounds(mant, exp, neg, flt)
var buf [32]byte
digs.d = buf[:]
ok = f.ShortestDecimal(&digs, &lower, &upper)
if !ok {
bigFtoa(dst, prec, fmt, neg, mant, exp, flt)
return
}
// Precision for shortest representation mode.
switch fmt {
case 'e', 'E':
prec = max(digs.nd-1, 0)
case 'f':
prec = max(digs.nd-digs.dp, 0)
case 'g', 'G':
prec = digs.nd
}
} else if fmt != 'f' {
// Fixed number of digits.
digits := prec
switch fmt {
case 'e', 'E':
digits++
case 'g', 'G':
if prec == 0 {
prec = 1
}
digits = prec
}
if digits <= 15 {
// try fast algorithm when the number of digits is reasonable.
var buf [24]byte
digs.d = buf[:]
f := extFloat{mant, exp - int(flt.mantbits), neg}
ok = f.FixedDecimal(&digs, digits)
}
}
if !ok {
bigFtoa(dst, prec, fmt, neg, mant, exp, flt)
return
}
formatDigits(dst, shortest, neg, digs, prec, fmt)
return
}
// bigFtoa uses multiprecision computations to format a float.
func bigFtoa(dst EncodingBuffer, prec int, fmt byte, neg bool, mant uint64, exp int, flt *floatInfo) {
d := new(decimal)
d.Assign(mant)
d.Shift(exp - int(flt.mantbits))
var digs decimalSlice
shortest := prec < 0
if shortest {
roundShortest(d, mant, exp, flt)
digs = decimalSlice{d: d.d[:], nd: d.nd, dp: d.dp}
// Precision for shortest representation mode.
switch fmt {
case 'e', 'E':
prec = digs.nd - 1
case 'f':
prec = max(digs.nd-digs.dp, 0)
case 'g', 'G':
prec = digs.nd
}
} else {
// Round appropriately.
switch fmt {
case 'e', 'E':
d.Round(prec + 1)
case 'f':
d.Round(d.dp + prec)
case 'g', 'G':
if prec == 0 {
prec = 1
}
d.Round(prec)
}
digs = decimalSlice{d: d.d[:], nd: d.nd, dp: d.dp}
}
formatDigits(dst, shortest, neg, digs, prec, fmt)
return
}
func formatDigits(dst EncodingBuffer, shortest bool, neg bool, digs decimalSlice, prec int, fmt byte) {
switch fmt {
case 'e', 'E':
fmtE(dst, neg, digs, prec, fmt)
return
case 'f':
fmtF(dst, neg, digs, prec)
return
case 'g', 'G':
// trailing fractional zeros in 'e' form will be trimmed.
eprec := prec
if eprec > digs.nd && digs.nd >= digs.dp {
eprec = digs.nd
}
// %e is used if the exponent from the conversion
// is less than -4 or greater than or equal to the precision.
// if precision was the shortest possible, use precision 6 for this decision.
if shortest {
eprec = 6
}
exp := digs.dp - 1
if exp < -4 || exp >= eprec {
if prec > digs.nd {
prec = digs.nd
}
fmtE(dst, neg, digs, prec-1, fmt+'e'-'g')
return
}
if prec > digs.dp {
prec = digs.nd
}
fmtF(dst, neg, digs, max(prec-digs.dp, 0))
return
}
// unknown format
dst.Write([]byte{'%', fmt})
return
}
// Round d (= mant * 2^exp) to the shortest number of digits
// that will let the original floating point value be precisely
// reconstructed. Size is original floating point size (64 or 32).
func roundShortest(d *decimal, mant uint64, exp int, flt *floatInfo) {
// If mantissa is zero, the number is zero; stop now.
if mant == 0 {
d.nd = 0
return
}
// Compute upper and lower such that any decimal number
// between upper and lower (possibly inclusive)
// will round to the original floating point number.
// We may see at once that the number is already shortest.
//
// Suppose d is not denormal, so that 2^exp <= d < 10^dp.
// The closest shorter number is at least 10^(dp-nd) away.
// The lower/upper bounds computed below are at distance
// at most 2^(exp-mantbits).
//
// So the number is already shortest if 10^(dp-nd) > 2^(exp-mantbits),
// or equivalently log2(10)*(dp-nd) > exp-mantbits.
// It is true if 332/100*(dp-nd) >= exp-mantbits (log2(10) > 3.32).
minexp := flt.bias + 1 // minimum possible exponent
if exp > minexp && 332*(d.dp-d.nd) >= 100*(exp-int(flt.mantbits)) {
// The number is already shortest.
return
}
// d = mant << (exp - mantbits)
// Next highest floating point number is mant+1 << exp-mantbits.
// Our upper bound is halfway between, mant*2+1 << exp-mantbits-1.
upper := new(decimal)
upper.Assign(mant*2 + 1)
upper.Shift(exp - int(flt.mantbits) - 1)
// d = mant << (exp - mantbits)
// Next lowest floating point number is mant-1 << exp-mantbits,
// unless mant-1 drops the significant bit and exp is not the minimum exp,
// in which case the next lowest is mant*2-1 << exp-mantbits-1.
// Either way, call it mantlo << explo-mantbits.
// Our lower bound is halfway between, mantlo*2+1 << explo-mantbits-1.
var mantlo uint64
var explo int
if mant > 1<<flt.mantbits || exp == minexp {
mantlo = mant - 1
explo = exp
} else {
mantlo = mant*2 - 1
explo = exp - 1
}
lower := new(decimal)
lower.Assign(mantlo*2 + 1)
lower.Shift(explo - int(flt.mantbits) - 1)
// The upper and lower bounds are possible outputs only if
// the original mantissa is even, so that IEEE round-to-even
// would round to the original mantissa and not the neighbors.
inclusive := mant%2 == 0
// Now we can figure out the minimum number of digits required.
// Walk along until d has distinguished itself from upper and lower.
for i := 0; i < d.nd; i++ {
var l, m, u byte // lower, middle, upper digits
if i < lower.nd {
l = lower.d[i]
} else {
l = '0'
}
m = d.d[i]
if i < upper.nd {
u = upper.d[i]
} else {
u = '0'
}
// Okay to round down (truncate) if lower has a different digit
// or if lower is inclusive and is exactly the result of rounding down.
okdown := l != m || (inclusive && l == m && i+1 == lower.nd)
// Okay to round up if upper has a different digit and
// either upper is inclusive or upper is bigger than the result of rounding up.
okup := m != u && (inclusive || m+1 < u || i+1 < upper.nd)
// If it's okay to do either, then round to the nearest one.
// If it's okay to do only one, do it.
switch {
case okdown && okup:
d.Round(i + 1)
return
case okdown:
d.RoundDown(i + 1)
return
case okup:
d.RoundUp(i + 1)
return
}
}
}
type decimalSlice struct {
d []byte
nd, dp int
neg bool
}
// %e: -d.ddddde±dd
func fmtE(dst EncodingBuffer, neg bool, d decimalSlice, prec int, fmt byte) {
// sign
if neg {
dst.WriteByte('-')
}
// first digit
ch := byte('0')
if d.nd != 0 {
ch = d.d[0]
}
dst.WriteByte(ch)
// .moredigits
if prec > 0 {
dst.WriteByte('.')
i := 1
m := min(d.nd, prec+1)
if i < m {
dst.Write(d.d[i:m])
i = m
}
for i <= prec {
dst.WriteByte('0')
i++
}
}
// e±
dst.WriteByte(fmt)
exp := d.dp - 1
if d.nd == 0 { // special case: 0 has exponent 0
exp = 0
}
if exp < 0 {
ch = '-'
exp = -exp
} else {
ch = '+'
}
dst.WriteByte(ch)
// dd or ddd
switch {
case exp < 10:
dst.WriteByte('0')
dst.WriteByte(byte(exp) + '0')
case exp < 100:
dst.WriteByte(byte(exp/10) + '0')
dst.WriteByte(byte(exp%10) + '0')
default:
dst.WriteByte(byte(exp/100) + '0')
dst.WriteByte(byte(exp/10)%10 + '0')
dst.WriteByte(byte(exp%10) + '0')
}
return
}
// %f: -ddddddd.ddddd
func fmtF(dst EncodingBuffer, neg bool, d decimalSlice, prec int) {
// sign
if neg {
dst.WriteByte('-')
}
// integer, padded with zeros as needed.
if d.dp > 0 {
m := min(d.nd, d.dp)
dst.Write(d.d[:m])
for ; m < d.dp; m++ {
dst.WriteByte('0')
}
} else {
dst.WriteByte('0')
}
// fraction
if prec > 0 {
dst.WriteByte('.')
for i := 0; i < prec; i++ {
ch := byte('0')
if j := d.dp + i; 0 <= j && j < d.nd {
ch = d.d[j]
}
dst.WriteByte(ch)
}
}
return
}
// %b: -ddddddddp±ddd
func fmtB(dst EncodingBuffer, neg bool, mant uint64, exp int, flt *floatInfo) {
// sign
if neg {
dst.WriteByte('-')
}
// mantissa
formatBits(dst, mant, 10, false)
// p
dst.WriteByte('p')
// ±exponent
exp -= int(flt.mantbits)
if exp >= 0 {
dst.WriteByte('+')
}
formatBits(dst, uint64(exp), 10, exp < 0)
return
}
func min(a, b int) int {
if a < b {
return a
}
return b
}
func max(a, b int) int {
if a > b {
return a
}
return b
}
// formatBits computes the string representation of u in the given base.
// If neg is set, u is treated as negative int64 value.
func formatBits(dst EncodingBuffer, u uint64, base int, neg bool) {
if base < 2 || base > len(digits) {
panic("strconv: illegal AppendInt/FormatInt base")
}
// 2 <= base && base <= len(digits)
var a [64 + 1]byte // +1 for sign of 64bit value in base 2
i := len(a)
if neg {
u = -u
}
// convert bits
if base == 10 {
// common case: use constants for / because
// the compiler can optimize it into a multiply+shift
if ^uintptr(0)>>32 == 0 {
for u > uint64(^uintptr(0)) {
q := u / 1e9
us := uintptr(u - q*1e9) // us % 1e9 fits into a uintptr
for j := 9; j > 0; j-- {
i--
qs := us / 10
a[i] = byte(us - qs*10 + '0')
us = qs
}
u = q
}
}
// u guaranteed to fit into a uintptr
us := uintptr(u)
for us >= 10 {
i--
q := us / 10
a[i] = byte(us - q*10 + '0')
us = q
}
// u < 10
i--
a[i] = byte(us + '0')
} else if s := shifts[base]; s > 0 {
// base is power of 2: use shifts and masks instead of / and %
b := uint64(base)
m := uintptr(b) - 1 // == 1<<s - 1
for u >= b {
i--
a[i] = digits[uintptr(u)&m]
u >>= s
}
// u < base
i--
a[i] = digits[uintptr(u)]
} else {
// general case
b := uint64(base)
for u >= b {
i--
q := u / b
a[i] = digits[uintptr(u-q*b)]
u = q
}
// u < base
i--
a[i] = digits[uintptr(u)]
}
// add sign, if any
if neg {
i--
a[i] = '-'
}
dst.Write(a[i:])
}

View File

@ -0,0 +1,936 @@
/**
* Copyright 2014 Paul Querna
*
* 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.
*
*/
/* Portions of this file are on Go stdlib's strconv/atof.go */
// 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.
package internal
// decimal to binary floating point conversion.
// Algorithm:
// 1) Store input in multiprecision decimal.
// 2) Multiply/divide decimal by powers of two until in range [0.5, 1)
// 3) Multiply by 2^precision and round to get mantissa.
import "math"
var optimize = true // can change for testing
func equalIgnoreCase(s1 []byte, s2 []byte) bool {
if len(s1) != len(s2) {
return false
}
for i := 0; i < len(s1); i++ {
c1 := s1[i]
if 'A' <= c1 && c1 <= 'Z' {
c1 += 'a' - 'A'
}
c2 := s2[i]
if 'A' <= c2 && c2 <= 'Z' {
c2 += 'a' - 'A'
}
if c1 != c2 {
return false
}
}
return true
}
func special(s []byte) (f float64, ok bool) {
if len(s) == 0 {
return
}
switch s[0] {
default:
return
case '+':
if equalIgnoreCase(s, []byte("+inf")) || equalIgnoreCase(s, []byte("+infinity")) {
return math.Inf(1), true
}
case '-':
if equalIgnoreCase(s, []byte("-inf")) || equalIgnoreCase(s, []byte("-infinity")) {
return math.Inf(-1), true
}
case 'n', 'N':
if equalIgnoreCase(s, []byte("nan")) {
return math.NaN(), true
}
case 'i', 'I':
if equalIgnoreCase(s, []byte("inf")) || equalIgnoreCase(s, []byte("infinity")) {
return math.Inf(1), true
}
}
return
}
func (b *decimal) set(s []byte) (ok bool) {
i := 0
b.neg = false
b.trunc = false
// optional sign
if i >= len(s) {
return
}
switch {
case s[i] == '+':
i++
case s[i] == '-':
b.neg = true
i++
}
// digits
sawdot := false
sawdigits := false
for ; i < len(s); i++ {
switch {
case s[i] == '.':
if sawdot {
return
}
sawdot = true
b.dp = b.nd
continue
case '0' <= s[i] && s[i] <= '9':
sawdigits = true
if s[i] == '0' && b.nd == 0 { // ignore leading zeros
b.dp--
continue
}
if b.nd < len(b.d) {
b.d[b.nd] = s[i]
b.nd++
} else if s[i] != '0' {
b.trunc = true
}
continue
}
break
}
if !sawdigits {
return
}
if !sawdot {
b.dp = b.nd
}
// optional exponent moves decimal point.
// if we read a very large, very long number,
// just be sure to move the decimal point by
// a lot (say, 100000). it doesn't matter if it's
// not the exact number.
if i < len(s) && (s[i] == 'e' || s[i] == 'E') {
i++
if i >= len(s) {
return
}
esign := 1
if s[i] == '+' {
i++
} else if s[i] == '-' {
i++
esign = -1
}
if i >= len(s) || s[i] < '0' || s[i] > '9' {
return
}
e := 0
for ; i < len(s) && '0' <= s[i] && s[i] <= '9'; i++ {
if e < 10000 {
e = e*10 + int(s[i]) - '0'
}
}
b.dp += e * esign
}
if i != len(s) {
return
}
ok = true
return
}
// readFloat reads a decimal mantissa and exponent from a float
// string representation. It sets ok to false if the number could
// not fit return types or is invalid.
func readFloat(s []byte) (mantissa uint64, exp int, neg, trunc, ok bool) {
const uint64digits = 19
i := 0
// optional sign
if i >= len(s) {
return
}
switch {
case s[i] == '+':
i++
case s[i] == '-':
neg = true
i++
}
// digits
sawdot := false
sawdigits := false
nd := 0
ndMant := 0
dp := 0
for ; i < len(s); i++ {
switch c := s[i]; true {
case c == '.':
if sawdot {
return
}
sawdot = true
dp = nd
continue
case '0' <= c && c <= '9':
sawdigits = true
if c == '0' && nd == 0 { // ignore leading zeros
dp--
continue
}
nd++
if ndMant < uint64digits {
mantissa *= 10
mantissa += uint64(c - '0')
ndMant++
} else if s[i] != '0' {
trunc = true
}
continue
}
break
}
if !sawdigits {
return
}
if !sawdot {
dp = nd
}
// optional exponent moves decimal point.
// if we read a very large, very long number,
// just be sure to move the decimal point by
// a lot (say, 100000). it doesn't matter if it's
// not the exact number.
if i < len(s) && (s[i] == 'e' || s[i] == 'E') {
i++
if i >= len(s) {
return
}
esign := 1
if s[i] == '+' {
i++
} else if s[i] == '-' {
i++
esign = -1
}
if i >= len(s) || s[i] < '0' || s[i] > '9' {
return
}
e := 0
for ; i < len(s) && '0' <= s[i] && s[i] <= '9'; i++ {
if e < 10000 {
e = e*10 + int(s[i]) - '0'
}
}
dp += e * esign
}
if i != len(s) {
return
}
exp = dp - ndMant
ok = true
return
}
// decimal power of ten to binary power of two.
var powtab = []int{1, 3, 6, 9, 13, 16, 19, 23, 26}
func (d *decimal) floatBits(flt *floatInfo) (b uint64, overflow bool) {
var exp int
var mant uint64
// Zero is always a special case.
if d.nd == 0 {
mant = 0
exp = flt.bias
goto out
}
// Obvious overflow/underflow.
// These bounds are for 64-bit floats.
// Will have to change if we want to support 80-bit floats in the future.
if d.dp > 310 {
goto overflow
}
if d.dp < -330 {
// zero
mant = 0
exp = flt.bias
goto out
}
// Scale by powers of two until in range [0.5, 1.0)
exp = 0
for d.dp > 0 {
var n int
if d.dp >= len(powtab) {
n = 27
} else {
n = powtab[d.dp]
}
d.Shift(-n)
exp += n
}
for d.dp < 0 || d.dp == 0 && d.d[0] < '5' {
var n int
if -d.dp >= len(powtab) {
n = 27
} else {
n = powtab[-d.dp]
}
d.Shift(n)
exp -= n
}
// Our range is [0.5,1) but floating point range is [1,2).
exp--
// Minimum representable exponent is flt.bias+1.
// If the exponent is smaller, move it up and
// adjust d accordingly.
if exp < flt.bias+1 {
n := flt.bias + 1 - exp
d.Shift(-n)
exp += n
}
if exp-flt.bias >= 1<<flt.expbits-1 {
goto overflow
}
// Extract 1+flt.mantbits bits.
d.Shift(int(1 + flt.mantbits))
mant = d.RoundedInteger()
// Rounding might have added a bit; shift down.
if mant == 2<<flt.mantbits {
mant >>= 1
exp++
if exp-flt.bias >= 1<<flt.expbits-1 {
goto overflow
}
}
// Denormalized?
if mant&(1<<flt.mantbits) == 0 {
exp = flt.bias
}
goto out
overflow:
// ±Inf
mant = 0
exp = 1<<flt.expbits - 1 + flt.bias
overflow = true
out:
// Assemble bits.
bits := mant & (uint64(1)<<flt.mantbits - 1)
bits |= uint64((exp-flt.bias)&(1<<flt.expbits-1)) << flt.mantbits
if d.neg {
bits |= 1 << flt.mantbits << flt.expbits
}
return bits, overflow
}
// Exact powers of 10.
var float64pow10 = []float64{
1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
1e20, 1e21, 1e22,
}
var float32pow10 = []float32{1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10}
// If possible to convert decimal representation to 64-bit float f exactly,
// entirely in floating-point math, do so, avoiding the expense of decimalToFloatBits.
// Three common cases:
// value is exact integer
// value is exact integer * exact power of ten
// value is exact integer / exact power of ten
// These all produce potentially inexact but correctly rounded answers.
func atof64exact(mantissa uint64, exp int, neg bool) (f float64, ok bool) {
if mantissa>>float64info.mantbits != 0 {
return
}
f = float64(mantissa)
if neg {
f = -f
}
switch {
case exp == 0:
// an integer.
return f, true
// Exact integers are <= 10^15.
// Exact powers of ten are <= 10^22.
case exp > 0 && exp <= 15+22: // int * 10^k
// If exponent is big but number of digits is not,
// can move a few zeros into the integer part.
if exp > 22 {
f *= float64pow10[exp-22]
exp = 22
}
if f > 1e15 || f < -1e15 {
// the exponent was really too large.
return
}
return f * float64pow10[exp], true
case exp < 0 && exp >= -22: // int / 10^k
return f / float64pow10[-exp], true
}
return
}
// If possible to compute mantissa*10^exp to 32-bit float f exactly,
// entirely in floating-point math, do so, avoiding the machinery above.
func atof32exact(mantissa uint64, exp int, neg bool) (f float32, ok bool) {
if mantissa>>float32info.mantbits != 0 {
return
}
f = float32(mantissa)
if neg {
f = -f
}
switch {
case exp == 0:
return f, true
// Exact integers are <= 10^7.
// Exact powers of ten are <= 10^10.
case exp > 0 && exp <= 7+10: // int * 10^k
// If exponent is big but number of digits is not,
// can move a few zeros into the integer part.
if exp > 10 {
f *= float32pow10[exp-10]
exp = 10
}
if f > 1e7 || f < -1e7 {
// the exponent was really too large.
return
}
return f * float32pow10[exp], true
case exp < 0 && exp >= -10: // int / 10^k
return f / float32pow10[-exp], true
}
return
}
const fnParseFloat = "ParseFloat"
func atof32(s []byte) (f float32, err error) {
if val, ok := special(s); ok {
return float32(val), nil
}
if optimize {
// Parse mantissa and exponent.
mantissa, exp, neg, trunc, ok := readFloat(s)
if ok {
// Try pure floating-point arithmetic conversion.
if !trunc {
if f, ok := atof32exact(mantissa, exp, neg); ok {
return f, nil
}
}
// Try another fast path.
ext := new(extFloat)
if ok := ext.AssignDecimal(mantissa, exp, neg, trunc, &float32info); ok {
b, ovf := ext.floatBits(&float32info)
f = math.Float32frombits(uint32(b))
if ovf {
err = rangeError(fnParseFloat, string(s))
}
return f, err
}
}
}
var d decimal
if !d.set(s) {
return 0, syntaxError(fnParseFloat, string(s))
}
b, ovf := d.floatBits(&float32info)
f = math.Float32frombits(uint32(b))
if ovf {
err = rangeError(fnParseFloat, string(s))
}
return f, err
}
func atof64(s []byte) (f float64, err error) {
if val, ok := special(s); ok {
return val, nil
}
if optimize {
// Parse mantissa and exponent.
mantissa, exp, neg, trunc, ok := readFloat(s)
if ok {
// Try pure floating-point arithmetic conversion.
if !trunc {
if f, ok := atof64exact(mantissa, exp, neg); ok {
return f, nil
}
}
// Try another fast path.
ext := new(extFloat)
if ok := ext.AssignDecimal(mantissa, exp, neg, trunc, &float64info); ok {
b, ovf := ext.floatBits(&float64info)
f = math.Float64frombits(b)
if ovf {
err = rangeError(fnParseFloat, string(s))
}
return f, err
}
}
}
var d decimal
if !d.set(s) {
return 0, syntaxError(fnParseFloat, string(s))
}
b, ovf := d.floatBits(&float64info)
f = math.Float64frombits(b)
if ovf {
err = rangeError(fnParseFloat, string(s))
}
return f, err
}
// ParseFloat converts the string s to a floating-point number
// with the precision specified by bitSize: 32 for float32, or 64 for float64.
// When bitSize=32, the result still has type float64, but it will be
// convertible to float32 without changing its value.
//
// If s is well-formed and near a valid floating point number,
// ParseFloat returns the nearest floating point number rounded
// using IEEE754 unbiased rounding.
//
// The errors that ParseFloat returns have concrete type *NumError
// and include err.Num = s.
//
// If s is not syntactically well-formed, ParseFloat returns err.Err = ErrSyntax.
//
// If s is syntactically well-formed but is more than 1/2 ULP
// away from the largest floating point number of the given size,
// ParseFloat returns f = ±Inf, err.Err = ErrRange.
func ParseFloat(s []byte, bitSize int) (f float64, err error) {
if bitSize == 32 {
f1, err1 := atof32(s)
return float64(f1), err1
}
f1, err1 := atof64(s)
return f1, err1
}
// oroginal: strconv/decimal.go, but not exported, and needed for PareFloat.
// 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.
// Multiprecision decimal numbers.
// For floating-point formatting only; not general purpose.
// Only operations are assign and (binary) left/right shift.
// Can do binary floating point in multiprecision decimal precisely
// because 2 divides 10; cannot do decimal floating point
// in multiprecision binary precisely.
type decimal struct {
d [800]byte // digits
nd int // number of digits used
dp int // decimal point
neg bool
trunc bool // discarded nonzero digits beyond d[:nd]
}
func (a *decimal) String() string {
n := 10 + a.nd
if a.dp > 0 {
n += a.dp
}
if a.dp < 0 {
n += -a.dp
}
buf := make([]byte, n)
w := 0
switch {
case a.nd == 0:
return "0"
case a.dp <= 0:
// zeros fill space between decimal point and digits
buf[w] = '0'
w++
buf[w] = '.'
w++
w += digitZero(buf[w : w+-a.dp])
w += copy(buf[w:], a.d[0:a.nd])
case a.dp < a.nd:
// decimal point in middle of digits
w += copy(buf[w:], a.d[0:a.dp])
buf[w] = '.'
w++
w += copy(buf[w:], a.d[a.dp:a.nd])
default:
// zeros fill space between digits and decimal point
w += copy(buf[w:], a.d[0:a.nd])
w += digitZero(buf[w : w+a.dp-a.nd])
}
return string(buf[0:w])
}
func digitZero(dst []byte) int {
for i := range dst {
dst[i] = '0'
}
return len(dst)
}
// trim trailing zeros from number.
// (They are meaningless; the decimal point is tracked
// independent of the number of digits.)
func trim(a *decimal) {
for a.nd > 0 && a.d[a.nd-1] == '0' {
a.nd--
}
if a.nd == 0 {
a.dp = 0
}
}
// Assign v to a.
func (a *decimal) Assign(v uint64) {
var buf [24]byte
// Write reversed decimal in buf.
n := 0
for v > 0 {
v1 := v / 10
v -= 10 * v1
buf[n] = byte(v + '0')
n++
v = v1
}
// Reverse again to produce forward decimal in a.d.
a.nd = 0
for n--; n >= 0; n-- {
a.d[a.nd] = buf[n]
a.nd++
}
a.dp = a.nd
trim(a)
}
// Maximum shift that we can do in one pass without overflow.
// Signed int has 31 bits, and we have to be able to accommodate 9<<k.
const maxShift = 27
// Binary shift right (* 2) by k bits. k <= maxShift to avoid overflow.
func rightShift(a *decimal, k uint) {
r := 0 // read pointer
w := 0 // write pointer
// Pick up enough leading digits to cover first shift.
n := 0
for ; n>>k == 0; r++ {
if r >= a.nd {
if n == 0 {
// a == 0; shouldn't get here, but handle anyway.
a.nd = 0
return
}
for n>>k == 0 {
n = n * 10
r++
}
break
}
c := int(a.d[r])
n = n*10 + c - '0'
}
a.dp -= r - 1
// Pick up a digit, put down a digit.
for ; r < a.nd; r++ {
c := int(a.d[r])
dig := n >> k
n -= dig << k
a.d[w] = byte(dig + '0')
w++
n = n*10 + c - '0'
}
// Put down extra digits.
for n > 0 {
dig := n >> k
n -= dig << k
if w < len(a.d) {
a.d[w] = byte(dig + '0')
w++
} else if dig > 0 {
a.trunc = true
}
n = n * 10
}
a.nd = w
trim(a)
}
// Cheat sheet for left shift: table indexed by shift count giving
// number of new digits that will be introduced by that shift.
//
// For example, leftcheats[4] = {2, "625"}. That means that
// if we are shifting by 4 (multiplying by 16), it will add 2 digits
// when the string prefix is "625" through "999", and one fewer digit
// if the string prefix is "000" through "624".
//
// Credit for this trick goes to Ken.
type leftCheat struct {
delta int // number of new digits
cutoff string // minus one digit if original < a.
}
var leftcheats = []leftCheat{
// Leading digits of 1/2^i = 5^i.
// 5^23 is not an exact 64-bit floating point number,
// so have to use bc for the math.
/*
seq 27 | sed 's/^/5^/' | bc |
awk 'BEGIN{ print "\tleftCheat{ 0, \"\" }," }
{
log2 = log(2)/log(10)
printf("\tleftCheat{ %d, \"%s\" },\t// * %d\n",
int(log2*NR+1), $0, 2**NR)
}'
*/
{0, ""},
{1, "5"}, // * 2
{1, "25"}, // * 4
{1, "125"}, // * 8
{2, "625"}, // * 16
{2, "3125"}, // * 32
{2, "15625"}, // * 64
{3, "78125"}, // * 128
{3, "390625"}, // * 256
{3, "1953125"}, // * 512
{4, "9765625"}, // * 1024
{4, "48828125"}, // * 2048
{4, "244140625"}, // * 4096
{4, "1220703125"}, // * 8192
{5, "6103515625"}, // * 16384
{5, "30517578125"}, // * 32768
{5, "152587890625"}, // * 65536
{6, "762939453125"}, // * 131072
{6, "3814697265625"}, // * 262144
{6, "19073486328125"}, // * 524288
{7, "95367431640625"}, // * 1048576
{7, "476837158203125"}, // * 2097152
{7, "2384185791015625"}, // * 4194304
{7, "11920928955078125"}, // * 8388608
{8, "59604644775390625"}, // * 16777216
{8, "298023223876953125"}, // * 33554432
{8, "1490116119384765625"}, // * 67108864
{9, "7450580596923828125"}, // * 134217728
}
// Is the leading prefix of b lexicographically less than s?
func prefixIsLessThan(b []byte, s string) bool {
for i := 0; i < len(s); i++ {
if i >= len(b) {
return true
}
if b[i] != s[i] {
return b[i] < s[i]
}
}
return false
}
// Binary shift left (/ 2) by k bits. k <= maxShift to avoid overflow.
func leftShift(a *decimal, k uint) {
delta := leftcheats[k].delta
if prefixIsLessThan(a.d[0:a.nd], leftcheats[k].cutoff) {
delta--
}
r := a.nd // read index
w := a.nd + delta // write index
n := 0
// Pick up a digit, put down a digit.
for r--; r >= 0; r-- {
n += (int(a.d[r]) - '0') << k
quo := n / 10
rem := n - 10*quo
w--
if w < len(a.d) {
a.d[w] = byte(rem + '0')
} else if rem != 0 {
a.trunc = true
}
n = quo
}
// Put down extra digits.
for n > 0 {
quo := n / 10
rem := n - 10*quo
w--
if w < len(a.d) {
a.d[w] = byte(rem + '0')
} else if rem != 0 {
a.trunc = true
}
n = quo
}
a.nd += delta
if a.nd >= len(a.d) {
a.nd = len(a.d)
}
a.dp += delta
trim(a)
}
// Binary shift left (k > 0) or right (k < 0).
func (a *decimal) Shift(k int) {
switch {
case a.nd == 0:
// nothing to do: a == 0
case k > 0:
for k > maxShift {
leftShift(a, maxShift)
k -= maxShift
}
leftShift(a, uint(k))
case k < 0:
for k < -maxShift {
rightShift(a, maxShift)
k += maxShift
}
rightShift(a, uint(-k))
}
}
// If we chop a at nd digits, should we round up?
func shouldRoundUp(a *decimal, nd int) bool {
if nd < 0 || nd >= a.nd {
return false
}
if a.d[nd] == '5' && nd+1 == a.nd { // exactly halfway - round to even
// if we truncated, a little higher than what's recorded - always round up
if a.trunc {
return true
}
return nd > 0 && (a.d[nd-1]-'0')%2 != 0
}
// not halfway - digit tells all
return a.d[nd] >= '5'
}
// Round a to nd digits (or fewer).
// If nd is zero, it means we're rounding
// just to the left of the digits, as in
// 0.09 -> 0.1.
func (a *decimal) Round(nd int) {
if nd < 0 || nd >= a.nd {
return
}
if shouldRoundUp(a, nd) {
a.RoundUp(nd)
} else {
a.RoundDown(nd)
}
}
// Round a down to nd digits (or fewer).
func (a *decimal) RoundDown(nd int) {
if nd < 0 || nd >= a.nd {
return
}
a.nd = nd
trim(a)
}
// Round a up to nd digits (or fewer).
func (a *decimal) RoundUp(nd int) {
if nd < 0 || nd >= a.nd {
return
}
// round up
for i := nd - 1; i >= 0; i-- {
c := a.d[i]
if c < '9' { // can stop after this digit
a.d[i]++
a.nd = i + 1
return
}
}
// Number is all 9s.
// Change to single 1 with adjusted decimal point.
a.d[0] = '1'
a.nd = 1
a.dp++
}
// Extract integer part, rounded appropriately.
// No guarantees about overflow.
func (a *decimal) RoundedInteger() uint64 {
if a.dp > 20 {
return 0xFFFFFFFFFFFFFFFF
}
var i int
n := uint64(0)
for i = 0; i < a.dp && i < a.nd; i++ {
n = n*10 + uint64(a.d[i]-'0')
}
for ; i < a.dp; i++ {
n *= 10
}
if shouldRoundUp(a, a.dp) {
n++
}
return n
}

View File

@ -0,0 +1,213 @@
/**
* Copyright 2014 Paul Querna
*
* 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.
*
*/
/* Portions of this file are on Go stdlib's strconv/atoi.go */
// 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.
package internal
import (
"errors"
"strconv"
)
// ErrRange indicates that a value is out of range for the target type.
var ErrRange = errors.New("value out of range")
// ErrSyntax indicates that a value does not have the right syntax for the target type.
var ErrSyntax = errors.New("invalid syntax")
// A NumError records a failed conversion.
type NumError struct {
Func string // the failing function (ParseBool, ParseInt, ParseUint, ParseFloat)
Num string // the input
Err error // the reason the conversion failed (ErrRange, ErrSyntax)
}
func (e *NumError) Error() string {
return "strconv." + e.Func + ": " + "parsing " + strconv.Quote(e.Num) + ": " + e.Err.Error()
}
func syntaxError(fn, str string) *NumError {
return &NumError{fn, str, ErrSyntax}
}
func rangeError(fn, str string) *NumError {
return &NumError{fn, str, ErrRange}
}
const intSize = 32 << uint(^uint(0)>>63)
// IntSize is the size in bits of an int or uint value.
const IntSize = intSize
// 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
}
// ParseUint is like ParseInt but for unsigned numbers, and oeprating on []byte
func ParseUint(s []byte, base int, bitSize int) (n uint64, err error) {
var cutoff, maxVal uint64
if bitSize == 0 {
bitSize = int(IntSize)
}
s0 := s
switch {
case len(s) < 1:
err = 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 = 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<<uint(bitSize) - 1
for i := 0; i < len(s); i++ {
var v byte
d := s[i]
switch {
case '0' <= d && d <= '9':
v = d - '0'
case 'a' <= d && d <= 'z':
v = d - 'a' + 10
case 'A' <= d && d <= 'Z':
v = d - 'A' + 10
default:
n = 0
err = ErrSyntax
goto Error
}
if int(v) >= base {
n = 0
err = ErrSyntax
goto Error
}
if n >= cutoff {
// n*base overflows
n = 1<<64 - 1
err = ErrRange
goto Error
}
n *= uint64(base)
n1 := n + uint64(v)
if n1 < n || n1 > maxVal {
// n+v overflows
n = 1<<64 - 1
err = ErrRange
goto Error
}
n = n1
}
return n, nil
Error:
return n, &NumError{"ParseUint", string(s0), err}
}
// ParseInt interprets a string s in the given base (2 to 36) and
// returns the corresponding value i. If base == 0, the base is
// implied by the string's prefix: base 16 for "0x", base 8 for
// "0", and base 10 otherwise.
//
// The bitSize argument specifies the integer type
// that the result must fit into. Bit sizes 0, 8, 16, 32, and 64
// correspond to int, int8, int16, int32, and int64.
//
// The errors that ParseInt returns have concrete type *NumError
// and include err.Num = s. If s is empty or contains invalid
// digits, err.Err = ErrSyntax and the returned value is 0;
// if the value corresponding to s cannot be represented by a
// signed integer of the given size, err.Err = ErrRange and the
// returned value is the maximum magnitude integer of the
// appropriate bitSize and sign.
func ParseInt(s []byte, base int, bitSize int) (i int64, err error) {
const fnParseInt = "ParseInt"
if bitSize == 0 {
bitSize = int(IntSize)
}
// Empty string bad.
if len(s) == 0 {
return 0, syntaxError(fnParseInt, string(s))
}
// Pick off leading sign.
s0 := s
neg := false
if s[0] == '+' {
s = s[1:]
} else if s[0] == '-' {
neg = true
s = s[1:]
}
// Convert unsigned and check range.
var un uint64
un, err = ParseUint(s, base, bitSize)
if err != nil && err.(*NumError).Err != ErrRange {
err.(*NumError).Func = fnParseInt
err.(*NumError).Num = string(s0)
return 0, err
}
cutoff := uint64(1 << uint(bitSize-1))
if !neg && un >= cutoff {
return int64(cutoff - 1), rangeError(fnParseInt, string(s0))
}
if neg && un > cutoff {
return -int64(cutoff), rangeError(fnParseInt, string(s0))
}
n := int64(un)
if neg {
n = -n
}
return n, nil
}

View File

@ -0,0 +1,668 @@
// 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 internal
// An extFloat represents an extended floating-point number, with more
// precision than a float64. It does not try to save bits: the
// number represented by the structure is mant*(2^exp), with a negative
// sign if neg is true.
type extFloat struct {
mant uint64
exp int
neg bool
}
// Powers of ten taken from double-conversion library.
// http://code.google.com/p/double-conversion/
const (
firstPowerOfTen = -348
stepPowerOfTen = 8
)
var smallPowersOfTen = [...]extFloat{
{1 << 63, -63, false}, // 1
{0xa << 60, -60, false}, // 1e1
{0x64 << 57, -57, false}, // 1e2
{0x3e8 << 54, -54, false}, // 1e3
{0x2710 << 50, -50, false}, // 1e4
{0x186a0 << 47, -47, false}, // 1e5
{0xf4240 << 44, -44, false}, // 1e6
{0x989680 << 40, -40, false}, // 1e7
}
var powersOfTen = [...]extFloat{
{0xfa8fd5a0081c0288, -1220, false}, // 10^-348
{0xbaaee17fa23ebf76, -1193, false}, // 10^-340
{0x8b16fb203055ac76, -1166, false}, // 10^-332
{0xcf42894a5dce35ea, -1140, false}, // 10^-324
{0x9a6bb0aa55653b2d, -1113, false}, // 10^-316
{0xe61acf033d1a45df, -1087, false}, // 10^-308
{0xab70fe17c79ac6ca, -1060, false}, // 10^-300
{0xff77b1fcbebcdc4f, -1034, false}, // 10^-292
{0xbe5691ef416bd60c, -1007, false}, // 10^-284
{0x8dd01fad907ffc3c, -980, false}, // 10^-276
{0xd3515c2831559a83, -954, false}, // 10^-268
{0x9d71ac8fada6c9b5, -927, false}, // 10^-260
{0xea9c227723ee8bcb, -901, false}, // 10^-252
{0xaecc49914078536d, -874, false}, // 10^-244
{0x823c12795db6ce57, -847, false}, // 10^-236
{0xc21094364dfb5637, -821, false}, // 10^-228
{0x9096ea6f3848984f, -794, false}, // 10^-220
{0xd77485cb25823ac7, -768, false}, // 10^-212
{0xa086cfcd97bf97f4, -741, false}, // 10^-204
{0xef340a98172aace5, -715, false}, // 10^-196
{0xb23867fb2a35b28e, -688, false}, // 10^-188
{0x84c8d4dfd2c63f3b, -661, false}, // 10^-180
{0xc5dd44271ad3cdba, -635, false}, // 10^-172
{0x936b9fcebb25c996, -608, false}, // 10^-164
{0xdbac6c247d62a584, -582, false}, // 10^-156
{0xa3ab66580d5fdaf6, -555, false}, // 10^-148
{0xf3e2f893dec3f126, -529, false}, // 10^-140
{0xb5b5ada8aaff80b8, -502, false}, // 10^-132
{0x87625f056c7c4a8b, -475, false}, // 10^-124
{0xc9bcff6034c13053, -449, false}, // 10^-116
{0x964e858c91ba2655, -422, false}, // 10^-108
{0xdff9772470297ebd, -396, false}, // 10^-100
{0xa6dfbd9fb8e5b88f, -369, false}, // 10^-92
{0xf8a95fcf88747d94, -343, false}, // 10^-84
{0xb94470938fa89bcf, -316, false}, // 10^-76
{0x8a08f0f8bf0f156b, -289, false}, // 10^-68
{0xcdb02555653131b6, -263, false}, // 10^-60
{0x993fe2c6d07b7fac, -236, false}, // 10^-52
{0xe45c10c42a2b3b06, -210, false}, // 10^-44
{0xaa242499697392d3, -183, false}, // 10^-36
{0xfd87b5f28300ca0e, -157, false}, // 10^-28
{0xbce5086492111aeb, -130, false}, // 10^-20
{0x8cbccc096f5088cc, -103, false}, // 10^-12
{0xd1b71758e219652c, -77, false}, // 10^-4
{0x9c40000000000000, -50, false}, // 10^4
{0xe8d4a51000000000, -24, false}, // 10^12
{0xad78ebc5ac620000, 3, false}, // 10^20
{0x813f3978f8940984, 30, false}, // 10^28
{0xc097ce7bc90715b3, 56, false}, // 10^36
{0x8f7e32ce7bea5c70, 83, false}, // 10^44
{0xd5d238a4abe98068, 109, false}, // 10^52
{0x9f4f2726179a2245, 136, false}, // 10^60
{0xed63a231d4c4fb27, 162, false}, // 10^68
{0xb0de65388cc8ada8, 189, false}, // 10^76
{0x83c7088e1aab65db, 216, false}, // 10^84
{0xc45d1df942711d9a, 242, false}, // 10^92
{0x924d692ca61be758, 269, false}, // 10^100
{0xda01ee641a708dea, 295, false}, // 10^108
{0xa26da3999aef774a, 322, false}, // 10^116
{0xf209787bb47d6b85, 348, false}, // 10^124
{0xb454e4a179dd1877, 375, false}, // 10^132
{0x865b86925b9bc5c2, 402, false}, // 10^140
{0xc83553c5c8965d3d, 428, false}, // 10^148
{0x952ab45cfa97a0b3, 455, false}, // 10^156
{0xde469fbd99a05fe3, 481, false}, // 10^164
{0xa59bc234db398c25, 508, false}, // 10^172
{0xf6c69a72a3989f5c, 534, false}, // 10^180
{0xb7dcbf5354e9bece, 561, false}, // 10^188
{0x88fcf317f22241e2, 588, false}, // 10^196
{0xcc20ce9bd35c78a5, 614, false}, // 10^204
{0x98165af37b2153df, 641, false}, // 10^212
{0xe2a0b5dc971f303a, 667, false}, // 10^220
{0xa8d9d1535ce3b396, 694, false}, // 10^228
{0xfb9b7cd9a4a7443c, 720, false}, // 10^236
{0xbb764c4ca7a44410, 747, false}, // 10^244
{0x8bab8eefb6409c1a, 774, false}, // 10^252
{0xd01fef10a657842c, 800, false}, // 10^260
{0x9b10a4e5e9913129, 827, false}, // 10^268
{0xe7109bfba19c0c9d, 853, false}, // 10^276
{0xac2820d9623bf429, 880, false}, // 10^284
{0x80444b5e7aa7cf85, 907, false}, // 10^292
{0xbf21e44003acdd2d, 933, false}, // 10^300
{0x8e679c2f5e44ff8f, 960, false}, // 10^308
{0xd433179d9c8cb841, 986, false}, // 10^316
{0x9e19db92b4e31ba9, 1013, false}, // 10^324
{0xeb96bf6ebadf77d9, 1039, false}, // 10^332
{0xaf87023b9bf0ee6b, 1066, false}, // 10^340
}
// floatBits returns the bits of the float64 that best approximates
// the extFloat passed as receiver. Overflow is set to true if
// the resulting float64 is ±Inf.
func (f *extFloat) floatBits(flt *floatInfo) (bits uint64, overflow bool) {
f.Normalize()
exp := f.exp + 63
// Exponent too small.
if exp < flt.bias+1 {
n := flt.bias + 1 - exp
f.mant >>= uint(n)
exp += n
}
// Extract 1+flt.mantbits bits from the 64-bit mantissa.
mant := f.mant >> (63 - flt.mantbits)
if f.mant&(1<<(62-flt.mantbits)) != 0 {
// Round up.
mant += 1
}
// Rounding might have added a bit; shift down.
if mant == 2<<flt.mantbits {
mant >>= 1
exp++
}
// Infinities.
if exp-flt.bias >= 1<<flt.expbits-1 {
// ±Inf
mant = 0
exp = 1<<flt.expbits - 1 + flt.bias
overflow = true
} else if mant&(1<<flt.mantbits) == 0 {
// Denormalized?
exp = flt.bias
}
// Assemble bits.
bits = mant & (uint64(1)<<flt.mantbits - 1)
bits |= uint64((exp-flt.bias)&(1<<flt.expbits-1)) << flt.mantbits
if f.neg {
bits |= 1 << (flt.mantbits + flt.expbits)
}
return
}
// AssignComputeBounds sets f to the floating point value
// defined by mant, exp and precision given by flt. It returns
// lower, upper such that any number in the closed interval
// [lower, upper] is converted back to the same floating point number.
func (f *extFloat) AssignComputeBounds(mant uint64, exp int, neg bool, flt *floatInfo) (lower, upper extFloat) {
f.mant = mant
f.exp = exp - int(flt.mantbits)
f.neg = neg
if f.exp <= 0 && mant == (mant>>uint(-f.exp))<<uint(-f.exp) {
// An exact integer
f.mant >>= uint(-f.exp)
f.exp = 0
return *f, *f
}
expBiased := exp - flt.bias
upper = extFloat{mant: 2*f.mant + 1, exp: f.exp - 1, neg: f.neg}
if mant != 1<<flt.mantbits || expBiased == 1 {
lower = extFloat{mant: 2*f.mant - 1, exp: f.exp - 1, neg: f.neg}
} else {
lower = extFloat{mant: 4*f.mant - 1, exp: f.exp - 2, neg: f.neg}
}
return
}
// Normalize normalizes f so that the highest bit of the mantissa is
// set, and returns the number by which the mantissa was left-shifted.
func (f *extFloat) Normalize() (shift uint) {
mant, exp := f.mant, f.exp
if mant == 0 {
return 0
}
if mant>>(64-32) == 0 {
mant <<= 32
exp -= 32
}
if mant>>(64-16) == 0 {
mant <<= 16
exp -= 16
}
if mant>>(64-8) == 0 {
mant <<= 8
exp -= 8
}
if mant>>(64-4) == 0 {
mant <<= 4
exp -= 4
}
if mant>>(64-2) == 0 {
mant <<= 2
exp -= 2
}
if mant>>(64-1) == 0 {
mant <<= 1
exp -= 1
}
shift = uint(f.exp - exp)
f.mant, f.exp = mant, exp
return
}
// Multiply sets f to the product f*g: the result is correctly rounded,
// but not normalized.
func (f *extFloat) Multiply(g extFloat) {
fhi, flo := f.mant>>32, uint64(uint32(f.mant))
ghi, glo := g.mant>>32, uint64(uint32(g.mant))
// Cross products.
cross1 := fhi * glo
cross2 := flo * ghi
// f.mant*g.mant is fhi*ghi << 64 + (cross1+cross2) << 32 + flo*glo
f.mant = fhi*ghi + (cross1 >> 32) + (cross2 >> 32)
rem := uint64(uint32(cross1)) + uint64(uint32(cross2)) + ((flo * glo) >> 32)
// Round up.
rem += (1 << 31)
f.mant += (rem >> 32)
f.exp = f.exp + g.exp + 64
}
var uint64pow10 = [...]uint64{
1, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
}
// AssignDecimal sets f to an approximate value mantissa*10^exp. It
// returns true if the value represented by f is guaranteed to be the
// best approximation of d after being rounded to a float64 or
// float32 depending on flt.
func (f *extFloat) AssignDecimal(mantissa uint64, exp10 int, neg bool, trunc bool, flt *floatInfo) (ok bool) {
const uint64digits = 19
const errorscale = 8
errors := 0 // An upper bound for error, computed in errorscale*ulp.
if trunc {
// the decimal number was truncated.
errors += errorscale / 2
}
f.mant = mantissa
f.exp = 0
f.neg = neg
// Multiply by powers of ten.
i := (exp10 - firstPowerOfTen) / stepPowerOfTen
if exp10 < firstPowerOfTen || i >= len(powersOfTen) {
return false
}
adjExp := (exp10 - firstPowerOfTen) % stepPowerOfTen
// We multiply by exp%step
if adjExp < uint64digits && mantissa < uint64pow10[uint64digits-adjExp] {
// We can multiply the mantissa exactly.
f.mant *= uint64pow10[adjExp]
f.Normalize()
} else {
f.Normalize()
f.Multiply(smallPowersOfTen[adjExp])
errors += errorscale / 2
}
// We multiply by 10 to the exp - exp%step.
f.Multiply(powersOfTen[i])
if errors > 0 {
errors += 1
}
errors += errorscale / 2
// Normalize
shift := f.Normalize()
errors <<= shift
// Now f is a good approximation of the decimal.
// Check whether the error is too large: that is, if the mantissa
// is perturbated by the error, the resulting float64 will change.
// The 64 bits mantissa is 1 + 52 bits for float64 + 11 extra bits.
//
// In many cases the approximation will be good enough.
denormalExp := flt.bias - 63
var extrabits uint
if f.exp <= denormalExp {
// f.mant * 2^f.exp is smaller than 2^(flt.bias+1).
extrabits = uint(63 - flt.mantbits + 1 + uint(denormalExp-f.exp))
} else {
extrabits = uint(63 - flt.mantbits)
}
halfway := uint64(1) << (extrabits - 1)
mant_extra := f.mant & (1<<extrabits - 1)
// Do a signed comparison here! If the error estimate could make
// the mantissa round differently for the conversion to double,
// then we can't give a definite answer.
if int64(halfway)-int64(errors) < int64(mant_extra) &&
int64(mant_extra) < int64(halfway)+int64(errors) {
return false
}
return true
}
// Frexp10 is an analogue of math.Frexp for decimal powers. It scales
// f by an approximate power of ten 10^-exp, and returns exp10, so
// that f*10^exp10 has the same value as the old f, up to an ulp,
// as well as the index of 10^-exp in the powersOfTen table.
func (f *extFloat) frexp10() (exp10, index int) {
// The constants expMin and expMax constrain the final value of the
// binary exponent of f. We want a small integral part in the result
// because finding digits of an integer requires divisions, whereas
// digits of the fractional part can be found by repeatedly multiplying
// by 10.
const expMin = -60
const expMax = -32
// Find power of ten such that x * 10^n has a binary exponent
// between expMin and expMax.
approxExp10 := ((expMin+expMax)/2 - f.exp) * 28 / 93 // log(10)/log(2) is close to 93/28.
i := (approxExp10 - firstPowerOfTen) / stepPowerOfTen
Loop:
for {
exp := f.exp + powersOfTen[i].exp + 64
switch {
case exp < expMin:
i++
case exp > expMax:
i--
default:
break Loop
}
}
// Apply the desired decimal shift on f. It will have exponent
// in the desired range. This is multiplication by 10^-exp10.
f.Multiply(powersOfTen[i])
return -(firstPowerOfTen + i*stepPowerOfTen), i
}
// frexp10Many applies a common shift by a power of ten to a, b, c.
func frexp10Many(a, b, c *extFloat) (exp10 int) {
exp10, i := c.frexp10()
a.Multiply(powersOfTen[i])
b.Multiply(powersOfTen[i])
return
}
// FixedDecimal stores in d the first n significant digits
// of the decimal representation of f. It returns false
// if it cannot be sure of the answer.
func (f *extFloat) FixedDecimal(d *decimalSlice, n int) bool {
if f.mant == 0 {
d.nd = 0
d.dp = 0
d.neg = f.neg
return true
}
if n == 0 {
panic("strconv: internal error: extFloat.FixedDecimal called with n == 0")
}
// Multiply by an appropriate power of ten to have a reasonable
// number to process.
f.Normalize()
exp10, _ := f.frexp10()
shift := uint(-f.exp)
integer := uint32(f.mant >> shift)
fraction := f.mant - (uint64(integer) << shift)
ε := uint64(1) // ε is the uncertainty we have on the mantissa of f.
// Write exactly n digits to d.
needed := n // how many digits are left to write.
integerDigits := 0 // the number of decimal digits of integer.
pow10 := uint64(1) // the power of ten by which f was scaled.
for i, pow := 0, uint64(1); i < 20; i++ {
if pow > uint64(integer) {
integerDigits = i
break
}
pow *= 10
}
rest := integer
if integerDigits > needed {
// the integral part is already large, trim the last digits.
pow10 = uint64pow10[integerDigits-needed]
integer /= uint32(pow10)
rest -= integer * uint32(pow10)
} else {
rest = 0
}
// Write the digits of integer: the digits of rest are omitted.
var buf [32]byte
pos := len(buf)
for v := integer; v > 0; {
v1 := v / 10
v -= 10 * v1
pos--
buf[pos] = byte(v + '0')
v = v1
}
for i := pos; i < len(buf); i++ {
d.d[i-pos] = buf[i]
}
nd := len(buf) - pos
d.nd = nd
d.dp = integerDigits + exp10
needed -= nd
if needed > 0 {
if rest != 0 || pow10 != 1 {
panic("strconv: internal error, rest != 0 but needed > 0")
}
// Emit digits for the fractional part. Each time, 10*fraction
// fits in a uint64 without overflow.
for needed > 0 {
fraction *= 10
ε *= 10 // the uncertainty scales as we multiply by ten.
if 2*ε > 1<<shift {
// the error is so large it could modify which digit to write, abort.
return false
}
digit := fraction >> shift
d.d[nd] = byte(digit + '0')
fraction -= digit << shift
nd++
needed--
}
d.nd = nd
}
// We have written a truncation of f (a numerator / 10^d.dp). The remaining part
// can be interpreted as a small number (< 1) to be added to the last digit of the
// numerator.
//
// If rest > 0, the amount is:
// (rest<<shift | fraction) / (pow10 << shift)
// fraction being known with a ±ε uncertainty.
// The fact that n > 0 guarantees that pow10 << shift does not overflow a uint64.
//
// If rest = 0, pow10 == 1 and the amount is
// fraction / (1 << shift)
// fraction being known with a ±ε uncertainty.
//
// We pass this information to the rounding routine for adjustment.
ok := adjustLastDigitFixed(d, uint64(rest)<<shift|fraction, pow10, shift, ε)
if !ok {
return false
}
// Trim trailing zeros.
for i := d.nd - 1; i >= 0; i-- {
if d.d[i] != '0' {
d.nd = i + 1
break
}
}
return true
}
// adjustLastDigitFixed assumes d contains the representation of the integral part
// of some number, whose fractional part is num / (den << shift). The numerator
// num is only known up to an uncertainty of size ε, assumed to be less than
// (den << shift)/2.
//
// It will increase the last digit by one to account for correct rounding, typically
// when the fractional part is greater than 1/2, and will return false if ε is such
// that no correct answer can be given.
func adjustLastDigitFixed(d *decimalSlice, num, den uint64, shift uint, ε uint64) bool {
if num > den<<shift {
panic("strconv: num > den<<shift in adjustLastDigitFixed")
}
if 2*ε > den<<shift {
panic("strconv: ε > (den<<shift)/2")
}
if 2*(num+ε) < den<<shift {
return true
}
if 2*(num-ε) > den<<shift {
// increment d by 1.
i := d.nd - 1
for ; i >= 0; i-- {
if d.d[i] == '9' {
d.nd--
} else {
break
}
}
if i < 0 {
d.d[0] = '1'
d.nd = 1
d.dp++
} else {
d.d[i]++
}
return true
}
return false
}
// ShortestDecimal stores in d the shortest decimal representation of f
// which belongs to the open interval (lower, upper), where f is supposed
// to lie. It returns false whenever the result is unsure. The implementation
// uses the Grisu3 algorithm.
func (f *extFloat) ShortestDecimal(d *decimalSlice, lower, upper *extFloat) bool {
if f.mant == 0 {
d.nd = 0
d.dp = 0
d.neg = f.neg
return true
}
if f.exp == 0 && *lower == *f && *lower == *upper {
// an exact integer.
var buf [24]byte
n := len(buf) - 1
for v := f.mant; v > 0; {
v1 := v / 10
v -= 10 * v1
buf[n] = byte(v + '0')
n--
v = v1
}
nd := len(buf) - n - 1
for i := 0; i < nd; i++ {
d.d[i] = buf[n+1+i]
}
d.nd, d.dp = nd, nd
for d.nd > 0 && d.d[d.nd-1] == '0' {
d.nd--
}
if d.nd == 0 {
d.dp = 0
}
d.neg = f.neg
return true
}
upper.Normalize()
// Uniformize exponents.
if f.exp > upper.exp {
f.mant <<= uint(f.exp - upper.exp)
f.exp = upper.exp
}
if lower.exp > upper.exp {
lower.mant <<= uint(lower.exp - upper.exp)
lower.exp = upper.exp
}
exp10 := frexp10Many(lower, f, upper)
// Take a safety margin due to rounding in frexp10Many, but we lose precision.
upper.mant++
lower.mant--
// The shortest representation of f is either rounded up or down, but
// in any case, it is a truncation of upper.
shift := uint(-upper.exp)
integer := uint32(upper.mant >> shift)
fraction := upper.mant - (uint64(integer) << shift)
// How far we can go down from upper until the result is wrong.
allowance := upper.mant - lower.mant
// How far we should go to get a very precise result.
targetDiff := upper.mant - f.mant
// Count integral digits: there are at most 10.
var integerDigits int
for i, pow := 0, uint64(1); i < 20; i++ {
if pow > uint64(integer) {
integerDigits = i
break
}
pow *= 10
}
for i := 0; i < integerDigits; i++ {
pow := uint64pow10[integerDigits-i-1]
digit := integer / uint32(pow)
d.d[i] = byte(digit + '0')
integer -= digit * uint32(pow)
// evaluate whether we should stop.
if currentDiff := uint64(integer)<<shift + fraction; currentDiff < allowance {
d.nd = i + 1
d.dp = integerDigits + exp10
d.neg = f.neg
// Sometimes allowance is so large the last digit might need to be
// decremented to get closer to f.
return adjustLastDigit(d, currentDiff, targetDiff, allowance, pow<<shift, 2)
}
}
d.nd = integerDigits
d.dp = d.nd + exp10
d.neg = f.neg
// Compute digits of the fractional part. At each step fraction does not
// overflow. The choice of minExp implies that fraction is less than 2^60.
var digit int
multiplier := uint64(1)
for {
fraction *= 10
multiplier *= 10
digit = int(fraction >> shift)
d.d[d.nd] = byte(digit + '0')
d.nd++
fraction -= uint64(digit) << shift
if fraction < allowance*multiplier {
// We are in the admissible range. Note that if allowance is about to
// overflow, that is, allowance > 2^64/10, the condition is automatically
// true due to the limited range of fraction.
return adjustLastDigit(d,
fraction, targetDiff*multiplier, allowance*multiplier,
1<<shift, multiplier*2)
}
}
}
// adjustLastDigit modifies d = x-currentDiff*ε, to get closest to
// d = x-targetDiff*ε, without becoming smaller than x-maxDiff*ε.
// It assumes that a decimal digit is worth ulpDecimal*ε, and that
// all data is known with a error estimate of ulpBinary*ε.
func adjustLastDigit(d *decimalSlice, currentDiff, targetDiff, maxDiff, ulpDecimal, ulpBinary uint64) bool {
if ulpDecimal < 2*ulpBinary {
// Approximation is too wide.
return false
}
for currentDiff+ulpDecimal/2+ulpBinary < targetDiff {
d.d[d.nd-1]--
currentDiff += ulpDecimal
}
if currentDiff+ulpDecimal <= targetDiff+ulpDecimal/2+ulpBinary {
// we have two choices, and don't know what to do.
return false
}
if currentDiff < ulpBinary || currentDiff > maxDiff-ulpBinary {
// we went too far
return false
}
if d.nd == 1 && d.d[0] == '0' {
// the number has actually reached zero.
d.nd = 0
d.dp = 0
}
return true
}

View File

@ -0,0 +1,475 @@
// 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.
// Binary to decimal floating point conversion.
// Algorithm:
// 1) store mantissa in multiprecision decimal
// 2) shift decimal by exponent
// 3) read digits out & format
package internal
import "math"
// TODO: move elsewhere?
type floatInfo struct {
mantbits uint
expbits uint
bias int
}
var float32info = floatInfo{23, 8, -127}
var float64info = floatInfo{52, 11, -1023}
// FormatFloat converts the floating-point number f to a string,
// according to the format fmt and precision prec. It rounds the
// result assuming that the original was obtained from a floating-point
// value of bitSize bits (32 for float32, 64 for float64).
//
// The format fmt is one of
// 'b' (-ddddp±ddd, a binary exponent),
// 'e' (-d.dddde±dd, a decimal exponent),
// 'E' (-d.ddddE±dd, a decimal exponent),
// 'f' (-ddd.dddd, no exponent),
// 'g' ('e' for large exponents, 'f' otherwise), or
// 'G' ('E' for large exponents, 'f' otherwise).
//
// The precision prec controls the number of digits
// (excluding the exponent) printed by the 'e', 'E', 'f', 'g', and 'G' formats.
// For 'e', 'E', and 'f' it is the number of digits after the decimal point.
// For 'g' and 'G' it is the total number of digits.
// The special precision -1 uses the smallest number of digits
// necessary such that ParseFloat will return f exactly.
func formatFloat(f float64, fmt byte, prec, bitSize int) string {
return string(genericFtoa(make([]byte, 0, max(prec+4, 24)), f, fmt, prec, bitSize))
}
// AppendFloat appends the string form of the floating-point number f,
// as generated by FormatFloat, to dst and returns the extended buffer.
func appendFloat(dst []byte, f float64, fmt byte, prec int, bitSize int) []byte {
return genericFtoa(dst, f, fmt, prec, bitSize)
}
func genericFtoa(dst []byte, val float64, fmt byte, prec, bitSize int) []byte {
var bits uint64
var flt *floatInfo
switch bitSize {
case 32:
bits = uint64(math.Float32bits(float32(val)))
flt = &float32info
case 64:
bits = math.Float64bits(val)
flt = &float64info
default:
panic("strconv: illegal AppendFloat/FormatFloat bitSize")
}
neg := bits>>(flt.expbits+flt.mantbits) != 0
exp := int(bits>>flt.mantbits) & (1<<flt.expbits - 1)
mant := bits & (uint64(1)<<flt.mantbits - 1)
switch exp {
case 1<<flt.expbits - 1:
// Inf, NaN
var s string
switch {
case mant != 0:
s = "NaN"
case neg:
s = "-Inf"
default:
s = "+Inf"
}
return append(dst, s...)
case 0:
// denormalized
exp++
default:
// add implicit top bit
mant |= uint64(1) << flt.mantbits
}
exp += flt.bias
// Pick off easy binary format.
if fmt == 'b' {
return fmtB(dst, neg, mant, exp, flt)
}
if !optimize {
return bigFtoa(dst, prec, fmt, neg, mant, exp, flt)
}
var digs decimalSlice
ok := false
// Negative precision means "only as much as needed to be exact."
shortest := prec < 0
if shortest {
// Try Grisu3 algorithm.
f := new(extFloat)
lower, upper := f.AssignComputeBounds(mant, exp, neg, flt)
var buf [32]byte
digs.d = buf[:]
ok = f.ShortestDecimal(&digs, &lower, &upper)
if !ok {
return bigFtoa(dst, prec, fmt, neg, mant, exp, flt)
}
// Precision for shortest representation mode.
switch fmt {
case 'e', 'E':
prec = digs.nd - 1
case 'f':
prec = max(digs.nd-digs.dp, 0)
case 'g', 'G':
prec = digs.nd
}
} else if fmt != 'f' {
// Fixed number of digits.
digits := prec
switch fmt {
case 'e', 'E':
digits++
case 'g', 'G':
if prec == 0 {
prec = 1
}
digits = prec
}
if digits <= 15 {
// try fast algorithm when the number of digits is reasonable.
var buf [24]byte
digs.d = buf[:]
f := extFloat{mant, exp - int(flt.mantbits), neg}
ok = f.FixedDecimal(&digs, digits)
}
}
if !ok {
return bigFtoa(dst, prec, fmt, neg, mant, exp, flt)
}
return formatDigits(dst, shortest, neg, digs, prec, fmt)
}
// bigFtoa uses multiprecision computations to format a float.
func bigFtoa(dst []byte, prec int, fmt byte, neg bool, mant uint64, exp int, flt *floatInfo) []byte {
d := new(decimal)
d.Assign(mant)
d.Shift(exp - int(flt.mantbits))
var digs decimalSlice
shortest := prec < 0
if shortest {
roundShortest(d, mant, exp, flt)
digs = decimalSlice{d: d.d[:], nd: d.nd, dp: d.dp}
// Precision for shortest representation mode.
switch fmt {
case 'e', 'E':
prec = digs.nd - 1
case 'f':
prec = max(digs.nd-digs.dp, 0)
case 'g', 'G':
prec = digs.nd
}
} else {
// Round appropriately.
switch fmt {
case 'e', 'E':
d.Round(prec + 1)
case 'f':
d.Round(d.dp + prec)
case 'g', 'G':
if prec == 0 {
prec = 1
}
d.Round(prec)
}
digs = decimalSlice{d: d.d[:], nd: d.nd, dp: d.dp}
}
return formatDigits(dst, shortest, neg, digs, prec, fmt)
}
func formatDigits(dst []byte, shortest bool, neg bool, digs decimalSlice, prec int, fmt byte) []byte {
switch fmt {
case 'e', 'E':
return fmtE(dst, neg, digs, prec, fmt)
case 'f':
return fmtF(dst, neg, digs, prec)
case 'g', 'G':
// trailing fractional zeros in 'e' form will be trimmed.
eprec := prec
if eprec > digs.nd && digs.nd >= digs.dp {
eprec = digs.nd
}
// %e is used if the exponent from the conversion
// is less than -4 or greater than or equal to the precision.
// if precision was the shortest possible, use precision 6 for this decision.
if shortest {
eprec = 6
}
exp := digs.dp - 1
if exp < -4 || exp >= eprec {
if prec > digs.nd {
prec = digs.nd
}
return fmtE(dst, neg, digs, prec-1, fmt+'e'-'g')
}
if prec > digs.dp {
prec = digs.nd
}
return fmtF(dst, neg, digs, max(prec-digs.dp, 0))
}
// unknown format
return append(dst, '%', fmt)
}
// Round d (= mant * 2^exp) to the shortest number of digits
// that will let the original floating point value be precisely
// reconstructed. Size is original floating point size (64 or 32).
func roundShortest(d *decimal, mant uint64, exp int, flt *floatInfo) {
// If mantissa is zero, the number is zero; stop now.
if mant == 0 {
d.nd = 0
return
}
// Compute upper and lower such that any decimal number
// between upper and lower (possibly inclusive)
// will round to the original floating point number.
// We may see at once that the number is already shortest.
//
// Suppose d is not denormal, so that 2^exp <= d < 10^dp.
// The closest shorter number is at least 10^(dp-nd) away.
// The lower/upper bounds computed below are at distance
// at most 2^(exp-mantbits).
//
// So the number is already shortest if 10^(dp-nd) > 2^(exp-mantbits),
// or equivalently log2(10)*(dp-nd) > exp-mantbits.
// It is true if 332/100*(dp-nd) >= exp-mantbits (log2(10) > 3.32).
minexp := flt.bias + 1 // minimum possible exponent
if exp > minexp && 332*(d.dp-d.nd) >= 100*(exp-int(flt.mantbits)) {
// The number is already shortest.
return
}
// d = mant << (exp - mantbits)
// Next highest floating point number is mant+1 << exp-mantbits.
// Our upper bound is halfway between, mant*2+1 << exp-mantbits-1.
upper := new(decimal)
upper.Assign(mant*2 + 1)
upper.Shift(exp - int(flt.mantbits) - 1)
// d = mant << (exp - mantbits)
// Next lowest floating point number is mant-1 << exp-mantbits,
// unless mant-1 drops the significant bit and exp is not the minimum exp,
// in which case the next lowest is mant*2-1 << exp-mantbits-1.
// Either way, call it mantlo << explo-mantbits.
// Our lower bound is halfway between, mantlo*2+1 << explo-mantbits-1.
var mantlo uint64
var explo int
if mant > 1<<flt.mantbits || exp == minexp {
mantlo = mant - 1
explo = exp
} else {
mantlo = mant*2 - 1
explo = exp - 1
}
lower := new(decimal)
lower.Assign(mantlo*2 + 1)
lower.Shift(explo - int(flt.mantbits) - 1)
// The upper and lower bounds are possible outputs only if
// the original mantissa is even, so that IEEE round-to-even
// would round to the original mantissa and not the neighbors.
inclusive := mant%2 == 0
// Now we can figure out the minimum number of digits required.
// Walk along until d has distinguished itself from upper and lower.
for i := 0; i < d.nd; i++ {
var l, m, u byte // lower, middle, upper digits
if i < lower.nd {
l = lower.d[i]
} else {
l = '0'
}
m = d.d[i]
if i < upper.nd {
u = upper.d[i]
} else {
u = '0'
}
// Okay to round down (truncate) if lower has a different digit
// or if lower is inclusive and is exactly the result of rounding down.
okdown := l != m || (inclusive && l == m && i+1 == lower.nd)
// Okay to round up if upper has a different digit and
// either upper is inclusive or upper is bigger than the result of rounding up.
okup := m != u && (inclusive || m+1 < u || i+1 < upper.nd)
// If it's okay to do either, then round to the nearest one.
// If it's okay to do only one, do it.
switch {
case okdown && okup:
d.Round(i + 1)
return
case okdown:
d.RoundDown(i + 1)
return
case okup:
d.RoundUp(i + 1)
return
}
}
}
type decimalSlice struct {
d []byte
nd, dp int
neg bool
}
// %e: -d.ddddde±dd
func fmtE(dst []byte, neg bool, d decimalSlice, prec int, fmt byte) []byte {
// sign
if neg {
dst = append(dst, '-')
}
// first digit
ch := byte('0')
if d.nd != 0 {
ch = d.d[0]
}
dst = append(dst, ch)
// .moredigits
if prec > 0 {
dst = append(dst, '.')
i := 1
m := d.nd + prec + 1 - max(d.nd, prec+1)
for i < m {
dst = append(dst, d.d[i])
i++
}
for i <= prec {
dst = append(dst, '0')
i++
}
}
// e±
dst = append(dst, fmt)
exp := d.dp - 1
if d.nd == 0 { // special case: 0 has exponent 0
exp = 0
}
if exp < 0 {
ch = '-'
exp = -exp
} else {
ch = '+'
}
dst = append(dst, ch)
// dddd
var buf [3]byte
i := len(buf)
for exp >= 10 {
i--
buf[i] = byte(exp%10 + '0')
exp /= 10
}
// exp < 10
i--
buf[i] = byte(exp + '0')
switch i {
case 0:
dst = append(dst, buf[0], buf[1], buf[2])
case 1:
dst = append(dst, buf[1], buf[2])
case 2:
// leading zeroes
dst = append(dst, '0', buf[2])
}
return dst
}
// %f: -ddddddd.ddddd
func fmtF(dst []byte, neg bool, d decimalSlice, prec int) []byte {
// sign
if neg {
dst = append(dst, '-')
}
// integer, padded with zeros as needed.
if d.dp > 0 {
var i int
for i = 0; i < d.dp && i < d.nd; i++ {
dst = append(dst, d.d[i])
}
for ; i < d.dp; i++ {
dst = append(dst, '0')
}
} else {
dst = append(dst, '0')
}
// fraction
if prec > 0 {
dst = append(dst, '.')
for i := 0; i < prec; i++ {
ch := byte('0')
if j := d.dp + i; 0 <= j && j < d.nd {
ch = d.d[j]
}
dst = append(dst, ch)
}
}
return dst
}
// %b: -ddddddddp+ddd
func fmtB(dst []byte, neg bool, mant uint64, exp int, flt *floatInfo) []byte {
var buf [50]byte
w := len(buf)
exp -= int(flt.mantbits)
esign := byte('+')
if exp < 0 {
esign = '-'
exp = -exp
}
n := 0
for exp > 0 || n < 1 {
n++
w--
buf[w] = byte(exp%10 + '0')
exp /= 10
}
w--
buf[w] = esign
w--
buf[w] = 'p'
n = 0
for mant > 0 || n < 1 {
n++
w--
buf[w] = byte(mant%10 + '0')
mant /= 10
}
if neg {
w--
buf[w] = '-'
}
return append(dst, buf[w:]...)
}
func max(a, b int) int {
if a > b {
return a
}
return b
}

161
vendor/github.com/pquerna/ffjson/fflib/v1/iota.go generated vendored Normal file
View File

@ -0,0 +1,161 @@
/**
* Copyright 2014 Paul Querna
*
* 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.
*
*/
/* Portions of this file are on Go stdlib's strconv/iota.go */
// 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.
package v1
import (
"io"
)
const (
digits = "0123456789abcdefghijklmnopqrstuvwxyz"
digits01 = "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789"
digits10 = "0000000000111111111122222222223333333333444444444455555555556666666666777777777788888888889999999999"
)
var shifts = [len(digits) + 1]uint{
1 << 1: 1,
1 << 2: 2,
1 << 3: 3,
1 << 4: 4,
1 << 5: 5,
}
var smallNumbers = [][]byte{
[]byte("0"),
[]byte("1"),
[]byte("2"),
[]byte("3"),
[]byte("4"),
[]byte("5"),
[]byte("6"),
[]byte("7"),
[]byte("8"),
[]byte("9"),
[]byte("10"),
}
type FormatBitsWriter interface {
io.Writer
io.ByteWriter
}
type FormatBitsScratch struct{}
//
// DEPRECIATED: `scratch` is no longer used, FormatBits2 is available.
//
// FormatBits computes the string representation of u in the given base.
// If neg is set, u is treated as negative int64 value. If append_ is
// set, the string is appended to dst and the resulting byte slice is
// returned as the first result value; otherwise the string is returned
// as the second result value.
//
func FormatBits(scratch *FormatBitsScratch, dst FormatBitsWriter, u uint64, base int, neg bool) {
FormatBits2(dst, u, base, neg)
}
// FormatBits2 computes the string representation of u in the given base.
// If neg is set, u is treated as negative int64 value. If append_ is
// set, the string is appended to dst and the resulting byte slice is
// returned as the first result value; otherwise the string is returned
// as the second result value.
//
func FormatBits2(dst FormatBitsWriter, u uint64, base int, neg bool) {
if base < 2 || base > len(digits) {
panic("strconv: illegal AppendInt/FormatInt base")
}
// fast path for small common numbers
if u <= 10 {
if neg {
dst.WriteByte('-')
}
dst.Write(smallNumbers[u])
return
}
// 2 <= base && base <= len(digits)
var a = makeSlice(65)
// var a [64 + 1]byte // +1 for sign of 64bit value in base 2
i := len(a)
if neg {
u = -u
}
// convert bits
if base == 10 {
// common case: use constants for / and % because
// the compiler can optimize it into a multiply+shift,
// and unroll loop
for u >= 100 {
i -= 2
q := u / 100
j := uintptr(u - q*100)
a[i+1] = digits01[j]
a[i+0] = digits10[j]
u = q
}
if u >= 10 {
i--
q := u / 10
a[i] = digits[uintptr(u-q*10)]
u = q
}
} else if s := shifts[base]; s > 0 {
// base is power of 2: use shifts and masks instead of / and %
b := uint64(base)
m := uintptr(b) - 1 // == 1<<s - 1
for u >= b {
i--
a[i] = digits[uintptr(u)&m]
u >>= s
}
} else {
// general case
b := uint64(base)
for u >= b {
i--
a[i] = digits[uintptr(u%b)]
u /= b
}
}
// u < base
i--
a[i] = digits[uintptr(u)]
// add sign, if any
if neg {
i--
a[i] = '-'
}
dst.Write(a[i:])
Pool(a)
return
}

512
vendor/github.com/pquerna/ffjson/fflib/v1/jsonstring.go generated vendored Normal file
View File

@ -0,0 +1,512 @@
/**
* Copyright 2014 Paul Querna
*
* 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.
*
*/
/* Portions of this file are on Go stdlib's encoding/json/encode.go */
// 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.
package v1
import (
"io"
"unicode/utf8"
"strconv"
"unicode/utf16"
"unicode"
)
const hex = "0123456789abcdef"
type JsonStringWriter interface {
io.Writer
io.ByteWriter
stringWriter
}
func WriteJsonString(buf JsonStringWriter, s string) {
WriteJson(buf, []byte(s))
}
/**
* Function ported from encoding/json: func (e *encodeState) string(s string) (int, error)
*/
func WriteJson(buf JsonStringWriter, s []byte) {
buf.WriteByte('"')
start := 0
for i := 0; i < len(s); {
if b := s[i]; b < utf8.RuneSelf {
/*
if 0x20 <= b && b != '\\' && b != '"' && b != '<' && b != '>' && b != '&' {
i++
continue
}
*/
if lt[b] == true {
i++
continue
}
if start < i {
buf.Write(s[start:i])
}
switch b {
case '\\', '"':
buf.WriteByte('\\')
buf.WriteByte(b)
case '\n':
buf.WriteByte('\\')
buf.WriteByte('n')
case '\r':
buf.WriteByte('\\')
buf.WriteByte('r')
default:
// This encodes bytes < 0x20 except for \n and \r,
// as well as < and >. The latter are escaped because they
// can lead to security holes when user-controlled strings
// are rendered into JSON and served to some browsers.
buf.WriteString(`\u00`)
buf.WriteByte(hex[b>>4])
buf.WriteByte(hex[b&0xF])
}
i++
start = i
continue
}
c, size := utf8.DecodeRune(s[i:])
if c == utf8.RuneError && size == 1 {
if start < i {
buf.Write(s[start:i])
}
buf.WriteString(`\ufffd`)
i += size
start = i
continue
}
// U+2028 is LINE SEPARATOR.
// U+2029 is PARAGRAPH SEPARATOR.
// They are both technically valid characters in JSON strings,
// but don't work in JSONP, which has to be evaluated as JavaScript,
// and can lead to security holes there. It is valid JSON to
// escape them, so we do so unconditionally.
// See http://timelessrepo.com/json-isnt-a-javascript-subset for discussion.
if c == '\u2028' || c == '\u2029' {
if start < i {
buf.Write(s[start:i])
}
buf.WriteString(`\u202`)
buf.WriteByte(hex[c&0xF])
i += size
start = i
continue
}
i += size
}
if start < len(s) {
buf.Write(s[start:])
}
buf.WriteByte('"')
}
// UnquoteBytes will decode []byte containing json string to go string
// ported from encoding/json/decode.go
func UnquoteBytes(s []byte) (t []byte, ok bool) {
if len(s) < 2 || s[0] != '"' || s[len(s)-1] != '"' {
return
}
s = s[1 : len(s)-1]
// Check for unusual characters. If there are none,
// then no unquoting is needed, so return a slice of the
// original bytes.
r := 0
for r < len(s) {
c := s[r]
if c == '\\' || c == '"' || c < ' ' {
break
}
if c < utf8.RuneSelf {
r++
continue
}
rr, size := utf8.DecodeRune(s[r:])
if rr == utf8.RuneError && size == 1 {
break
}
r += size
}
if r == len(s) {
return s, true
}
b := make([]byte, len(s)+2*utf8.UTFMax)
w := copy(b, s[0:r])
for r < len(s) {
// Out of room? Can only happen if s is full of
// malformed UTF-8 and we're replacing each
// byte with RuneError.
if w >= len(b)-2*utf8.UTFMax {
nb := make([]byte, (len(b)+utf8.UTFMax)*2)
copy(nb, b[0:w])
b = nb
}
switch c := s[r]; {
case c == '\\':
r++
if r >= len(s) {
return
}
switch s[r] {
default:
return
case '"', '\\', '/', '\'':
b[w] = s[r]
r++
w++
case 'b':
b[w] = '\b'
r++
w++
case 'f':
b[w] = '\f'
r++
w++
case 'n':
b[w] = '\n'
r++
w++
case 'r':
b[w] = '\r'
r++
w++
case 't':
b[w] = '\t'
r++
w++
case 'u':
r--
rr := getu4(s[r:])
if rr < 0 {
return
}
r += 6
if utf16.IsSurrogate(rr) {
rr1 := getu4(s[r:])
if dec := utf16.DecodeRune(rr, rr1); dec != unicode.ReplacementChar {
// A valid pair; consume.
r += 6
w += utf8.EncodeRune(b[w:], dec)
break
}
// Invalid surrogate; fall back to replacement rune.
rr = unicode.ReplacementChar
}
w += utf8.EncodeRune(b[w:], rr)
}
// Quote, control characters are invalid.
case c == '"', c < ' ':
return
// ASCII
case c < utf8.RuneSelf:
b[w] = c
r++
w++
// Coerce to well-formed UTF-8.
default:
rr, size := utf8.DecodeRune(s[r:])
r += size
w += utf8.EncodeRune(b[w:], rr)
}
}
return b[0:w], true
}
// getu4 decodes \uXXXX from the beginning of s, returning the hex value,
// or it returns -1.
func getu4(s []byte) rune {
if len(s) < 6 || s[0] != '\\' || s[1] != 'u' {
return -1
}
r, err := strconv.ParseUint(string(s[2:6]), 16, 64)
if err != nil {
return -1
}
return rune(r)
}
// TODO(pquerna): consider combining wibth the normal byte mask.
var lt [256]bool = [256]bool{
false, /* 0 */
false, /* 1 */
false, /* 2 */
false, /* 3 */
false, /* 4 */
false, /* 5 */
false, /* 6 */
false, /* 7 */
false, /* 8 */
false, /* 9 */
false, /* 10 */
false, /* 11 */
false, /* 12 */
false, /* 13 */
false, /* 14 */
false, /* 15 */
false, /* 16 */
false, /* 17 */
false, /* 18 */
false, /* 19 */
false, /* 20 */
false, /* 21 */
false, /* 22 */
false, /* 23 */
false, /* 24 */
false, /* 25 */
false, /* 26 */
false, /* 27 */
false, /* 28 */
false, /* 29 */
false, /* 30 */
false, /* 31 */
true, /* 32 */
true, /* 33 */
false, /* 34 */
true, /* 35 */
true, /* 36 */
true, /* 37 */
false, /* 38 */
true, /* 39 */
true, /* 40 */
true, /* 41 */
true, /* 42 */
true, /* 43 */
true, /* 44 */
true, /* 45 */
true, /* 46 */
true, /* 47 */
true, /* 48 */
true, /* 49 */
true, /* 50 */
true, /* 51 */
true, /* 52 */
true, /* 53 */
true, /* 54 */
true, /* 55 */
true, /* 56 */
true, /* 57 */
true, /* 58 */
true, /* 59 */
false, /* 60 */
true, /* 61 */
false, /* 62 */
true, /* 63 */
true, /* 64 */
true, /* 65 */
true, /* 66 */
true, /* 67 */
true, /* 68 */
true, /* 69 */
true, /* 70 */
true, /* 71 */
true, /* 72 */
true, /* 73 */
true, /* 74 */
true, /* 75 */
true, /* 76 */
true, /* 77 */
true, /* 78 */
true, /* 79 */
true, /* 80 */
true, /* 81 */
true, /* 82 */
true, /* 83 */
true, /* 84 */
true, /* 85 */
true, /* 86 */
true, /* 87 */
true, /* 88 */
true, /* 89 */
true, /* 90 */
true, /* 91 */
false, /* 92 */
true, /* 93 */
true, /* 94 */
true, /* 95 */
true, /* 96 */
true, /* 97 */
true, /* 98 */
true, /* 99 */
true, /* 100 */
true, /* 101 */
true, /* 102 */
true, /* 103 */
true, /* 104 */
true, /* 105 */
true, /* 106 */
true, /* 107 */
true, /* 108 */
true, /* 109 */
true, /* 110 */
true, /* 111 */
true, /* 112 */
true, /* 113 */
true, /* 114 */
true, /* 115 */
true, /* 116 */
true, /* 117 */
true, /* 118 */
true, /* 119 */
true, /* 120 */
true, /* 121 */
true, /* 122 */
true, /* 123 */
true, /* 124 */
true, /* 125 */
true, /* 126 */
true, /* 127 */
true, /* 128 */
true, /* 129 */
true, /* 130 */
true, /* 131 */
true, /* 132 */
true, /* 133 */
true, /* 134 */
true, /* 135 */
true, /* 136 */
true, /* 137 */
true, /* 138 */
true, /* 139 */
true, /* 140 */
true, /* 141 */
true, /* 142 */
true, /* 143 */
true, /* 144 */
true, /* 145 */
true, /* 146 */
true, /* 147 */
true, /* 148 */
true, /* 149 */
true, /* 150 */
true, /* 151 */
true, /* 152 */
true, /* 153 */
true, /* 154 */
true, /* 155 */
true, /* 156 */
true, /* 157 */
true, /* 158 */
true, /* 159 */
true, /* 160 */
true, /* 161 */
true, /* 162 */
true, /* 163 */
true, /* 164 */
true, /* 165 */
true, /* 166 */
true, /* 167 */
true, /* 168 */
true, /* 169 */
true, /* 170 */
true, /* 171 */
true, /* 172 */
true, /* 173 */
true, /* 174 */
true, /* 175 */
true, /* 176 */
true, /* 177 */
true, /* 178 */
true, /* 179 */
true, /* 180 */
true, /* 181 */
true, /* 182 */
true, /* 183 */
true, /* 184 */
true, /* 185 */
true, /* 186 */
true, /* 187 */
true, /* 188 */
true, /* 189 */
true, /* 190 */
true, /* 191 */
true, /* 192 */
true, /* 193 */
true, /* 194 */
true, /* 195 */
true, /* 196 */
true, /* 197 */
true, /* 198 */
true, /* 199 */
true, /* 200 */
true, /* 201 */
true, /* 202 */
true, /* 203 */
true, /* 204 */
true, /* 205 */
true, /* 206 */
true, /* 207 */
true, /* 208 */
true, /* 209 */
true, /* 210 */
true, /* 211 */
true, /* 212 */
true, /* 213 */
true, /* 214 */
true, /* 215 */
true, /* 216 */
true, /* 217 */
true, /* 218 */
true, /* 219 */
true, /* 220 */
true, /* 221 */
true, /* 222 */
true, /* 223 */
true, /* 224 */
true, /* 225 */
true, /* 226 */
true, /* 227 */
true, /* 228 */
true, /* 229 */
true, /* 230 */
true, /* 231 */
true, /* 232 */
true, /* 233 */
true, /* 234 */
true, /* 235 */
true, /* 236 */
true, /* 237 */
true, /* 238 */
true, /* 239 */
true, /* 240 */
true, /* 241 */
true, /* 242 */
true, /* 243 */
true, /* 244 */
true, /* 245 */
true, /* 246 */
true, /* 247 */
true, /* 248 */
true, /* 249 */
true, /* 250 */
true, /* 251 */
true, /* 252 */
true, /* 253 */
true, /* 254 */
true, /* 255 */
}

937
vendor/github.com/pquerna/ffjson/fflib/v1/lexer.go generated vendored Normal file
View File

@ -0,0 +1,937 @@
/**
* Copyright 2014 Paul Querna
*
* 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.
*
*/
/* Portions of this file are on derived from yajl: <https://github.com/lloyd/yajl> */
/*
* Copyright (c) 2007-2014, Lloyd Hilaiel <me@lloyd.io>
*
* 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.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
package v1
import (
"errors"
"fmt"
"io"
)
type FFParseState int
const (
FFParse_map_start FFParseState = iota
FFParse_want_key
FFParse_want_colon
FFParse_want_value
FFParse_after_value
)
type FFTok int
const (
FFTok_init FFTok = iota
FFTok_bool FFTok = iota
FFTok_colon FFTok = iota
FFTok_comma FFTok = iota
FFTok_eof FFTok = iota
FFTok_error FFTok = iota
FFTok_left_brace FFTok = iota
FFTok_left_bracket FFTok = iota
FFTok_null FFTok = iota
FFTok_right_brace FFTok = iota
FFTok_right_bracket FFTok = iota
/* we differentiate between integers and doubles to allow the
* parser to interpret the number without re-scanning */
FFTok_integer FFTok = iota
FFTok_double FFTok = iota
FFTok_string FFTok = iota
/* comment tokens are not currently returned to the parser, ever */
FFTok_comment FFTok = iota
)
type FFErr int
const (
FFErr_e_ok FFErr = iota
FFErr_io FFErr = iota
FFErr_string_invalid_utf8 FFErr = iota
FFErr_string_invalid_escaped_char FFErr = iota
FFErr_string_invalid_json_char FFErr = iota
FFErr_string_invalid_hex_char FFErr = iota
FFErr_invalid_char FFErr = iota
FFErr_invalid_string FFErr = iota
FFErr_missing_integer_after_decimal FFErr = iota
FFErr_missing_integer_after_exponent FFErr = iota
FFErr_missing_integer_after_minus FFErr = iota
FFErr_unallowed_comment FFErr = iota
FFErr_incomplete_comment FFErr = iota
FFErr_unexpected_token_type FFErr = iota // TODO: improve this error
)
type FFLexer struct {
reader *ffReader
Output DecodingBuffer
Token FFTok
Error FFErr
BigError error
// TODO: convert all of this to an interface
lastCurrentChar int
captureAll bool
buf Buffer
}
func NewFFLexer(input []byte) *FFLexer {
fl := &FFLexer{
Token: FFTok_init,
Error: FFErr_e_ok,
reader: newffReader(input),
Output: &Buffer{},
}
// TODO: guess size?
//fl.Output.Grow(64)
return fl
}
type LexerError struct {
offset int
line int
char int
err error
}
// Reset the Lexer and add new input.
func (ffl *FFLexer) Reset(input []byte) {
ffl.Token = FFTok_init
ffl.Error = FFErr_e_ok
ffl.BigError = nil
ffl.reader.Reset(input)
ffl.lastCurrentChar = 0
ffl.Output.Reset()
}
func (le *LexerError) Error() string {
return fmt.Sprintf(`ffjson error: (%T)%s offset=%d line=%d char=%d`,
le.err, le.err.Error(),
le.offset, le.line, le.char)
}
func (ffl *FFLexer) WrapErr(err error) error {
line, char := ffl.reader.PosWithLine()
// TOOD: calcualte lines/characters based on offset
return &LexerError{
offset: ffl.reader.Pos(),
line: line,
char: char,
err: err,
}
}
func (ffl *FFLexer) scanReadByte() (byte, error) {
var c byte
var err error
if ffl.captureAll {
c, err = ffl.reader.ReadByte()
} else {
c, err = ffl.reader.ReadByteNoWS()
}
if err != nil {
ffl.Error = FFErr_io
ffl.BigError = err
return 0, err
}
return c, nil
}
func (ffl *FFLexer) readByte() (byte, error) {
c, err := ffl.reader.ReadByte()
if err != nil {
ffl.Error = FFErr_io
ffl.BigError = err
return 0, err
}
return c, nil
}
func (ffl *FFLexer) unreadByte() {
ffl.reader.UnreadByte()
}
func (ffl *FFLexer) wantBytes(want []byte, iftrue FFTok) FFTok {
startPos := ffl.reader.Pos()
for _, b := range want {
c, err := ffl.readByte()
if err != nil {
return FFTok_error
}
if c != b {
ffl.unreadByte()
// fmt.Printf("wanted bytes: %s\n", string(want))
// TODO(pquerna): thsi is a bad error message
ffl.Error = FFErr_invalid_string
return FFTok_error
}
}
endPos := ffl.reader.Pos()
ffl.Output.Write(ffl.reader.Slice(startPos, endPos))
return iftrue
}
func (ffl *FFLexer) lexComment() FFTok {
c, err := ffl.readByte()
if err != nil {
return FFTok_error
}
if c == '/' {
// a // comment, scan until line ends.
for {
c, err := ffl.readByte()
if err != nil {
return FFTok_error
}
if c == '\n' {
return FFTok_comment
}
}
} else if c == '*' {
// a /* */ comment, scan */
for {
c, err := ffl.readByte()
if err != nil {
return FFTok_error
}
if c == '*' {
c, err := ffl.readByte()
if err != nil {
return FFTok_error
}
if c == '/' {
return FFTok_comment
}
ffl.Error = FFErr_incomplete_comment
return FFTok_error
}
}
} else {
ffl.Error = FFErr_incomplete_comment
return FFTok_error
}
}
func (ffl *FFLexer) lexString() FFTok {
if ffl.captureAll {
ffl.buf.Reset()
err := ffl.reader.SliceString(&ffl.buf)
if err != nil {
ffl.BigError = err
return FFTok_error
}
WriteJson(ffl.Output, ffl.buf.Bytes())
return FFTok_string
} else {
err := ffl.reader.SliceString(ffl.Output)
if err != nil {
ffl.BigError = err
return FFTok_error
}
return FFTok_string
}
}
func (ffl *FFLexer) lexNumber() FFTok {
var numRead int = 0
tok := FFTok_integer
startPos := ffl.reader.Pos()
c, err := ffl.readByte()
if err != nil {
return FFTok_error
}
/* optional leading minus */
if c == '-' {
c, err = ffl.readByte()
if err != nil {
return FFTok_error
}
}
/* a single zero, or a series of integers */
if c == '0' {
c, err = ffl.readByte()
if err != nil {
return FFTok_error
}
} else if c >= '1' && c <= '9' {
for c >= '0' && c <= '9' {
c, err = ffl.readByte()
if err != nil {
return FFTok_error
}
}
} else {
ffl.unreadByte()
ffl.Error = FFErr_missing_integer_after_minus
return FFTok_error
}
if c == '.' {
numRead = 0
c, err = ffl.readByte()
if err != nil {
return FFTok_error
}
for c >= '0' && c <= '9' {
numRead++
c, err = ffl.readByte()
if err != nil {
return FFTok_error
}
}
if numRead == 0 {
ffl.unreadByte()
ffl.Error = FFErr_missing_integer_after_decimal
return FFTok_error
}
tok = FFTok_double
}
/* optional exponent (indicates this is floating point) */
if c == 'e' || c == 'E' {
numRead = 0
c, err = ffl.readByte()
if err != nil {
return FFTok_error
}
/* optional sign */
if c == '+' || c == '-' {
c, err = ffl.readByte()
if err != nil {
return FFTok_error
}
}
for c >= '0' && c <= '9' {
numRead++
c, err = ffl.readByte()
if err != nil {
return FFTok_error
}
}
if numRead == 0 {
ffl.Error = FFErr_missing_integer_after_exponent
return FFTok_error
}
tok = FFTok_double
}
ffl.unreadByte()
endPos := ffl.reader.Pos()
ffl.Output.Write(ffl.reader.Slice(startPos, endPos))
return tok
}
var true_bytes = []byte{'r', 'u', 'e'}
var false_bytes = []byte{'a', 'l', 's', 'e'}
var null_bytes = []byte{'u', 'l', 'l'}
func (ffl *FFLexer) Scan() FFTok {
tok := FFTok_error
if ffl.captureAll == false {
ffl.Output.Reset()
}
ffl.Token = FFTok_init
for {
c, err := ffl.scanReadByte()
if err != nil {
if err == io.EOF {
return FFTok_eof
} else {
return FFTok_error
}
}
switch c {
case '{':
tok = FFTok_left_bracket
if ffl.captureAll {
ffl.Output.WriteByte('{')
}
goto lexed
case '}':
tok = FFTok_right_bracket
if ffl.captureAll {
ffl.Output.WriteByte('}')
}
goto lexed
case '[':
tok = FFTok_left_brace
if ffl.captureAll {
ffl.Output.WriteByte('[')
}
goto lexed
case ']':
tok = FFTok_right_brace
if ffl.captureAll {
ffl.Output.WriteByte(']')
}
goto lexed
case ',':
tok = FFTok_comma
if ffl.captureAll {
ffl.Output.WriteByte(',')
}
goto lexed
case ':':
tok = FFTok_colon
if ffl.captureAll {
ffl.Output.WriteByte(':')
}
goto lexed
case '\t', '\n', '\v', '\f', '\r', ' ':
if ffl.captureAll {
ffl.Output.WriteByte(c)
}
break
case 't':
ffl.Output.WriteByte('t')
tok = ffl.wantBytes(true_bytes, FFTok_bool)
goto lexed
case 'f':
ffl.Output.WriteByte('f')
tok = ffl.wantBytes(false_bytes, FFTok_bool)
goto lexed
case 'n':
ffl.Output.WriteByte('n')
tok = ffl.wantBytes(null_bytes, FFTok_null)
goto lexed
case '"':
tok = ffl.lexString()
goto lexed
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
ffl.unreadByte()
tok = ffl.lexNumber()
goto lexed
case '/':
tok = ffl.lexComment()
goto lexed
default:
tok = FFTok_error
ffl.Error = FFErr_invalid_char
}
}
lexed:
ffl.Token = tok
return tok
}
func (ffl *FFLexer) scanField(start FFTok, capture bool) ([]byte, error) {
switch start {
case FFTok_left_brace,
FFTok_left_bracket:
{
end := FFTok_right_brace
if start == FFTok_left_bracket {
end = FFTok_right_bracket
if capture {
ffl.Output.WriteByte('{')
}
} else {
if capture {
ffl.Output.WriteByte('[')
}
}
depth := 1
if capture {
ffl.captureAll = true
}
// TODO: work.
scanloop:
for {
tok := ffl.Scan()
//fmt.Printf("capture-token: %v end: %v depth: %v\n", tok, end, depth)
switch tok {
case FFTok_eof:
return nil, errors.New("ffjson: unexpected EOF")
case FFTok_error:
if ffl.BigError != nil {
return nil, ffl.BigError
}
return nil, ffl.Error.ToError()
case end:
depth--
if depth == 0 {
break scanloop
}
case start:
depth++
}
}
if capture {
ffl.captureAll = false
}
if capture {
return ffl.Output.Bytes(), nil
} else {
return nil, nil
}
}
case FFTok_bool,
FFTok_integer,
FFTok_null,
FFTok_double:
// simple value, return it.
if capture {
return ffl.Output.Bytes(), nil
} else {
return nil, nil
}
case FFTok_string:
//TODO(pquerna): so, other users expect this to be a quoted string :(
if capture {
ffl.buf.Reset()
WriteJson(&ffl.buf, ffl.Output.Bytes())
return ffl.buf.Bytes(), nil
} else {
return nil, nil
}
}
return nil, fmt.Errorf("ffjson: invalid capture type: %v", start)
}
// Captures an entire field value, including recursive objects,
// and converts them to a []byte suitable to pass to a sub-object's
// UnmarshalJSON
func (ffl *FFLexer) CaptureField(start FFTok) ([]byte, error) {
return ffl.scanField(start, true)
}
func (ffl *FFLexer) SkipField(start FFTok) error {
_, err := ffl.scanField(start, false)
return err
}
// TODO(pquerna): return line number and offset.
func (err FFErr) ToError() error {
switch err {
case FFErr_e_ok:
return nil
case FFErr_io:
return errors.New("ffjson: IO error")
case FFErr_string_invalid_utf8:
return errors.New("ffjson: string with invalid UTF-8 sequence")
case FFErr_string_invalid_escaped_char:
return errors.New("ffjson: string with invalid escaped character")
case FFErr_string_invalid_json_char:
return errors.New("ffjson: string with invalid JSON character")
case FFErr_string_invalid_hex_char:
return errors.New("ffjson: string with invalid hex character")
case FFErr_invalid_char:
return errors.New("ffjson: invalid character")
case FFErr_invalid_string:
return errors.New("ffjson: invalid string")
case FFErr_missing_integer_after_decimal:
return errors.New("ffjson: missing integer after decimal")
case FFErr_missing_integer_after_exponent:
return errors.New("ffjson: missing integer after exponent")
case FFErr_missing_integer_after_minus:
return errors.New("ffjson: missing integer after minus")
case FFErr_unallowed_comment:
return errors.New("ffjson: unallowed comment")
case FFErr_incomplete_comment:
return errors.New("ffjson: incomplete comment")
case FFErr_unexpected_token_type:
return errors.New("ffjson: unexpected token sequence")
}
panic(fmt.Sprintf("unknown error type: %v ", err))
}
func (state FFParseState) String() string {
switch state {
case FFParse_map_start:
return "map:start"
case FFParse_want_key:
return "want_key"
case FFParse_want_colon:
return "want_colon"
case FFParse_want_value:
return "want_value"
case FFParse_after_value:
return "after_value"
}
panic(fmt.Sprintf("unknown parse state: %d", int(state)))
}
func (tok FFTok) String() string {
switch tok {
case FFTok_init:
return "tok:init"
case FFTok_bool:
return "tok:bool"
case FFTok_colon:
return "tok:colon"
case FFTok_comma:
return "tok:comma"
case FFTok_eof:
return "tok:eof"
case FFTok_error:
return "tok:error"
case FFTok_left_brace:
return "tok:left_brace"
case FFTok_left_bracket:
return "tok:left_bracket"
case FFTok_null:
return "tok:null"
case FFTok_right_brace:
return "tok:right_brace"
case FFTok_right_bracket:
return "tok:right_bracket"
case FFTok_integer:
return "tok:integer"
case FFTok_double:
return "tok:double"
case FFTok_string:
return "tok:string"
case FFTok_comment:
return "comment"
}
panic(fmt.Sprintf("unknown token: %d", int(tok)))
}
/* a lookup table which lets us quickly determine three things:
* cVEC - valid escaped control char
* note. the solidus '/' may be escaped or not.
* cIJC - invalid json char
* cVHC - valid hex char
* cNFP - needs further processing (from a string scanning perspective)
* cNUC - needs utf8 checking when enabled (from a string scanning perspective)
*/
const (
cVEC int8 = 0x01
cIJC int8 = 0x02
cVHC int8 = 0x04
cNFP int8 = 0x08
cNUC int8 = 0x10
)
var byteLookupTable [256]int8 = [256]int8{
cIJC, /* 0 */
cIJC, /* 1 */
cIJC, /* 2 */
cIJC, /* 3 */
cIJC, /* 4 */
cIJC, /* 5 */
cIJC, /* 6 */
cIJC, /* 7 */
cIJC, /* 8 */
cIJC, /* 9 */
cIJC, /* 10 */
cIJC, /* 11 */
cIJC, /* 12 */
cIJC, /* 13 */
cIJC, /* 14 */
cIJC, /* 15 */
cIJC, /* 16 */
cIJC, /* 17 */
cIJC, /* 18 */
cIJC, /* 19 */
cIJC, /* 20 */
cIJC, /* 21 */
cIJC, /* 22 */
cIJC, /* 23 */
cIJC, /* 24 */
cIJC, /* 25 */
cIJC, /* 26 */
cIJC, /* 27 */
cIJC, /* 28 */
cIJC, /* 29 */
cIJC, /* 30 */
cIJC, /* 31 */
0, /* 32 */
0, /* 33 */
cVEC | cIJC | cNFP, /* 34 */
0, /* 35 */
0, /* 36 */
0, /* 37 */
0, /* 38 */
0, /* 39 */
0, /* 40 */
0, /* 41 */
0, /* 42 */
0, /* 43 */
0, /* 44 */
0, /* 45 */
0, /* 46 */
cVEC, /* 47 */
cVHC, /* 48 */
cVHC, /* 49 */
cVHC, /* 50 */
cVHC, /* 51 */
cVHC, /* 52 */
cVHC, /* 53 */
cVHC, /* 54 */
cVHC, /* 55 */
cVHC, /* 56 */
cVHC, /* 57 */
0, /* 58 */
0, /* 59 */
0, /* 60 */
0, /* 61 */
0, /* 62 */
0, /* 63 */
0, /* 64 */
cVHC, /* 65 */
cVHC, /* 66 */
cVHC, /* 67 */
cVHC, /* 68 */
cVHC, /* 69 */
cVHC, /* 70 */
0, /* 71 */
0, /* 72 */
0, /* 73 */
0, /* 74 */
0, /* 75 */
0, /* 76 */
0, /* 77 */
0, /* 78 */
0, /* 79 */
0, /* 80 */
0, /* 81 */
0, /* 82 */
0, /* 83 */
0, /* 84 */
0, /* 85 */
0, /* 86 */
0, /* 87 */
0, /* 88 */
0, /* 89 */
0, /* 90 */
0, /* 91 */
cVEC | cIJC | cNFP, /* 92 */
0, /* 93 */
0, /* 94 */
0, /* 95 */
0, /* 96 */
cVHC, /* 97 */
cVEC | cVHC, /* 98 */
cVHC, /* 99 */
cVHC, /* 100 */
cVHC, /* 101 */
cVEC | cVHC, /* 102 */
0, /* 103 */
0, /* 104 */
0, /* 105 */
0, /* 106 */
0, /* 107 */
0, /* 108 */
0, /* 109 */
cVEC, /* 110 */
0, /* 111 */
0, /* 112 */
0, /* 113 */
cVEC, /* 114 */
0, /* 115 */
cVEC, /* 116 */
0, /* 117 */
0, /* 118 */
0, /* 119 */
0, /* 120 */
0, /* 121 */
0, /* 122 */
0, /* 123 */
0, /* 124 */
0, /* 125 */
0, /* 126 */
0, /* 127 */
cNUC, /* 128 */
cNUC, /* 129 */
cNUC, /* 130 */
cNUC, /* 131 */
cNUC, /* 132 */
cNUC, /* 133 */
cNUC, /* 134 */
cNUC, /* 135 */
cNUC, /* 136 */
cNUC, /* 137 */
cNUC, /* 138 */
cNUC, /* 139 */
cNUC, /* 140 */
cNUC, /* 141 */
cNUC, /* 142 */
cNUC, /* 143 */
cNUC, /* 144 */
cNUC, /* 145 */
cNUC, /* 146 */
cNUC, /* 147 */
cNUC, /* 148 */
cNUC, /* 149 */
cNUC, /* 150 */
cNUC, /* 151 */
cNUC, /* 152 */
cNUC, /* 153 */
cNUC, /* 154 */
cNUC, /* 155 */
cNUC, /* 156 */
cNUC, /* 157 */
cNUC, /* 158 */
cNUC, /* 159 */
cNUC, /* 160 */
cNUC, /* 161 */
cNUC, /* 162 */
cNUC, /* 163 */
cNUC, /* 164 */
cNUC, /* 165 */
cNUC, /* 166 */
cNUC, /* 167 */
cNUC, /* 168 */
cNUC, /* 169 */
cNUC, /* 170 */
cNUC, /* 171 */
cNUC, /* 172 */
cNUC, /* 173 */
cNUC, /* 174 */
cNUC, /* 175 */
cNUC, /* 176 */
cNUC, /* 177 */
cNUC, /* 178 */
cNUC, /* 179 */
cNUC, /* 180 */
cNUC, /* 181 */
cNUC, /* 182 */
cNUC, /* 183 */
cNUC, /* 184 */
cNUC, /* 185 */
cNUC, /* 186 */
cNUC, /* 187 */
cNUC, /* 188 */
cNUC, /* 189 */
cNUC, /* 190 */
cNUC, /* 191 */
cNUC, /* 192 */
cNUC, /* 193 */
cNUC, /* 194 */
cNUC, /* 195 */
cNUC, /* 196 */
cNUC, /* 197 */
cNUC, /* 198 */
cNUC, /* 199 */
cNUC, /* 200 */
cNUC, /* 201 */
cNUC, /* 202 */
cNUC, /* 203 */
cNUC, /* 204 */
cNUC, /* 205 */
cNUC, /* 206 */
cNUC, /* 207 */
cNUC, /* 208 */
cNUC, /* 209 */
cNUC, /* 210 */
cNUC, /* 211 */
cNUC, /* 212 */
cNUC, /* 213 */
cNUC, /* 214 */
cNUC, /* 215 */
cNUC, /* 216 */
cNUC, /* 217 */
cNUC, /* 218 */
cNUC, /* 219 */
cNUC, /* 220 */
cNUC, /* 221 */
cNUC, /* 222 */
cNUC, /* 223 */
cNUC, /* 224 */
cNUC, /* 225 */
cNUC, /* 226 */
cNUC, /* 227 */
cNUC, /* 228 */
cNUC, /* 229 */
cNUC, /* 230 */
cNUC, /* 231 */
cNUC, /* 232 */
cNUC, /* 233 */
cNUC, /* 234 */
cNUC, /* 235 */
cNUC, /* 236 */
cNUC, /* 237 */
cNUC, /* 238 */
cNUC, /* 239 */
cNUC, /* 240 */
cNUC, /* 241 */
cNUC, /* 242 */
cNUC, /* 243 */
cNUC, /* 244 */
cNUC, /* 245 */
cNUC, /* 246 */
cNUC, /* 247 */
cNUC, /* 248 */
cNUC, /* 249 */
cNUC, /* 250 */
cNUC, /* 251 */
cNUC, /* 252 */
cNUC, /* 253 */
cNUC, /* 254 */
cNUC, /* 255 */
}

512
vendor/github.com/pquerna/ffjson/fflib/v1/reader.go generated vendored Normal file
View File

@ -0,0 +1,512 @@
/**
* Copyright 2014 Paul Querna
*
* 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 v1
import (
"fmt"
"io"
"unicode"
"unicode/utf16"
)
const sliceStringMask = cIJC | cNFP
type ffReader struct {
s []byte
i int
l int
}
func newffReader(d []byte) *ffReader {
return &ffReader{
s: d,
i: 0,
l: len(d),
}
}
func (r *ffReader) Slice(start, stop int) []byte {
return r.s[start:stop]
}
func (r *ffReader) Pos() int {
return r.i
}
// Reset the reader, and add new input.
func (r *ffReader) Reset(d []byte) {
r.s = d
r.i = 0
r.l = len(d)
}
// Calcuates the Position with line and line offset,
// because this isn't counted for performance reasons,
// it will iterate the buffer from the beginning, and should
// only be used in error-paths.
func (r *ffReader) PosWithLine() (int, int) {
currentLine := 1
currentChar := 0
for i := 0; i < r.i; i++ {
c := r.s[i]
currentChar++
if c == '\n' {
currentLine++
currentChar = 0
}
}
return currentLine, currentChar
}
func (r *ffReader) ReadByteNoWS() (byte, error) {
if r.i >= r.l {
return 0, io.EOF
}
j := r.i
for {
c := r.s[j]
j++
// inline whitespace parsing gives another ~8% performance boost
// for many kinds of nicely indented JSON.
// ... and using a [255]bool instead of multiple ifs, gives another 2%
/*
if c != '\t' &&
c != '\n' &&
c != '\v' &&
c != '\f' &&
c != '\r' &&
c != ' ' {
r.i = j
return c, nil
}
*/
if whitespaceLookupTable[c] == false {
r.i = j
return c, nil
}
if j >= r.l {
return 0, io.EOF
}
}
}
func (r *ffReader) ReadByte() (byte, error) {
if r.i >= r.l {
return 0, io.EOF
}
r.i++
return r.s[r.i-1], nil
}
func (r *ffReader) UnreadByte() error {
if r.i <= 0 {
panic("ffReader.UnreadByte: at beginning of slice")
}
r.i--
return nil
}
func (r *ffReader) readU4(j int) (rune, error) {
var u4 [4]byte
for i := 0; i < 4; i++ {
if j >= r.l {
return -1, io.EOF
}
c := r.s[j]
if byteLookupTable[c]&cVHC != 0 {
u4[i] = c
j++
continue
} else {
// TODO(pquerna): handle errors better. layering violation.
return -1, fmt.Errorf("lex_string_invalid_hex_char: %v %v", c, string(u4[:]))
}
}
// TODO(pquerna): utf16.IsSurrogate
rr, err := ParseUint(u4[:], 16, 64)
if err != nil {
return -1, err
}
return rune(rr), nil
}
func (r *ffReader) handleEscaped(c byte, j int, out DecodingBuffer) (int, error) {
if j >= r.l {
return 0, io.EOF
}
c = r.s[j]
j++
if c == 'u' {
ru, err := r.readU4(j)
if err != nil {
return 0, err
}
if utf16.IsSurrogate(ru) {
ru2, err := r.readU4(j + 6)
if err != nil {
return 0, err
}
out.Write(r.s[r.i : j-2])
r.i = j + 10
j = r.i
rval := utf16.DecodeRune(ru, ru2)
if rval != unicode.ReplacementChar {
out.WriteRune(rval)
} else {
return 0, fmt.Errorf("lex_string_invalid_unicode_surrogate: %v %v", ru, ru2)
}
} else {
out.Write(r.s[r.i : j-2])
r.i = j + 4
j = r.i
out.WriteRune(ru)
}
return j, nil
} else if byteLookupTable[c]&cVEC == 0 {
return 0, fmt.Errorf("lex_string_invalid_escaped_char: %v", c)
} else {
out.Write(r.s[r.i : j-2])
r.i = j
j = r.i
switch c {
case '"':
out.WriteByte('"')
case '\\':
out.WriteByte('\\')
case '/':
out.WriteByte('/')
case 'b':
out.WriteByte('\b')
case 'f':
out.WriteByte('\f')
case 'n':
out.WriteByte('\n')
case 'r':
out.WriteByte('\r')
case 't':
out.WriteByte('\t')
}
}
return j, nil
}
func (r *ffReader) SliceString(out DecodingBuffer) error {
var c byte
// TODO(pquerna): string_with_escapes? de-escape here?
j := r.i
for {
if j >= r.l {
return io.EOF
}
j, c = scanString(r.s, j)
if c == '"' {
if j != r.i {
out.Write(r.s[r.i : j-1])
r.i = j
}
return nil
} else if c == '\\' {
var err error
j, err = r.handleEscaped(c, j, out)
if err != nil {
return err
}
} else if byteLookupTable[c]&cIJC != 0 {
return fmt.Errorf("lex_string_invalid_json_char: %v", c)
}
continue
}
}
// TODO(pquerna): consider combining wibth the normal byte mask.
var whitespaceLookupTable [256]bool = [256]bool{
false, /* 0 */
false, /* 1 */
false, /* 2 */
false, /* 3 */
false, /* 4 */
false, /* 5 */
false, /* 6 */
false, /* 7 */
false, /* 8 */
true, /* 9 */
true, /* 10 */
true, /* 11 */
true, /* 12 */
true, /* 13 */
false, /* 14 */
false, /* 15 */
false, /* 16 */
false, /* 17 */
false, /* 18 */
false, /* 19 */
false, /* 20 */
false, /* 21 */
false, /* 22 */
false, /* 23 */
false, /* 24 */
false, /* 25 */
false, /* 26 */
false, /* 27 */
false, /* 28 */
false, /* 29 */
false, /* 30 */
false, /* 31 */
true, /* 32 */
false, /* 33 */
false, /* 34 */
false, /* 35 */
false, /* 36 */
false, /* 37 */
false, /* 38 */
false, /* 39 */
false, /* 40 */
false, /* 41 */
false, /* 42 */
false, /* 43 */
false, /* 44 */
false, /* 45 */
false, /* 46 */
false, /* 47 */
false, /* 48 */
false, /* 49 */
false, /* 50 */
false, /* 51 */
false, /* 52 */
false, /* 53 */
false, /* 54 */
false, /* 55 */
false, /* 56 */
false, /* 57 */
false, /* 58 */
false, /* 59 */
false, /* 60 */
false, /* 61 */
false, /* 62 */
false, /* 63 */
false, /* 64 */
false, /* 65 */
false, /* 66 */
false, /* 67 */
false, /* 68 */
false, /* 69 */
false, /* 70 */
false, /* 71 */
false, /* 72 */
false, /* 73 */
false, /* 74 */
false, /* 75 */
false, /* 76 */
false, /* 77 */
false, /* 78 */
false, /* 79 */
false, /* 80 */
false, /* 81 */
false, /* 82 */
false, /* 83 */
false, /* 84 */
false, /* 85 */
false, /* 86 */
false, /* 87 */
false, /* 88 */
false, /* 89 */
false, /* 90 */
false, /* 91 */
false, /* 92 */
false, /* 93 */
false, /* 94 */
false, /* 95 */
false, /* 96 */
false, /* 97 */
false, /* 98 */
false, /* 99 */
false, /* 100 */
false, /* 101 */
false, /* 102 */
false, /* 103 */
false, /* 104 */
false, /* 105 */
false, /* 106 */
false, /* 107 */
false, /* 108 */
false, /* 109 */
false, /* 110 */
false, /* 111 */
false, /* 112 */
false, /* 113 */
false, /* 114 */
false, /* 115 */
false, /* 116 */
false, /* 117 */
false, /* 118 */
false, /* 119 */
false, /* 120 */
false, /* 121 */
false, /* 122 */
false, /* 123 */
false, /* 124 */
false, /* 125 */
false, /* 126 */
false, /* 127 */
false, /* 128 */
false, /* 129 */
false, /* 130 */
false, /* 131 */
false, /* 132 */
false, /* 133 */
false, /* 134 */
false, /* 135 */
false, /* 136 */
false, /* 137 */
false, /* 138 */
false, /* 139 */
false, /* 140 */
false, /* 141 */
false, /* 142 */
false, /* 143 */
false, /* 144 */
false, /* 145 */
false, /* 146 */
false, /* 147 */
false, /* 148 */
false, /* 149 */
false, /* 150 */
false, /* 151 */
false, /* 152 */
false, /* 153 */
false, /* 154 */
false, /* 155 */
false, /* 156 */
false, /* 157 */
false, /* 158 */
false, /* 159 */
false, /* 160 */
false, /* 161 */
false, /* 162 */
false, /* 163 */
false, /* 164 */
false, /* 165 */
false, /* 166 */
false, /* 167 */
false, /* 168 */
false, /* 169 */
false, /* 170 */
false, /* 171 */
false, /* 172 */
false, /* 173 */
false, /* 174 */
false, /* 175 */
false, /* 176 */
false, /* 177 */
false, /* 178 */
false, /* 179 */
false, /* 180 */
false, /* 181 */
false, /* 182 */
false, /* 183 */
false, /* 184 */
false, /* 185 */
false, /* 186 */
false, /* 187 */
false, /* 188 */
false, /* 189 */
false, /* 190 */
false, /* 191 */
false, /* 192 */
false, /* 193 */
false, /* 194 */
false, /* 195 */
false, /* 196 */
false, /* 197 */
false, /* 198 */
false, /* 199 */
false, /* 200 */
false, /* 201 */
false, /* 202 */
false, /* 203 */
false, /* 204 */
false, /* 205 */
false, /* 206 */
false, /* 207 */
false, /* 208 */
false, /* 209 */
false, /* 210 */
false, /* 211 */
false, /* 212 */
false, /* 213 */
false, /* 214 */
false, /* 215 */
false, /* 216 */
false, /* 217 */
false, /* 218 */
false, /* 219 */
false, /* 220 */
false, /* 221 */
false, /* 222 */
false, /* 223 */
false, /* 224 */
false, /* 225 */
false, /* 226 */
false, /* 227 */
false, /* 228 */
false, /* 229 */
false, /* 230 */
false, /* 231 */
false, /* 232 */
false, /* 233 */
false, /* 234 */
false, /* 235 */
false, /* 236 */
false, /* 237 */
false, /* 238 */
false, /* 239 */
false, /* 240 */
false, /* 241 */
false, /* 242 */
false, /* 243 */
false, /* 244 */
false, /* 245 */
false, /* 246 */
false, /* 247 */
false, /* 248 */
false, /* 249 */
false, /* 250 */
false, /* 251 */
false, /* 252 */
false, /* 253 */
false, /* 254 */
false, /* 255 */
}

View File

@ -0,0 +1,34 @@
/**
* Copyright 2014 Paul Querna
*
* 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 v1
func scanString(s []byte, j int) (int, byte) {
for {
if j >= len(s) {
return j, 0
}
c := s[j]
j++
if byteLookupTable[c]&sliceStringMask == 0 {
continue
}
return j, c
}
}