Moved to google.golang.org/genproto/googleapis/api/annotations

Fixes #52
This commit is contained in:
Valerio Gheri
2017-03-31 18:01:58 +02:00
parent 024c5a4e4e
commit c40779224f
2037 changed files with 831329 additions and 1854 deletions

4
vendor/github.com/go-logfmt/logfmt/.gitignore generated vendored Normal file
View File

@@ -0,0 +1,4 @@
_testdata/
_testdata2/
logfmt-fuzz.zip
logfmt.test.exe

15
vendor/github.com/go-logfmt/logfmt/.travis.yml generated vendored Normal file
View File

@@ -0,0 +1,15 @@
language: go
sudo: false
go:
- 1.3
- 1.4
- 1.5
- 1.6
- tip
before_install:
- go get github.com/mattn/goveralls
- go get golang.org/x/tools/cmd/cover
script:
- goveralls -service=travis-ci

22
vendor/github.com/go-logfmt/logfmt/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,22 @@
The MIT License (MIT)
Copyright (c) 2015 go-logfmt
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.

33
vendor/github.com/go-logfmt/logfmt/README.md generated vendored Normal file
View File

@@ -0,0 +1,33 @@
[![GoDoc](https://godoc.org/github.com/go-logfmt/logfmt?status.svg)](https://godoc.org/github.com/go-logfmt/logfmt)
[![Go Report Card](https://goreportcard.com/badge/go-logfmt/logfmt)](https://goreportcard.com/report/go-logfmt/logfmt)
[![TravisCI](https://travis-ci.org/go-logfmt/logfmt.svg?branch=master)](https://travis-ci.org/go-logfmt/logfmt)
[![Coverage Status](https://coveralls.io/repos/github/go-logfmt/logfmt/badge.svg?branch=master)](https://coveralls.io/github/go-logfmt/logfmt?branch=master)
# logfmt
Package logfmt implements utilities to marshal and unmarshal data in the [logfmt
format](https://brandur.org/logfmt). It provides an API similar to
[encoding/json](http://golang.org/pkg/encoding/json/) and
[encoding/xml](http://golang.org/pkg/encoding/xml/).
The logfmt format was first documented by Brandur Leach in [this
article](https://brandur.org/logfmt). The format has not been formally
standardized. The most authoritative public specification to date has been the
documentation of a Go Language [package](http://godoc.org/github.com/kr/logfmt)
written by Blake Mizerany and Keith Rarick.
## Goals
This project attempts to conform as closely as possible to the prior art, while
also removing ambiguity where necessary to provide well behaved encoder and
decoder implementations.
## Non-goals
This project does not attempt to formally standardize the logfmt format. In the
event that logfmt is standardized this project would take conforming to the
standard as a goal.
## Versioning
Package logfmt publishes releases via [semver](http://semver.org/) compatible Git tags prefixed with a single 'v'.

View File

@@ -0,0 +1,75 @@
package logfmt
import (
"bufio"
"bytes"
"testing"
kr "github.com/kr/logfmt"
)
func BenchmarkDecodeKeyval(b *testing.B) {
const rows = 10000
data := []byte{}
for i := 0; i < rows; i++ {
data = append(data, "a=1 b=\"bar\" ƒ=2h3s r=\"esc\\tmore stuff\" d x=sf \n"...)
}
b.SetBytes(int64(len(data)))
b.ResetTimer()
for i := 0; i < b.N; i++ {
var (
dec = NewDecoder(bytes.NewReader(data))
j = 0
)
for dec.ScanRecord() {
for dec.ScanKeyval() {
}
j++
}
if err := dec.Err(); err != nil {
b.Errorf("got %v, want %v", err, nil)
}
if j != rows {
b.Errorf("got %v, want %v", j, rows)
}
}
}
func BenchmarkKRDecode(b *testing.B) {
const rows = 10000
data := []byte{}
for i := 0; i < rows; i++ {
data = append(data, "a=1 b=\"bar\" ƒ=2h3s r=\"esc\\tmore stuff\" d x=sf \n"...)
}
b.SetBytes(int64(len(data)))
b.ResetTimer()
for i := 0; i < b.N; i++ {
var (
s = bufio.NewScanner(bytes.NewReader(data))
err error
j = 0
dh discardHandler
)
for err == nil && s.Scan() {
err = kr.Unmarshal(s.Bytes(), &dh)
j++
}
if err == nil {
err = s.Err()
}
if err != nil {
b.Errorf("got %v, want %v", err, nil)
}
if j != rows {
b.Errorf("got %v, want %v", j, rows)
}
}
}
type discardHandler struct{}
func (discardHandler) HandleLogfmt(key, val []byte) error {
return nil
}

237
vendor/github.com/go-logfmt/logfmt/decode.go generated vendored Normal file
View File

@@ -0,0 +1,237 @@
package logfmt
import (
"bufio"
"bytes"
"fmt"
"io"
"unicode/utf8"
)
// A Decoder reads and decodes logfmt records from an input stream.
type Decoder struct {
pos int
key []byte
value []byte
lineNum int
s *bufio.Scanner
err error
}
// NewDecoder returns a new decoder that reads from r.
//
// The decoder introduces its own buffering and may read data from r beyond
// the logfmt records requested.
func NewDecoder(r io.Reader) *Decoder {
dec := &Decoder{
s: bufio.NewScanner(r),
}
return dec
}
// ScanRecord advances the Decoder to the next record, which can then be
// parsed with the ScanKeyval method. It returns false when decoding stops,
// either by reaching the end of the input or an error. After ScanRecord
// returns false, the Err method will return any error that occurred during
// decoding, except that if it was io.EOF, Err will return nil.
func (dec *Decoder) ScanRecord() bool {
if dec.err != nil {
return false
}
if !dec.s.Scan() {
dec.err = dec.s.Err()
return false
}
dec.lineNum++
dec.pos = 0
return true
}
// ScanKeyval advances the Decoder to the next key/value pair of the current
// record, which can then be retrieved with the Key and Value methods. It
// returns false when decoding stops, either by reaching the end of the
// current record or an error.
func (dec *Decoder) ScanKeyval() bool {
dec.key, dec.value = nil, nil
if dec.err != nil {
return false
}
line := dec.s.Bytes()
// garbage
for p, c := range line[dec.pos:] {
if c > ' ' {
dec.pos += p
goto key
}
}
dec.pos = len(line)
return false
key:
const invalidKeyError = "invalid key"
start, multibyte := dec.pos, false
for p, c := range line[dec.pos:] {
switch {
case c == '=':
dec.pos += p
if dec.pos > start {
dec.key = line[start:dec.pos]
if multibyte && bytes.IndexRune(dec.key, utf8.RuneError) != -1 {
dec.syntaxError(invalidKeyError)
return false
}
}
if dec.key == nil {
dec.unexpectedByte(c)
return false
}
goto equal
case c == '"':
dec.pos += p
dec.unexpectedByte(c)
return false
case c <= ' ':
dec.pos += p
if dec.pos > start {
dec.key = line[start:dec.pos]
if multibyte && bytes.IndexRune(dec.key, utf8.RuneError) != -1 {
dec.syntaxError(invalidKeyError)
return false
}
}
return true
case c >= utf8.RuneSelf:
multibyte = true
}
}
dec.pos = len(line)
if dec.pos > start {
dec.key = line[start:dec.pos]
if multibyte && bytes.IndexRune(dec.key, utf8.RuneError) != -1 {
dec.syntaxError(invalidKeyError)
return false
}
}
return true
equal:
dec.pos++
if dec.pos >= len(line) {
return true
}
switch c := line[dec.pos]; {
case c <= ' ':
return true
case c == '"':
goto qvalue
}
// value
start = dec.pos
for p, c := range line[dec.pos:] {
switch {
case c == '=' || c == '"':
dec.pos += p
dec.unexpectedByte(c)
return false
case c <= ' ':
dec.pos += p
if dec.pos > start {
dec.value = line[start:dec.pos]
}
return true
}
}
dec.pos = len(line)
if dec.pos > start {
dec.value = line[start:dec.pos]
}
return true
qvalue:
const (
untermQuote = "unterminated quoted value"
invalidQuote = "invalid quoted value"
)
hasEsc, esc := false, false
start = dec.pos
for p, c := range line[dec.pos+1:] {
switch {
case esc:
esc = false
case c == '\\':
hasEsc, esc = true, true
case c == '"':
dec.pos += p + 2
if hasEsc {
v, ok := unquoteBytes(line[start:dec.pos])
if !ok {
dec.syntaxError(invalidQuote)
return false
}
dec.value = v
} else {
start++
end := dec.pos - 1
if end > start {
dec.value = line[start:end]
}
}
return true
}
}
dec.pos = len(line)
dec.syntaxError(untermQuote)
return false
}
// Key returns the most recent key found by a call to ScanKeyval. The returned
// slice may point to internal buffers and is only valid until the next call
// to ScanRecord. It does no allocation.
func (dec *Decoder) Key() []byte {
return dec.key
}
// Value returns the most recent value found by a call to ScanKeyval. The
// returned slice may point to internal buffers and is only valid until the
// next call to ScanRecord. It does no allocation when the value has no
// escape sequences.
func (dec *Decoder) Value() []byte {
return dec.value
}
// Err returns the first non-EOF error that was encountered by the Scanner.
func (dec *Decoder) Err() error {
return dec.err
}
func (dec *Decoder) syntaxError(msg string) {
dec.err = &SyntaxError{
Msg: msg,
Line: dec.lineNum,
Pos: dec.pos + 1,
}
}
func (dec *Decoder) unexpectedByte(c byte) {
dec.err = &SyntaxError{
Msg: fmt.Sprintf("unexpected %q", c),
Line: dec.lineNum,
Pos: dec.pos + 1,
}
}
// A SyntaxError represents a syntax error in the logfmt input stream.
type SyntaxError struct {
Msg string
Line int
Pos int
}
func (e *SyntaxError) Error() string {
return fmt.Sprintf("logfmt syntax error at pos %d on line %d: %s", e.Pos, e.Line, e.Msg)
}

184
vendor/github.com/go-logfmt/logfmt/decode_test.go generated vendored Normal file
View File

@@ -0,0 +1,184 @@
package logfmt
import (
"bytes"
"fmt"
"reflect"
"strings"
"testing"
)
type kv struct {
k, v []byte
}
func (s kv) String() string {
return fmt.Sprintf("{k:%q v:%q}", s.k, s.v)
}
func TestDecoder_scan(t *testing.T) {
tests := []struct {
data string
want [][]kv
}{
{"", nil},
{"\n\n", [][]kv{nil, nil}},
{`x= `, [][]kv{{{[]byte("x"), nil}}}},
{`y=`, [][]kv{{{[]byte("y"), nil}}}},
{`y`, [][]kv{{{[]byte("y"), nil}}}},
{`y=f`, [][]kv{{{[]byte("y"), []byte("f")}}}},
{"y=\"\\tf\"", [][]kv{{{[]byte("y"), []byte("\tf")}}}},
{"a=1\n", [][]kv{{{[]byte("a"), []byte("1")}}}},
{
`a=1 b="bar" ƒ=2h3s r="esc\t" d x=sf `,
[][]kv{{
{[]byte("a"), []byte("1")},
{[]byte("b"), []byte("bar")},
{[]byte("ƒ"), []byte("2h3s")},
{[]byte("r"), []byte("esc\t")},
{[]byte("d"), nil},
{[]byte("x"), []byte("sf")},
}},
},
{
"y=f\ny=g",
[][]kv{
{{[]byte("y"), []byte("f")}},
{{[]byte("y"), []byte("g")}},
},
},
{
"y=f \n\x1e y=g",
[][]kv{
{{[]byte("y"), []byte("f")}},
{{[]byte("y"), []byte("g")}},
},
},
{
"y= d y=g",
[][]kv{{
{[]byte("y"), nil},
{[]byte("d"), nil},
{[]byte("y"), []byte("g")},
}},
},
{
"y=\"f\"\ny=g",
[][]kv{
{{[]byte("y"), []byte("f")}},
{{[]byte("y"), []byte("g")}},
},
},
{
"y=\"f\\n\"y=g",
[][]kv{{
{[]byte("y"), []byte("f\n")},
{[]byte("y"), []byte("g")},
}},
},
}
for _, test := range tests {
var got [][]kv
dec := NewDecoder(strings.NewReader(test.data))
for dec.ScanRecord() {
var kvs []kv
for dec.ScanKeyval() {
k := dec.Key()
v := dec.Value()
if k != nil {
kvs = append(kvs, kv{k, v})
}
}
got = append(got, kvs)
}
if err := dec.Err(); err != nil {
t.Errorf("got err: %v", err)
}
if !reflect.DeepEqual(got, test.want) {
t.Errorf("\n in: %q\n got: %+v\nwant: %+v", test.data, got, test.want)
}
}
}
func TestDecoder_errors(t *testing.T) {
tests := []struct {
data string
want error
}{
{"a=1\n=bar", &SyntaxError{Msg: "unexpected '='", Line: 2, Pos: 1}},
{"a=1\n\"k\"=bar", &SyntaxError{Msg: "unexpected '\"'", Line: 2, Pos: 1}},
{"a=1\nk\"ey=bar", &SyntaxError{Msg: "unexpected '\"'", Line: 2, Pos: 2}},
{"a=1\nk=b\"ar", &SyntaxError{Msg: "unexpected '\"'", Line: 2, Pos: 4}},
{"a=1\nk=b =ar", &SyntaxError{Msg: "unexpected '='", Line: 2, Pos: 5}},
{"a==", &SyntaxError{Msg: "unexpected '='", Line: 1, Pos: 3}},
{"a=1\nk=b=ar", &SyntaxError{Msg: "unexpected '='", Line: 2, Pos: 4}},
{"a=\"1", &SyntaxError{Msg: "unterminated quoted value", Line: 1, Pos: 5}},
{"a=\"1\\", &SyntaxError{Msg: "unterminated quoted value", Line: 1, Pos: 6}},
{"a=\"\\t1", &SyntaxError{Msg: "unterminated quoted value", Line: 1, Pos: 7}},
{"a=\"\\u1\"", &SyntaxError{Msg: "invalid quoted value", Line: 1, Pos: 8}},
{"a\ufffd=bar", &SyntaxError{Msg: "invalid key", Line: 1, Pos: 5}},
{"\x80=bar", &SyntaxError{Msg: "invalid key", Line: 1, Pos: 2}},
{"\x80", &SyntaxError{Msg: "invalid key", Line: 1, Pos: 2}},
}
for _, test := range tests {
dec := NewDecoder(strings.NewReader(test.data))
for dec.ScanRecord() {
for dec.ScanKeyval() {
}
}
if got, want := dec.Err(), test.want; !reflect.DeepEqual(got, want) {
t.Errorf("got: %v, want: %v", got, want)
}
}
}
func TestDecoder_decode_encode(t *testing.T) {
tests := []struct {
in, out string
}{
{"", ""},
{"\n", "\n"},
{"\n \n", "\n\n"},
{
"a=1\nb=2\n",
"a=1\nb=2\n",
},
{
"a=1 b=\"bar\" ƒ=2h3s r=\"esc\\t\" d x=sf ",
"a=1 b=bar ƒ=2h3s r=\"esc\\t\" d= x=sf\n",
},
}
for _, test := range tests {
dec := NewDecoder(strings.NewReader(test.in))
buf := bytes.Buffer{}
enc := NewEncoder(&buf)
var err error
loop:
for dec.ScanRecord() && err == nil {
for dec.ScanKeyval() {
if dec.Key() == nil {
continue
}
if err = enc.EncodeKeyval(dec.Key(), dec.Value()); err != nil {
break loop
}
}
enc.EndRecord()
}
if err == nil {
err = dec.Err()
}
if err != nil {
t.Errorf("got err: %v", err)
}
if got, want := buf.String(), test.out; got != want {
t.Errorf("\n got: %q\nwant: %q", got, want)
}
}
}

6
vendor/github.com/go-logfmt/logfmt/doc.go generated vendored Normal file
View File

@@ -0,0 +1,6 @@
// Package logfmt implements utilities to marshal and unmarshal data in the
// logfmt format. The logfmt format records key/value pairs in a way that
// balances readability for humans and simplicity of computer parsing. It is
// most commonly used as a more human friendly alternative to JSON for
// structured logging.
package logfmt

321
vendor/github.com/go-logfmt/logfmt/encode.go generated vendored Normal file
View File

@@ -0,0 +1,321 @@
package logfmt
import (
"bytes"
"encoding"
"errors"
"fmt"
"io"
"reflect"
"strings"
"unicode/utf8"
)
// MarshalKeyvals returns the logfmt encoding of keyvals, a variadic sequence
// of alternating keys and values.
func MarshalKeyvals(keyvals ...interface{}) ([]byte, error) {
buf := &bytes.Buffer{}
if err := NewEncoder(buf).EncodeKeyvals(keyvals...); err != nil {
return nil, err
}
return buf.Bytes(), nil
}
// An Encoder writes logfmt data to an output stream.
type Encoder struct {
w io.Writer
scratch bytes.Buffer
needSep bool
}
// NewEncoder returns a new encoder that writes to w.
func NewEncoder(w io.Writer) *Encoder {
return &Encoder{
w: w,
}
}
var (
space = []byte(" ")
equals = []byte("=")
newline = []byte("\n")
null = []byte("null")
)
// EncodeKeyval writes the logfmt encoding of key and value to the stream. A
// single space is written before the second and subsequent keys in a record.
// Nothing is written if a non-nil error is returned.
func (enc *Encoder) EncodeKeyval(key, value interface{}) error {
enc.scratch.Reset()
if enc.needSep {
if _, err := enc.scratch.Write(space); err != nil {
return err
}
}
if err := writeKey(&enc.scratch, key); err != nil {
return err
}
if _, err := enc.scratch.Write(equals); err != nil {
return err
}
if err := writeValue(&enc.scratch, value); err != nil {
return err
}
_, err := enc.w.Write(enc.scratch.Bytes())
enc.needSep = true
return err
}
// EncodeKeyvals writes the logfmt encoding of keyvals to the stream. Keyvals
// is a variadic sequence of alternating keys and values. Keys of unsupported
// type are skipped along with their corresponding value. Values of
// unsupported type or that cause a MarshalerError are replaced by their error
// but do not cause EncodeKeyvals to return an error. If a non-nil error is
// returned some key/value pairs may not have be written.
func (enc *Encoder) EncodeKeyvals(keyvals ...interface{}) error {
if len(keyvals) == 0 {
return nil
}
if len(keyvals)%2 == 1 {
keyvals = append(keyvals, nil)
}
for i := 0; i < len(keyvals); i += 2 {
k, v := keyvals[i], keyvals[i+1]
err := enc.EncodeKeyval(k, v)
if err == ErrUnsupportedKeyType {
continue
}
if _, ok := err.(*MarshalerError); ok || err == ErrUnsupportedValueType {
v = err
err = enc.EncodeKeyval(k, v)
}
if err != nil {
return err
}
}
return nil
}
// MarshalerError represents an error encountered while marshaling a value.
type MarshalerError struct {
Type reflect.Type
Err error
}
func (e *MarshalerError) Error() string {
return "error marshaling value of type " + e.Type.String() + ": " + e.Err.Error()
}
// ErrNilKey is returned by Marshal functions and Encoder methods if a key is
// a nil interface or pointer value.
var ErrNilKey = errors.New("nil key")
// ErrInvalidKey is returned by Marshal functions and Encoder methods if a key
// contains an invalid character.
var ErrInvalidKey = errors.New("invalid key")
// ErrUnsupportedKeyType is returned by Encoder methods if a key has an
// unsupported type.
var ErrUnsupportedKeyType = errors.New("unsupported key type")
// ErrUnsupportedValueType is returned by Encoder methods if a value has an
// unsupported type.
var ErrUnsupportedValueType = errors.New("unsupported value type")
func writeKey(w io.Writer, key interface{}) error {
if key == nil {
return ErrNilKey
}
switch k := key.(type) {
case string:
return writeStringKey(w, k)
case []byte:
if k == nil {
return ErrNilKey
}
return writeBytesKey(w, k)
case encoding.TextMarshaler:
kb, err := safeMarshal(k)
if err != nil {
return err
}
if kb == nil {
return ErrNilKey
}
return writeBytesKey(w, kb)
case fmt.Stringer:
ks, ok := safeString(k)
if !ok {
return ErrNilKey
}
return writeStringKey(w, ks)
default:
rkey := reflect.ValueOf(key)
switch rkey.Kind() {
case reflect.Array, reflect.Chan, reflect.Func, reflect.Map, reflect.Slice, reflect.Struct:
return ErrUnsupportedKeyType
case reflect.Ptr:
if rkey.IsNil() {
return ErrNilKey
}
return writeKey(w, rkey.Elem().Interface())
}
return writeStringKey(w, fmt.Sprint(k))
}
}
func invalidKeyRune(r rune) bool {
return r <= ' ' || r == '=' || r == '"' || r == utf8.RuneError
}
func invalidKeyString(key string) bool {
return len(key) == 0 || strings.IndexFunc(key, invalidKeyRune) != -1
}
func invalidKey(key []byte) bool {
return len(key) == 0 || bytes.IndexFunc(key, invalidKeyRune) != -1
}
func writeStringKey(w io.Writer, key string) error {
if invalidKeyString(key) {
return ErrInvalidKey
}
_, err := io.WriteString(w, key)
return err
}
func writeBytesKey(w io.Writer, key []byte) error {
if invalidKey(key) {
return ErrInvalidKey
}
_, err := w.Write(key)
return err
}
func writeValue(w io.Writer, value interface{}) error {
switch v := value.(type) {
case nil:
return writeBytesValue(w, null)
case string:
return writeStringValue(w, v, true)
case []byte:
return writeBytesValue(w, v)
case encoding.TextMarshaler:
vb, err := safeMarshal(v)
if err != nil {
return err
}
if vb == nil {
vb = null
}
return writeBytesValue(w, vb)
case error:
se, ok := safeError(v)
return writeStringValue(w, se, ok)
case fmt.Stringer:
ss, ok := safeString(v)
return writeStringValue(w, ss, ok)
default:
rvalue := reflect.ValueOf(value)
switch rvalue.Kind() {
case reflect.Array, reflect.Chan, reflect.Func, reflect.Map, reflect.Slice, reflect.Struct:
return ErrUnsupportedValueType
case reflect.Ptr:
if rvalue.IsNil() {
return writeBytesValue(w, null)
}
return writeValue(w, rvalue.Elem().Interface())
}
return writeStringValue(w, fmt.Sprint(v), true)
}
}
func needsQuotedValueRune(r rune) bool {
return r <= ' ' || r == '=' || r == '"' || r == utf8.RuneError
}
func writeStringValue(w io.Writer, value string, ok bool) error {
var err error
if ok && value == "null" {
_, err = io.WriteString(w, `"null"`)
} else if strings.IndexFunc(value, needsQuotedValueRune) != -1 {
_, err = writeQuotedString(w, value)
} else {
_, err = io.WriteString(w, value)
}
return err
}
func writeBytesValue(w io.Writer, value []byte) error {
var err error
if bytes.IndexFunc(value, needsQuotedValueRune) != -1 {
_, err = writeQuotedBytes(w, value)
} else {
_, err = w.Write(value)
}
return err
}
// EndRecord writes a newline character to the stream and resets the encoder
// to the beginning of a new record.
func (enc *Encoder) EndRecord() error {
_, err := enc.w.Write(newline)
if err == nil {
enc.needSep = false
}
return err
}
// Reset resets the encoder to the beginning of a new record.
func (enc *Encoder) Reset() {
enc.needSep = false
}
func safeError(err error) (s string, ok bool) {
defer func() {
if panicVal := recover(); panicVal != nil {
if v := reflect.ValueOf(err); v.Kind() == reflect.Ptr && v.IsNil() {
s, ok = "null", false
} else {
panic(panicVal)
}
}
}()
s, ok = err.Error(), true
return
}
func safeString(str fmt.Stringer) (s string, ok bool) {
defer func() {
if panicVal := recover(); panicVal != nil {
if v := reflect.ValueOf(str); v.Kind() == reflect.Ptr && v.IsNil() {
s, ok = "null", false
} else {
panic(panicVal)
}
}
}()
s, ok = str.String(), true
return
}
func safeMarshal(tm encoding.TextMarshaler) (b []byte, err error) {
defer func() {
if panicVal := recover(); panicVal != nil {
if v := reflect.ValueOf(tm); v.Kind() == reflect.Ptr && v.IsNil() {
b, err = nil, nil
} else {
panic(panicVal)
}
}
}()
b, err = tm.MarshalText()
if err != nil {
return nil, &MarshalerError{
Type: reflect.TypeOf(tm),
Err: err,
}
}
return
}

View File

@@ -0,0 +1,233 @@
package logfmt
import (
"bytes"
"errors"
"fmt"
"reflect"
"testing"
)
func TestSafeString(t *testing.T) {
_, ok := safeString((*stringStringer)(nil))
if got, want := ok, false; got != want {
t.Errorf(" got %v, want %v", got, want)
}
}
func TestSafeMarshal(t *testing.T) {
kb, err := safeMarshal((*stringMarshaler)(nil))
if got := kb; got != nil {
t.Errorf(" got %v, want nil", got)
}
if got, want := err, error(nil); got != want {
t.Errorf(" got %v, want %v", got, want)
}
}
func TestWriteKeyStrings(t *testing.T) {
keygen := []func(string) interface{}{
func(s string) interface{} { return s },
func(s string) interface{} { return stringData(s) },
func(s string) interface{} { return stringStringer(s) },
func(s string) interface{} { return stringMarshaler(s) },
}
data := []struct {
key string
want string
err error
}{
{key: "k", want: "k"},
{key: `\`, want: `\`},
{key: "\n", err: ErrInvalidKey},
{key: "\x00", err: ErrInvalidKey},
{key: "\x10", err: ErrInvalidKey},
{key: "\x1F", err: ErrInvalidKey},
{key: "", err: ErrInvalidKey},
{key: " ", err: ErrInvalidKey},
{key: "=", err: ErrInvalidKey},
{key: `"`, err: ErrInvalidKey},
}
for _, g := range keygen {
for _, d := range data {
w := &bytes.Buffer{}
key := g(d.key)
err := writeKey(w, key)
if err != d.err {
t.Errorf("%#v (%[1]T): got error: %v, want error: %v", key, err, d.err)
}
if err != nil {
continue
}
if got, want := w.String(), d.want; got != want {
t.Errorf("%#v (%[1]T): got '%s', want '%s'", key, got, want)
}
}
}
}
func TestWriteKey(t *testing.T) {
var (
nilPtr *int
one = 1
ptr = &one
)
data := []struct {
key interface{}
want string
err error
}{
{key: nil, err: ErrNilKey},
{key: nilPtr, err: ErrNilKey},
{key: (*stringStringer)(nil), err: ErrNilKey},
{key: (*stringMarshaler)(nil), err: ErrNilKey},
{key: (*stringerMarshaler)(nil), err: ErrNilKey},
{key: ptr, want: "1"},
{key: errorMarshaler{}, err: &MarshalerError{Type: reflect.TypeOf(errorMarshaler{}), Err: errMarshaling}},
{key: make(chan int), err: ErrUnsupportedKeyType},
{key: []int{}, err: ErrUnsupportedKeyType},
{key: map[int]int{}, err: ErrUnsupportedKeyType},
{key: [2]int{}, err: ErrUnsupportedKeyType},
{key: struct{}{}, err: ErrUnsupportedKeyType},
{key: fmt.Sprint, err: ErrUnsupportedKeyType},
}
for _, d := range data {
w := &bytes.Buffer{}
err := writeKey(w, d.key)
if !reflect.DeepEqual(err, d.err) {
t.Errorf("%#v: got error: %v, want error: %v", d.key, err, d.err)
}
if err != nil {
continue
}
if got, want := w.String(), d.want; got != want {
t.Errorf("%#v: got '%s', want '%s'", d.key, got, want)
}
}
}
func TestWriteValueStrings(t *testing.T) {
keygen := []func(string) interface{}{
func(s string) interface{} { return s },
func(s string) interface{} { return errors.New(s) },
func(s string) interface{} { return stringData(s) },
func(s string) interface{} { return stringStringer(s) },
func(s string) interface{} { return stringMarshaler(s) },
}
data := []struct {
value string
want string
err error
}{
{value: "", want: ""},
{value: "v", want: "v"},
{value: " ", want: `" "`},
{value: "=", want: `"="`},
{value: `\`, want: `\`},
{value: `"`, want: `"\""`},
{value: `\"`, want: `"\\\""`},
{value: "\n", want: `"\n"`},
{value: "\x00", want: `"\u0000"`},
{value: "\x10", want: `"\u0010"`},
{value: "\x1F", want: `"\u001f"`},
{value: "µ", want: `µ`},
}
for _, g := range keygen {
for _, d := range data {
w := &bytes.Buffer{}
value := g(d.value)
err := writeValue(w, value)
if err != d.err {
t.Errorf("%#v (%[1]T): got error: %v, want error: %v", value, err, d.err)
}
if err != nil {
continue
}
if got, want := w.String(), d.want; got != want {
t.Errorf("%#v (%[1]T): got '%s', want '%s'", value, got, want)
}
}
}
}
func TestWriteValue(t *testing.T) {
var (
nilPtr *int
one = 1
ptr = &one
)
data := []struct {
value interface{}
want string
err error
}{
{value: nil, want: "null"},
{value: nilPtr, want: "null"},
{value: (*stringStringer)(nil), want: "null"},
{value: (*stringMarshaler)(nil), want: "null"},
{value: (*stringerMarshaler)(nil), want: "null"},
{value: ptr, want: "1"},
{value: errorMarshaler{}, err: &MarshalerError{Type: reflect.TypeOf(errorMarshaler{}), Err: errMarshaling}},
{value: make(chan int), err: ErrUnsupportedValueType},
{value: []int{}, err: ErrUnsupportedValueType},
{value: map[int]int{}, err: ErrUnsupportedValueType},
{value: [2]int{}, err: ErrUnsupportedValueType},
{value: struct{}{}, err: ErrUnsupportedValueType},
{value: fmt.Sprint, err: ErrUnsupportedValueType},
}
for _, d := range data {
w := &bytes.Buffer{}
err := writeValue(w, d.value)
if !reflect.DeepEqual(err, d.err) {
t.Errorf("%#v: got error: %v, want error: %v", d.value, err, d.err)
}
if err != nil {
continue
}
if got, want := w.String(), d.want; got != want {
t.Errorf("%#v: got '%s', want '%s'", d.value, got, want)
}
}
}
type stringData string
type stringStringer string
func (s stringStringer) String() string {
return string(s)
}
type stringMarshaler string
func (s stringMarshaler) MarshalText() ([]byte, error) {
return []byte(s), nil
}
type stringerMarshaler string
func (s stringerMarshaler) String() string {
return "String() called"
}
func (s stringerMarshaler) MarshalText() ([]byte, error) {
return []byte(s), nil
}
var errMarshaling = errors.New("marshal error")
type errorMarshaler struct{}
func (errorMarshaler) MarshalText() ([]byte, error) {
return nil, errMarshaling
}

206
vendor/github.com/go-logfmt/logfmt/encode_test.go generated vendored Normal file
View File

@@ -0,0 +1,206 @@
package logfmt_test
import (
"bytes"
"errors"
"fmt"
"io/ioutil"
"reflect"
"testing"
"time"
"github.com/go-logfmt/logfmt"
)
func TestEncodeKeyval(t *testing.T) {
data := []struct {
key, value interface{}
want string
err error
}{
{key: "k", value: "v", want: "k=v"},
{key: "k", value: nil, want: "k=null"},
{key: `\`, value: "v", want: `\=v`},
{key: "k", value: "", want: "k="},
{key: "k", value: "null", want: `k="null"`},
{key: "k", value: "<nil>", want: `k=<nil>`},
{key: "k", value: true, want: "k=true"},
{key: "k", value: 1, want: "k=1"},
{key: "k", value: 1.025, want: "k=1.025"},
{key: "k", value: 1e-3, want: "k=0.001"},
{key: "k", value: 3.5 + 2i, want: "k=(3.5+2i)"},
{key: "k", value: "v v", want: `k="v v"`},
{key: "k", value: " ", want: `k=" "`},
{key: "k", value: `"`, want: `k="\""`},
{key: "k", value: `=`, want: `k="="`},
{key: "k", value: `\`, want: `k=\`},
{key: "k", value: `=\`, want: `k="=\\"`},
{key: "k", value: `\"`, want: `k="\\\""`},
{key: "k", value: [2]int{2, 19}, err: logfmt.ErrUnsupportedValueType},
{key: "k", value: []string{"e1", "e 2"}, err: logfmt.ErrUnsupportedValueType},
{key: "k", value: structData{"a a", 9}, err: logfmt.ErrUnsupportedValueType},
{key: "k", value: decimalMarshaler{5, 9}, want: "k=5.9"},
{key: "k", value: (*decimalMarshaler)(nil), want: "k=null"},
{key: "k", value: decimalStringer{5, 9}, want: "k=5.9"},
{key: "k", value: (*decimalStringer)(nil), want: "k=null"},
{key: "k", value: marshalerStringer{5, 9}, want: "k=5.9"},
{key: "k", value: (*marshalerStringer)(nil), want: "k=null"},
{key: "k", value: new(nilMarshaler), want: "k=notnilmarshaler"},
{key: "k", value: (*nilMarshaler)(nil), want: "k=nilmarshaler"},
{key: (*marshalerStringer)(nil), value: "v", err: logfmt.ErrNilKey},
{key: decimalMarshaler{5, 9}, value: "v", want: "5.9=v"},
{key: (*decimalMarshaler)(nil), value: "v", err: logfmt.ErrNilKey},
{key: decimalStringer{5, 9}, value: "v", want: "5.9=v"},
{key: (*decimalStringer)(nil), value: "v", err: logfmt.ErrNilKey},
{key: marshalerStringer{5, 9}, value: "v", want: "5.9=v"},
{key: "k", value: "\xbd", want: `k="\ufffd"`},
{key: "k", value: "\ufffd\x00", want: `k="\ufffd\u0000"`},
{key: "k", value: "\ufffd", want: `k="\ufffd"`},
{key: "k", value: []byte("\ufffd\x00"), want: `k="\ufffd\u0000"`},
{key: "k", value: []byte("\ufffd"), want: `k="\ufffd"`},
}
for _, d := range data {
w := &bytes.Buffer{}
enc := logfmt.NewEncoder(w)
err := enc.EncodeKeyval(d.key, d.value)
if err != d.err {
t.Errorf("%#v, %#v: got error: %v, want error: %v", d.key, d.value, err, d.err)
}
if got, want := w.String(), d.want; got != want {
t.Errorf("%#v, %#v: got '%s', want '%s'", d.key, d.value, got, want)
}
}
}
func TestMarshalKeyvals(t *testing.T) {
one := 1
ptr := &one
nilPtr := (*int)(nil)
data := []struct {
in []interface{}
want []byte
err error
}{
{in: nil, want: nil},
{in: kv(), want: nil},
{in: kv(nil, "v"), err: logfmt.ErrNilKey},
{in: kv(nilPtr, "v"), err: logfmt.ErrNilKey},
{in: kv("\ufffd"), err: logfmt.ErrInvalidKey},
{in: kv("\xbd"), err: logfmt.ErrInvalidKey},
{in: kv("k"), want: []byte("k=null")},
{in: kv("k", nil), want: []byte("k=null")},
{in: kv("k", ""), want: []byte("k=")},
{in: kv("k", "null"), want: []byte(`k="null"`)},
{in: kv("k", "v"), want: []byte("k=v")},
{in: kv("k", true), want: []byte("k=true")},
{in: kv("k", 1), want: []byte("k=1")},
{in: kv("k", ptr), want: []byte("k=1")},
{in: kv("k", nilPtr), want: []byte("k=null")},
{in: kv("k", 1.025), want: []byte("k=1.025")},
{in: kv("k", 1e-3), want: []byte("k=0.001")},
{in: kv("k", "v v"), want: []byte(`k="v v"`)},
{in: kv("k", `"`), want: []byte(`k="\""`)},
{in: kv("k", `=`), want: []byte(`k="="`)},
{in: kv("k", `\`), want: []byte(`k=\`)},
{in: kv("k", `=\`), want: []byte(`k="=\\"`)},
{in: kv("k", `\"`), want: []byte(`k="\\\""`)},
{in: kv("k1", "v1", "k2", "v2"), want: []byte("k1=v1 k2=v2")},
{in: kv("k1", "v1", "k2", [2]int{}), want: []byte("k1=v1 k2=\"unsupported value type\"")},
{in: kv([2]int{}, "v1", "k2", "v2"), want: []byte("k2=v2")},
{in: kv("k", time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)), want: []byte("k=2009-11-10T23:00:00Z")},
{in: kv("k", errorMarshaler{}), want: []byte("k=\"error marshaling value of type logfmt_test.errorMarshaler: marshal error\"")},
{in: kv("k", decimalMarshaler{5, 9}), want: []byte("k=5.9")},
{in: kv("k", (*decimalMarshaler)(nil)), want: []byte("k=null")},
{in: kv("k", decimalStringer{5, 9}), want: []byte("k=5.9")},
{in: kv("k", (*decimalStringer)(nil)), want: []byte("k=null")},
{in: kv("k", marshalerStringer{5, 9}), want: []byte("k=5.9")},
{in: kv("k", (*marshalerStringer)(nil)), want: []byte("k=null")},
{in: kv(one, "v"), want: []byte("1=v")},
{in: kv(ptr, "v"), want: []byte("1=v")},
{in: kv((*marshalerStringer)(nil), "v"), err: logfmt.ErrNilKey},
{in: kv(decimalMarshaler{5, 9}, "v"), want: []byte("5.9=v")},
{in: kv((*decimalMarshaler)(nil), "v"), err: logfmt.ErrNilKey},
{in: kv(decimalStringer{5, 9}, "v"), want: []byte("5.9=v")},
{in: kv((*decimalStringer)(nil), "v"), err: logfmt.ErrNilKey},
{in: kv(marshalerStringer{5, 9}, "v"), want: []byte("5.9=v")},
}
for _, d := range data {
got, err := logfmt.MarshalKeyvals(d.in...)
if err != d.err {
t.Errorf("%#v: got error: %v, want error: %v", d.in, err, d.err)
}
if !reflect.DeepEqual(got, d.want) {
t.Errorf("%#v: got '%s', want '%s'", d.in, got, d.want)
}
}
}
func kv(keyvals ...interface{}) []interface{} {
return keyvals
}
type structData struct {
A string `logfmt:"fieldA"`
B int
}
type nilMarshaler int
func (m *nilMarshaler) MarshalText() ([]byte, error) {
if m == nil {
return []byte("nilmarshaler"), nil
}
return []byte("notnilmarshaler"), nil
}
type decimalMarshaler struct {
a, b int
}
func (t decimalMarshaler) MarshalText() ([]byte, error) {
buf := &bytes.Buffer{}
fmt.Fprintf(buf, "%d.%d", t.a, t.b)
return buf.Bytes(), nil
}
type decimalStringer struct {
a, b int
}
func (s decimalStringer) String() string {
return fmt.Sprintf("%d.%d", s.a, s.b)
}
type marshalerStringer struct {
a, b int
}
func (t marshalerStringer) MarshalText() ([]byte, error) {
buf := &bytes.Buffer{}
fmt.Fprintf(buf, "%d.%d", t.a, t.b)
return buf.Bytes(), nil
}
func (t marshalerStringer) String() string {
return fmt.Sprint(t.a + t.b)
}
var errMarshal = errors.New("marshal error")
type errorMarshaler struct{}
func (errorMarshaler) MarshalText() ([]byte, error) {
return nil, errMarshal
}
func BenchmarkEncodeKeyval(b *testing.B) {
b.ReportAllocs()
enc := logfmt.NewEncoder(ioutil.Discard)
for i := 0; i < b.N; i++ {
enc.EncodeKeyval("sk", "10")
enc.EncodeKeyval("some-key", "a rather long string with spaces")
}
}

60
vendor/github.com/go-logfmt/logfmt/example_test.go generated vendored Normal file
View File

@@ -0,0 +1,60 @@
package logfmt_test
import (
"errors"
"fmt"
"os"
"strings"
"time"
"github.com/go-logfmt/logfmt"
)
func ExampleEncoder() {
check := func(err error) {
if err != nil {
panic(err)
}
}
e := logfmt.NewEncoder(os.Stdout)
check(e.EncodeKeyval("id", 1))
check(e.EncodeKeyval("dur", time.Second+time.Millisecond))
check(e.EndRecord())
check(e.EncodeKeyval("id", 1))
check(e.EncodeKeyval("path", "/path/to/file"))
check(e.EncodeKeyval("err", errors.New("file not found")))
check(e.EndRecord())
// Output:
// id=1 dur=1.001s
// id=1 path=/path/to/file err="file not found"
}
func ExampleDecoder() {
in := `
id=1 dur=1.001s
id=1 path=/path/to/file err="file not found"
`
d := logfmt.NewDecoder(strings.NewReader(in))
for d.ScanRecord() {
for d.ScanKeyval() {
fmt.Printf("k: %s v: %s\n", d.Key(), d.Value())
}
fmt.Println()
}
if d.Err() != nil {
panic(d.Err())
}
// Output:
// k: id v: 1
// k: dur v: 1.001s
//
// k: id v: 1
// k: path v: /path/to/file
// k: err v: file not found
}

126
vendor/github.com/go-logfmt/logfmt/fuzz.go generated vendored Normal file
View File

@@ -0,0 +1,126 @@
// +build gofuzz
package logfmt
import (
"bufio"
"bytes"
"fmt"
"io"
"reflect"
kr "github.com/kr/logfmt"
)
// Fuzz checks reserialized data matches
func Fuzz(data []byte) int {
parsed, err := parse(data)
if err != nil {
return 0
}
var w1 bytes.Buffer
if err = write(parsed, &w1); err != nil {
panic(err)
}
parsed, err = parse(w1.Bytes())
if err != nil {
panic(err)
}
var w2 bytes.Buffer
if err = write(parsed, &w2); err != nil {
panic(err)
}
if !bytes.Equal(w1.Bytes(), w2.Bytes()) {
panic(fmt.Sprintf("reserialized data does not match:\n%q\n%q\n", w1.Bytes(), w2.Bytes()))
}
return 1
}
// FuzzVsKR checks go-logfmt/logfmt against kr/logfmt
func FuzzVsKR(data []byte) int {
parsed, err := parse(data)
parsedKR, errKR := parseKR(data)
// github.com/go-logfmt/logfmt is a stricter parser. It returns errors for
// more inputs than github.com/kr/logfmt. Ignore any inputs that have a
// stict error.
if err != nil {
return 0
}
// Fail if the more forgiving parser finds an error not found by the
// stricter parser.
if errKR != nil {
panic(fmt.Sprintf("unmatched error: %v", errKR))
}
if !reflect.DeepEqual(parsed, parsedKR) {
panic(fmt.Sprintf("parsers disagree:\n%+v\n%+v\n", parsed, parsedKR))
}
return 1
}
type kv struct {
k, v []byte
}
func parse(data []byte) ([][]kv, error) {
var got [][]kv
dec := NewDecoder(bytes.NewReader(data))
for dec.ScanRecord() {
var kvs []kv
for dec.ScanKeyval() {
kvs = append(kvs, kv{dec.Key(), dec.Value()})
}
got = append(got, kvs)
}
return got, dec.Err()
}
func parseKR(data []byte) ([][]kv, error) {
var (
s = bufio.NewScanner(bytes.NewReader(data))
err error
h saveHandler
got [][]kv
)
for err == nil && s.Scan() {
h.kvs = nil
err = kr.Unmarshal(s.Bytes(), &h)
got = append(got, h.kvs)
}
if err == nil {
err = s.Err()
}
return got, err
}
type saveHandler struct {
kvs []kv
}
func (h *saveHandler) HandleLogfmt(key, val []byte) error {
if len(key) == 0 {
key = nil
}
if len(val) == 0 {
val = nil
}
h.kvs = append(h.kvs, kv{key, val})
return nil
}
func write(recs [][]kv, w io.Writer) error {
enc := NewEncoder(w)
for _, rec := range recs {
for _, f := range rec {
if err := enc.EncodeKeyval(f.k, f.v); err != nil {
return err
}
}
if err := enc.EndRecord(); err != nil {
return err
}
}
return nil
}

277
vendor/github.com/go-logfmt/logfmt/jsonstring.go generated vendored Normal file
View File

@@ -0,0 +1,277 @@
package logfmt
import (
"bytes"
"io"
"strconv"
"sync"
"unicode"
"unicode/utf16"
"unicode/utf8"
)
// Taken from Go's encoding/json and modified for use here.
// 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.
var hex = "0123456789abcdef"
var bufferPool = sync.Pool{
New: func() interface{} {
return &bytes.Buffer{}
},
}
func getBuffer() *bytes.Buffer {
return bufferPool.Get().(*bytes.Buffer)
}
func poolBuffer(buf *bytes.Buffer) {
buf.Reset()
bufferPool.Put(buf)
}
// NOTE: keep in sync with writeQuotedBytes below.
func writeQuotedString(w io.Writer, s string) (int, error) {
buf := getBuffer()
buf.WriteByte('"')
start := 0
for i := 0; i < len(s); {
if b := s[i]; b < utf8.RuneSelf {
if 0x20 <= b && b != '\\' && b != '"' {
i++
continue
}
if start < i {
buf.WriteString(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')
case '\t':
buf.WriteByte('\\')
buf.WriteByte('t')
default:
// This encodes bytes < 0x20 except for \n, \r, and \t.
buf.WriteString(`\u00`)
buf.WriteByte(hex[b>>4])
buf.WriteByte(hex[b&0xF])
}
i++
start = i
continue
}
c, size := utf8.DecodeRuneInString(s[i:])
if c == utf8.RuneError {
if start < i {
buf.WriteString(s[start:i])
}
buf.WriteString(`\ufffd`)
i += size
start = i
continue
}
i += size
}
if start < len(s) {
buf.WriteString(s[start:])
}
buf.WriteByte('"')
n, err := w.Write(buf.Bytes())
poolBuffer(buf)
return n, err
}
// NOTE: keep in sync with writeQuoteString above.
func writeQuotedBytes(w io.Writer, s []byte) (int, error) {
buf := getBuffer()
buf.WriteByte('"')
start := 0
for i := 0; i < len(s); {
if b := s[i]; b < utf8.RuneSelf {
if 0x20 <= b && b != '\\' && b != '"' {
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')
case '\t':
buf.WriteByte('\\')
buf.WriteByte('t')
default:
// This encodes bytes < 0x20 except for \n, \r, and \t.
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 {
if start < i {
buf.Write(s[start:i])
}
buf.WriteString(`\ufffd`)
i += size
start = i
continue
}
i += size
}
if start < len(s) {
buf.Write(s[start:])
}
buf.WriteByte('"')
n, err := w.Write(buf.Bytes())
poolBuffer(buf)
return n, err
}
// 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)
}
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 {
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
}