Moved to google.golang.org/genproto/googleapis/api/annotations
Fixes #52
This commit is contained in:
		
							
								
								
									
										4
									
								
								vendor/github.com/go-logfmt/logfmt/.gitignore
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								vendor/github.com/go-logfmt/logfmt/.gitignore
									
									
									
										generated
									
									
										vendored
									
									
										Normal 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
									
								
							
							
						
						
									
										15
									
								
								vendor/github.com/go-logfmt/logfmt/.travis.yml
									
									
									
										generated
									
									
										vendored
									
									
										Normal 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
									
								
							
							
						
						
									
										22
									
								
								vendor/github.com/go-logfmt/logfmt/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal 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
									
								
							
							
						
						
									
										33
									
								
								vendor/github.com/go-logfmt/logfmt/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,33 @@
 | 
			
		||||
[](https://godoc.org/github.com/go-logfmt/logfmt)
 | 
			
		||||
[](https://goreportcard.com/report/go-logfmt/logfmt)
 | 
			
		||||
[](https://travis-ci.org/go-logfmt/logfmt)
 | 
			
		||||
[](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'.
 | 
			
		||||
							
								
								
									
										75
									
								
								vendor/github.com/go-logfmt/logfmt/decode-bench_test.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								vendor/github.com/go-logfmt/logfmt/decode-bench_test.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal 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
									
								
							
							
						
						
									
										237
									
								
								vendor/github.com/go-logfmt/logfmt/decode.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal 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
									
								
							
							
						
						
									
										184
									
								
								vendor/github.com/go-logfmt/logfmt/decode_test.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal 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
									
								
							
							
						
						
									
										6
									
								
								vendor/github.com/go-logfmt/logfmt/doc.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal 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
									
								
							
							
						
						
									
										321
									
								
								vendor/github.com/go-logfmt/logfmt/encode.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal 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
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										233
									
								
								vendor/github.com/go-logfmt/logfmt/encode_internal_test.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										233
									
								
								vendor/github.com/go-logfmt/logfmt/encode_internal_test.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal 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
									
								
							
							
						
						
									
										206
									
								
								vendor/github.com/go-logfmt/logfmt/encode_test.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal 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
									
								
							
							
						
						
									
										60
									
								
								vendor/github.com/go-logfmt/logfmt/example_test.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal 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
									
								
							
							
						
						
									
										126
									
								
								vendor/github.com/go-logfmt/logfmt/fuzz.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal 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
									
								
							
							
						
						
									
										277
									
								
								vendor/github.com/go-logfmt/logfmt/jsonstring.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal 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
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user