├── objutil ├── limits_test.go ├── duration_test.go ├── zero.go ├── empty.go ├── empty_test.go ├── tag.go ├── int_test.go ├── tag_test.go ├── zero_test.go ├── duration.go ├── limits.go └── int.go ├── go.mod ├── yaml ├── vendor │ ├── gopkg.in │ │ ├── check.v1 │ │ │ ├── TODO │ │ │ ├── README.md │ │ │ ├── export_test.go │ │ │ ├── LICENSE │ │ │ ├── bootstrap_test.go │ │ │ ├── reporter.go │ │ │ ├── printer_test.go │ │ │ ├── benchmark_test.go │ │ │ ├── printer.go │ │ │ ├── reporter_test.go │ │ │ ├── benchmark.go │ │ │ ├── check_test.go │ │ │ ├── run.go │ │ │ └── helpers.go │ │ └── yaml.v2 │ │ │ ├── suite_test.go │ │ │ ├── LICENSE │ │ │ ├── LICENSE.libyaml │ │ │ ├── writerc.go │ │ │ ├── sorter.go │ │ │ ├── README.md │ │ │ ├── yamlprivateh.go │ │ │ └── resolve.go │ └── vendor.json ├── yaml_test.go ├── init.go ├── encode.go ├── decode.go ├── emit.go └── parse.go ├── adapters ├── net │ ├── doc.go │ ├── url │ │ ├── doc.go │ │ ├── encode.go │ │ ├── init.go │ │ └── decode.go │ ├── mail │ │ ├── doc.go │ │ ├── encode.go │ │ ├── decode.go │ │ └── init.go │ ├── encode.go │ ├── init.go │ └── decode.go └── doc.go ├── msgpack ├── msgpack_test.go ├── init.go ├── encode.go ├── decode.go ├── msgpack.go └── emit.go ├── go.sum ├── .circleci └── config.yml ├── .gitignore ├── cbor ├── init.go ├── cbor_test.go ├── encode.go ├── decode.go ├── cbor.go └── emit.go ├── resp ├── init.go ├── error_test.go ├── error.go ├── encode.go ├── decode.go ├── decode_test.go └── encode_test.go ├── error.go ├── json ├── init.go ├── decode.go ├── encode.go ├── json_test.go ├── bench_test.go └── emit.go ├── LICENSE ├── struct_test.go ├── adapter.go ├── sort.go ├── codec.go ├── cmd └── objconv │ └── main.go ├── emit.go ├── struct.go ├── parse.go ├── README.md └── encode_test.go /objutil/limits_test.go: -------------------------------------------------------------------------------- 1 | package objutil 2 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/segmentio/objconv 2 | 3 | require gopkg.in/yaml.v2 v2.2.1 4 | -------------------------------------------------------------------------------- /yaml/vendor/gopkg.in/check.v1/TODO: -------------------------------------------------------------------------------- 1 | - Assert(slice, Contains, item) 2 | - Parallel test support 3 | -------------------------------------------------------------------------------- /yaml/vendor/gopkg.in/yaml.v2/suite_test.go: -------------------------------------------------------------------------------- 1 | package yaml_test 2 | 3 | import ( 4 | . "gopkg.in/check.v1" 5 | "testing" 6 | ) 7 | 8 | func Test(t *testing.T) { TestingT(t) } 9 | 10 | type S struct{} 11 | 12 | var _ = Suite(&S{}) 13 | -------------------------------------------------------------------------------- /adapters/net/doc.go: -------------------------------------------------------------------------------- 1 | // Package net provides adapters for types in the standard net package. 2 | // 3 | // The types and functions in this package aren't usually used direction and 4 | // instead are used implicitly by installing adapters on objconv. 5 | package net 6 | -------------------------------------------------------------------------------- /adapters/net/url/doc.go: -------------------------------------------------------------------------------- 1 | // Package url provides adapters for types in the standard net/url package. 2 | // 3 | // The types and functions in this package aren't usually used direction and 4 | // instead are used implicitly by installing adapters on objconv. 5 | package url 6 | -------------------------------------------------------------------------------- /adapters/net/mail/doc.go: -------------------------------------------------------------------------------- 1 | // Package mail provides adapters for types in the standard net/mail package. 2 | // 3 | // The types and functions in this package aren't usually used direction and 4 | // instead are used implicitly by installing adapters on objconv. 5 | package mail 6 | -------------------------------------------------------------------------------- /yaml/yaml_test.go: -------------------------------------------------------------------------------- 1 | package yaml 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/segmentio/objconv/objtests" 7 | ) 8 | 9 | func TestCodec(t *testing.T) { 10 | objtests.TestCodec(t, Codec) 11 | } 12 | 13 | func BenchmarkCodec(b *testing.B) { 14 | objtests.BenchmarkCodec(b, Codec) 15 | } 16 | -------------------------------------------------------------------------------- /msgpack/msgpack_test.go: -------------------------------------------------------------------------------- 1 | package msgpack 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/segmentio/objconv/objtests" 7 | ) 8 | 9 | func TestCodec(t *testing.T) { 10 | objtests.TestCodec(t, Codec) 11 | } 12 | 13 | func BenchmarkCodec(b *testing.B) { 14 | objtests.BenchmarkCodec(b, Codec) 15 | } 16 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= 2 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 3 | gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE= 4 | gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 5 | -------------------------------------------------------------------------------- /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | jobs: 3 | build: 4 | working_directory: /go/src/github.com/segmentio/objconv 5 | docker: 6 | - image: circleci/golang 7 | steps: 8 | - checkout 9 | - setup_remote_docker: { reusable: true, docker_layer_caching: true } 10 | - run: go get -v -t ./... 11 | - run: go vet ./... 12 | - run: go test -v -race ./... 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 2 | *.o 3 | *.a 4 | *.so 5 | 6 | # Folders 7 | _obj 8 | _test 9 | 10 | # Architecture specific extensions/prefixes 11 | *.[568vq] 12 | [568vq].out 13 | 14 | *.cgo1.go 15 | *.cgo2.c 16 | _cgo_defun.c 17 | _cgo_gotypes.go 18 | _cgo_export.* 19 | 20 | _testmain.go 21 | 22 | *.exe 23 | *.test 24 | *.prof 25 | /objconv 26 | 27 | # Emacs 28 | *~ 29 | -------------------------------------------------------------------------------- /adapters/net/url/encode.go: -------------------------------------------------------------------------------- 1 | package url 2 | 3 | import ( 4 | "net/url" 5 | "reflect" 6 | 7 | "github.com/segmentio/objconv" 8 | ) 9 | 10 | func encodeURL(e objconv.Encoder, v reflect.Value) error { 11 | u := v.Interface().(url.URL) 12 | return e.Encode(u.String()) 13 | } 14 | 15 | func encodeQuery(e objconv.Encoder, v reflect.Value) error { 16 | q := v.Interface().(url.Values) 17 | return e.Encode(q.Encode()) 18 | } 19 | -------------------------------------------------------------------------------- /yaml/vendor/gopkg.in/check.v1/README.md: -------------------------------------------------------------------------------- 1 | Instructions 2 | ============ 3 | 4 | Install the package with: 5 | 6 | go get gopkg.in/check.v1 7 | 8 | Import it with: 9 | 10 | import "gopkg.in/check.v1" 11 | 12 | and use _check_ as the package name inside the code. 13 | 14 | For more details, visit the project page: 15 | 16 | * http://labix.org/gocheck 17 | 18 | and the API documentation: 19 | 20 | * https://gopkg.in/check.v1 21 | -------------------------------------------------------------------------------- /adapters/doc.go: -------------------------------------------------------------------------------- 1 | // Package adapters installs all adapters from its subpackages into the objconv 2 | // package. 3 | // 4 | // This package exposes no functions or types and is solely useful for the side 5 | // effect of setting up extra adapters on the objconv package on initialization. 6 | package adapters 7 | 8 | import ( 9 | _ "github.com/segmentio/objconv/adapters/net" 10 | _ "github.com/segmentio/objconv/adapters/net/mail" 11 | _ "github.com/segmentio/objconv/adapters/net/url" 12 | ) 13 | -------------------------------------------------------------------------------- /cbor/init.go: -------------------------------------------------------------------------------- 1 | package cbor 2 | 3 | import ( 4 | "io" 5 | 6 | "github.com/segmentio/objconv" 7 | ) 8 | 9 | // Codec for the CBOR format. 10 | var Codec = objconv.Codec{ 11 | NewEmitter: func(w io.Writer) objconv.Emitter { return NewEmitter(w) }, 12 | NewParser: func(r io.Reader) objconv.Parser { return NewParser(r) }, 13 | } 14 | 15 | func init() { 16 | for _, name := range [...]string{ 17 | "application/cbor", 18 | "cbor", 19 | } { 20 | objconv.Register(name, Codec) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /yaml/vendor/gopkg.in/check.v1/export_test.go: -------------------------------------------------------------------------------- 1 | package check 2 | 3 | import "io" 4 | 5 | func PrintLine(filename string, line int) (string, error) { 6 | return printLine(filename, line) 7 | } 8 | 9 | func Indent(s, with string) string { 10 | return indent(s, with) 11 | } 12 | 13 | func NewOutputWriter(writer io.Writer, stream, verbose bool) *outputWriter { 14 | return newOutputWriter(writer, stream, verbose) 15 | } 16 | 17 | func (c *C) FakeSkip(reason string) { 18 | c.reason = reason 19 | } 20 | -------------------------------------------------------------------------------- /msgpack/init.go: -------------------------------------------------------------------------------- 1 | package msgpack 2 | 3 | import ( 4 | "io" 5 | 6 | "github.com/segmentio/objconv" 7 | ) 8 | 9 | // Codec for the MessagePack format. 10 | var Codec = objconv.Codec{ 11 | NewEmitter: func(w io.Writer) objconv.Emitter { return NewEmitter(w) }, 12 | NewParser: func(r io.Reader) objconv.Parser { return NewParser(r) }, 13 | } 14 | 15 | func init() { 16 | for _, name := range [...]string{ 17 | "application/msgpack", 18 | "msgpack", 19 | } { 20 | objconv.Register(name, Codec) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /resp/init.go: -------------------------------------------------------------------------------- 1 | package resp 2 | 3 | import ( 4 | "io" 5 | 6 | "github.com/segmentio/objconv" 7 | ) 8 | 9 | // Codec for the RESP format. 10 | var Codec = objconv.Codec{ 11 | NewEmitter: func(w io.Writer) objconv.Emitter { return NewEmitter(w) }, 12 | NewParser: func(r io.Reader) objconv.Parser { return NewParser(r) }, 13 | } 14 | 15 | func init() { 16 | for _, name := range [...]string{ 17 | "application/resp", 18 | "text/resp", 19 | "resp", 20 | } { 21 | objconv.Register(name, Codec) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /yaml/init.go: -------------------------------------------------------------------------------- 1 | package yaml 2 | 3 | import ( 4 | "io" 5 | 6 | "github.com/segmentio/objconv" 7 | ) 8 | 9 | // Codec for the YAML format. 10 | var Codec = objconv.Codec{ 11 | NewEmitter: func(w io.Writer) objconv.Emitter { return NewEmitter(w) }, 12 | NewParser: func(r io.Reader) objconv.Parser { return NewParser(r) }, 13 | } 14 | 15 | func init() { 16 | for _, name := range [...]string{ 17 | "application/yaml", 18 | "text/yaml", 19 | "yaml", 20 | } { 21 | objconv.Register(name, Codec) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /cbor/cbor_test.go: -------------------------------------------------------------------------------- 1 | package cbor 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/segmentio/objconv/objtests" 7 | ) 8 | 9 | func TestCodec(t *testing.T) { 10 | objtests.TestCodec(t, Codec) 11 | } 12 | 13 | func BenchmarkCodec(b *testing.B) { 14 | objtests.BenchmarkCodec(b, Codec) 15 | } 16 | 17 | func TestMajorType(t *testing.T) { 18 | m, b := majorType(majorByte(majorType7, 24)) 19 | 20 | if m != majorType7 { 21 | t.Error("bad major type:", m) 22 | } 23 | 24 | if b != 24 { 25 | t.Error("bad info value:", b) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /error.go: -------------------------------------------------------------------------------- 1 | package objconv 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | ) 7 | 8 | func typeConversionError(from Type, to Type) error { 9 | return fmt.Errorf("objconv: cannot convert from %s to %s", from, to) 10 | } 11 | 12 | var ( 13 | // End is expected to be returned to indicate that a function has completed 14 | // its work, this is usually employed in generic algorithms. 15 | End = errors.New("end") 16 | 17 | // This error value is used as a building block for reflection and is never 18 | // returned by the package. 19 | errBase = errors.New("") 20 | ) 21 | -------------------------------------------------------------------------------- /yaml/vendor/vendor.json: -------------------------------------------------------------------------------- 1 | { 2 | "comment": "", 3 | "ignore": "", 4 | "package": [ 5 | { 6 | "checksumSHA1": "538I8ghUdvZa25NxgMUDpq14Qic=", 7 | "path": "gopkg.in/check.v1", 8 | "revision": "20d25e2804050c1cd24a7eea1e7a6447dd0e74ec", 9 | "revisionTime": "2016-12-08T18:13:25Z" 10 | }, 11 | { 12 | "checksumSHA1": "lJHPwsxC3Xws7TIRUrB3Ki5HqkU=", 13 | "path": "gopkg.in/yaml.v2", 14 | "revision": "a5b47d31c556af34a302ce5d659e6fea44d90de0", 15 | "revisionTime": "2016-09-28T15:37:09Z" 16 | } 17 | ], 18 | "rootPath": "github.com/segmentio/objconv/yaml" 19 | } 20 | -------------------------------------------------------------------------------- /resp/error_test.go: -------------------------------------------------------------------------------- 1 | package resp 2 | 3 | import "testing" 4 | 5 | func TestErrorType(t *testing.T) { 6 | tests := []struct { 7 | err Error 8 | typ string 9 | }{ 10 | { 11 | err: Error("ERR wrong number of arguments for 'set' command"), 12 | typ: "ERR", 13 | }, 14 | { 15 | err: Error(""), 16 | typ: "", 17 | }, 18 | { 19 | err: Error("hello world!"), 20 | typ: "", 21 | }, 22 | } 23 | 24 | for _, test := range tests { 25 | t.Run(test.err.Error(), func(t *testing.T) { 26 | if typ := test.err.Type(); typ != test.typ { 27 | t.Error("bad error type:", typ) 28 | } 29 | }) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /yaml/vendor/gopkg.in/yaml.v2/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2011-2016 Canonical Ltd. 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | -------------------------------------------------------------------------------- /adapters/net/mail/encode.go: -------------------------------------------------------------------------------- 1 | package mail 2 | 3 | import ( 4 | "bytes" 5 | "net/mail" 6 | "reflect" 7 | 8 | "github.com/segmentio/objconv" 9 | ) 10 | 11 | func encodeAddress(e objconv.Encoder, v reflect.Value) error { 12 | a := v.Interface().(mail.Address) 13 | return e.Encode(a.String()) 14 | } 15 | 16 | func encodeAddressList(e objconv.Encoder, v reflect.Value) error { 17 | l := v.Interface().([]*mail.Address) 18 | b := &bytes.Buffer{} 19 | 20 | for i, a := range l { 21 | if a == nil { 22 | continue 23 | } 24 | if i != 0 { 25 | b.WriteString(", ") 26 | } 27 | b.WriteString(a.String()) 28 | } 29 | 30 | return e.Encode(b.String()) 31 | } 32 | -------------------------------------------------------------------------------- /adapters/net/url/init.go: -------------------------------------------------------------------------------- 1 | package url 2 | 3 | import ( 4 | "net/url" 5 | "reflect" 6 | 7 | "github.com/segmentio/objconv" 8 | ) 9 | 10 | func init() { 11 | objconv.Install(reflect.TypeOf(url.URL{}), URLAdapter()) 12 | objconv.Install(reflect.TypeOf(url.Values(nil)), QueryAdapter()) 13 | } 14 | 15 | // URLAdapter returns the adapter to encode and decode url.URL values. 16 | func URLAdapter() objconv.Adapter { 17 | return objconv.Adapter{ 18 | Encode: encodeURL, 19 | Decode: decodeURL, 20 | } 21 | } 22 | 23 | // QueryAdapter returns the adapter to encode and decode url.Values values. 24 | func QueryAdapter() objconv.Adapter { 25 | return objconv.Adapter{ 26 | Encode: encodeQuery, 27 | Decode: decodeQuery, 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /json/init.go: -------------------------------------------------------------------------------- 1 | package json 2 | 3 | import ( 4 | "io" 5 | 6 | "github.com/segmentio/objconv" 7 | ) 8 | 9 | // Codec for the JSON format. 10 | var Codec = objconv.Codec{ 11 | NewEmitter: func(w io.Writer) objconv.Emitter { return NewEmitter(w) }, 12 | NewParser: func(r io.Reader) objconv.Parser { return NewParser(r) }, 13 | } 14 | 15 | // PrettyCodec for the JSON format. 16 | var PrettyCodec = objconv.Codec{ 17 | NewEmitter: func(w io.Writer) objconv.Emitter { return NewPrettyEmitter(w) }, 18 | NewParser: func(r io.Reader) objconv.Parser { return NewParser(r) }, 19 | } 20 | 21 | func init() { 22 | for _, name := range [...]string{ 23 | "application/json", 24 | "text/json", 25 | "json", 26 | } { 27 | objconv.Register(name, Codec) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /resp/error.go: -------------------------------------------------------------------------------- 1 | package resp 2 | 3 | import ( 4 | "strings" 5 | "unicode" 6 | ) 7 | 8 | // The Error type represents redis errors. 9 | type Error string 10 | 11 | // NewError returns a new redis error. 12 | func NewError(s string) *Error { 13 | e := Error(s) 14 | return &e 15 | } 16 | 17 | // Error satsifies the error interface. 18 | func (e *Error) Error() string { 19 | return string(*e) 20 | } 21 | 22 | // Type returns the RESP error type, which is represented by the leading 23 | // uppercase word in the error string. 24 | func (e *Error) Type() string { 25 | s := e.Error() 26 | 27 | if i := strings.IndexByte(s, ' '); i < 0 { 28 | s = "" 29 | } else { 30 | s = s[:i] 31 | 32 | for _, c := range s { 33 | if !unicode.IsUpper(c) { 34 | s = "" 35 | break 36 | } 37 | } 38 | } 39 | 40 | return s 41 | } 42 | -------------------------------------------------------------------------------- /adapters/net/encode.go: -------------------------------------------------------------------------------- 1 | package net 2 | 3 | import ( 4 | "net" 5 | "reflect" 6 | 7 | "github.com/segmentio/objconv" 8 | ) 9 | 10 | func encodeTCPAddr(e objconv.Encoder, v reflect.Value) error { 11 | a := v.Interface().(net.TCPAddr) 12 | return e.Encode(a.String()) 13 | } 14 | 15 | func encodeUDPAddr(e objconv.Encoder, v reflect.Value) error { 16 | a := v.Interface().(net.UDPAddr) 17 | return e.Encode(a.String()) 18 | } 19 | 20 | func encodeUnixAddr(e objconv.Encoder, v reflect.Value) error { 21 | a := v.Interface().(net.UnixAddr) 22 | return e.Encode(a.String()) 23 | } 24 | 25 | func encodeIPAddr(e objconv.Encoder, v reflect.Value) error { 26 | a := v.Interface().(net.IPAddr) 27 | return e.Encode(a.String()) 28 | } 29 | 30 | func encodeIP(e objconv.Encoder, v reflect.Value) error { 31 | a := v.Interface().(net.IP) 32 | return e.Encode(a.String()) 33 | } 34 | -------------------------------------------------------------------------------- /objutil/duration_test.go: -------------------------------------------------------------------------------- 1 | package objutil 2 | 3 | import ( 4 | "testing" 5 | "time" 6 | ) 7 | 8 | var durationTests = []time.Duration{ 9 | 0, 10 | time.Nanosecond, 11 | time.Microsecond, 12 | time.Millisecond, 13 | time.Second, 14 | time.Minute, 15 | time.Hour, 16 | time.Hour + time.Minute + time.Second + (123456789 * time.Nanosecond), 17 | } 18 | 19 | func TestAppendDuration(t *testing.T) { 20 | for _, test := range durationTests { 21 | t.Run(test.String(), func(t *testing.T) { 22 | b := AppendDuration(nil, test) 23 | s := string(b) 24 | 25 | if s != test.String() { 26 | t.Error(s) 27 | } 28 | }) 29 | } 30 | } 31 | 32 | func BenchmarkAppendDuration(b *testing.B) { 33 | for _, test := range durationTests { 34 | b.Run(test.String(), func(b *testing.B) { 35 | var a [32]byte 36 | for i := 0; i != b.N; i++ { 37 | AppendDuration(a[:0], test) 38 | } 39 | }) 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /adapters/net/url/decode.go: -------------------------------------------------------------------------------- 1 | package url 2 | 3 | import ( 4 | "errors" 5 | "net/url" 6 | "reflect" 7 | 8 | "github.com/segmentio/objconv" 9 | ) 10 | 11 | func decodeURL(d objconv.Decoder, to reflect.Value) (err error) { 12 | var u *url.URL 13 | var s string 14 | 15 | if err = d.Decode(&s); err != nil { 16 | return 17 | } 18 | 19 | if u, err = url.Parse(s); err != nil { 20 | err = errors.New("objconv: bad URL: " + err.Error()) 21 | return 22 | } 23 | 24 | if to.IsValid() { 25 | to.Set(reflect.ValueOf(*u)) 26 | } 27 | return 28 | } 29 | 30 | func decodeQuery(d objconv.Decoder, to reflect.Value) (err error) { 31 | var v url.Values 32 | var s string 33 | 34 | if err = d.Decode(&s); err != nil { 35 | 36 | } 37 | 38 | if v, err = url.ParseQuery(s); err != nil { 39 | err = errors.New("objconv: bad URL values: " + err.Error()) 40 | return 41 | } 42 | 43 | if to.IsValid() { 44 | to.Set(reflect.ValueOf(v)) 45 | } 46 | return 47 | } 48 | -------------------------------------------------------------------------------- /adapters/net/mail/decode.go: -------------------------------------------------------------------------------- 1 | package mail 2 | 3 | import ( 4 | "errors" 5 | "net/mail" 6 | "reflect" 7 | 8 | "github.com/segmentio/objconv" 9 | ) 10 | 11 | func decodeAddress(d objconv.Decoder, to reflect.Value) (err error) { 12 | var a *mail.Address 13 | var s string 14 | 15 | if err = d.Decode(&s); err != nil { 16 | return 17 | } 18 | 19 | if a, err = mail.ParseAddress(s); err != nil { 20 | err = errors.New("objconv: bad email address: " + err.Error()) 21 | return 22 | } 23 | 24 | if to.IsValid() { 25 | to.Set(reflect.ValueOf(*a)) 26 | } 27 | return 28 | } 29 | 30 | func decodeAddressList(d objconv.Decoder, to reflect.Value) (err error) { 31 | var l []*mail.Address 32 | var s string 33 | 34 | if err = d.Decode(&s); err != nil { 35 | return 36 | } 37 | 38 | if l, err = mail.ParseAddressList(s); err != nil { 39 | err = errors.New("objconv: bad email address list: " + err.Error()) 40 | return 41 | } 42 | 43 | if to.IsValid() { 44 | to.Set(reflect.ValueOf(l)) 45 | } 46 | return 47 | } 48 | -------------------------------------------------------------------------------- /adapters/net/mail/init.go: -------------------------------------------------------------------------------- 1 | package mail 2 | 3 | import ( 4 | "net/mail" 5 | "reflect" 6 | 7 | "github.com/segmentio/objconv" 8 | ) 9 | 10 | func init() { 11 | objconv.Install(reflect.TypeOf(mail.Address{}), AddressAdapter()) 12 | objconv.Install(reflect.TypeOf(([]*mail.Address)(nil)), AddressListAdapter()) 13 | } 14 | 15 | // AddressAdapter returns the adapter to encode and decode mail.Address values. 16 | func AddressAdapter() objconv.Adapter { 17 | return objconv.Adapter{ 18 | Encode: encodeAddress, 19 | Decode: decodeAddress, 20 | } 21 | } 22 | 23 | // AddressListAdapter returns the adapter to encode and decode []*mail.Address 24 | // values. 25 | // 26 | // The adapter uses a string representation of the mail address list, in cases 27 | // where the serialized form has to be an actual array of strings the program 28 | // should use []mail.Address (no pointers). 29 | func AddressListAdapter() objconv.Adapter { 30 | return objconv.Adapter{ 31 | Encode: encodeAddressList, 32 | Decode: decodeAddressList, 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Segment 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /yaml/encode.go: -------------------------------------------------------------------------------- 1 | package yaml 2 | 3 | import ( 4 | "bytes" 5 | "io" 6 | "sync" 7 | 8 | "github.com/segmentio/objconv" 9 | ) 10 | 11 | // NewEncoder returns a new YAML encoder that writes to w. 12 | func NewEncoder(w io.Writer) *objconv.Encoder { 13 | return objconv.NewEncoder(NewEmitter(w)) 14 | } 15 | 16 | // NewStreamEncoder returns a new YAML stream encoder that writes to w. 17 | func NewStreamEncoder(w io.Writer) *objconv.StreamEncoder { 18 | return objconv.NewStreamEncoder(NewEmitter(w)) 19 | } 20 | 21 | // Marshal writes the YAML representation of v to a byte slice returned in b. 22 | func Marshal(v interface{}) (b []byte, err error) { 23 | m := marshalerPool.Get().(*marshaler) 24 | m.b.Truncate(0) 25 | 26 | if err = (objconv.Encoder{Emitter: m}).Encode(v); err == nil { 27 | b = make([]byte, m.b.Len()) 28 | copy(b, m.b.Bytes()) 29 | } 30 | 31 | marshalerPool.Put(m) 32 | return 33 | } 34 | 35 | var marshalerPool = sync.Pool{ 36 | New: func() interface{} { return newMarshaler() }, 37 | } 38 | 39 | type marshaler struct { 40 | Emitter 41 | b bytes.Buffer 42 | } 43 | 44 | func newMarshaler() *marshaler { 45 | m := &marshaler{} 46 | m.w = &m.b 47 | return m 48 | } 49 | -------------------------------------------------------------------------------- /cbor/encode.go: -------------------------------------------------------------------------------- 1 | package cbor 2 | 3 | import ( 4 | "bytes" 5 | "io" 6 | "sync" 7 | 8 | "github.com/segmentio/objconv" 9 | ) 10 | 11 | // NewEncoder returns a new MessagePack encoder that writes to w. 12 | func NewEncoder(w io.Writer) *objconv.Encoder { 13 | return objconv.NewEncoder(NewEmitter(w)) 14 | } 15 | 16 | // NewStreamEncoder returns a new MessagePack stream encoder that writes to w. 17 | func NewStreamEncoder(w io.Writer) *objconv.StreamEncoder { 18 | return objconv.NewStreamEncoder(NewEmitter(w)) 19 | } 20 | 21 | // Marshal writes the MessagePack representation of v to a byte slice returned in b. 22 | func Marshal(v interface{}) (b []byte, err error) { 23 | m := marshalerPool.Get().(*marshaler) 24 | m.b.Truncate(0) 25 | 26 | if err = (objconv.Encoder{Emitter: m}).Encode(v); err == nil { 27 | b = make([]byte, m.b.Len()) 28 | copy(b, m.b.Bytes()) 29 | } 30 | 31 | marshalerPool.Put(m) 32 | return 33 | } 34 | 35 | var marshalerPool = sync.Pool{ 36 | New: func() interface{} { return newMarshaler() }, 37 | } 38 | 39 | type marshaler struct { 40 | Emitter 41 | b bytes.Buffer 42 | } 43 | 44 | func newMarshaler() *marshaler { 45 | m := &marshaler{} 46 | m.w = &m.b 47 | return m 48 | } 49 | -------------------------------------------------------------------------------- /resp/encode.go: -------------------------------------------------------------------------------- 1 | package resp 2 | 3 | import ( 4 | "bytes" 5 | "io" 6 | "sync" 7 | 8 | "github.com/segmentio/objconv" 9 | ) 10 | 11 | // NewEncoder returns a new RESP encoder that writes to w. 12 | func NewEncoder(w io.Writer) *objconv.Encoder { 13 | return objconv.NewEncoder(NewEmitter(w)) 14 | } 15 | 16 | // NewStreamEncoder returns a new RESP stream encoder that writes to w. 17 | func NewStreamEncoder(w io.Writer) *objconv.StreamEncoder { 18 | return objconv.NewStreamEncoder(NewEmitter(w)) 19 | } 20 | 21 | // Marshal writes the RESP representation of v to a byte slice returned in b. 22 | func Marshal(v interface{}) (b []byte, err error) { 23 | m := marshalerPool.Get().(*marshaler) 24 | m.b.Truncate(0) 25 | 26 | if err = (objconv.Encoder{Emitter: m}).Encode(v); err == nil { 27 | b = make([]byte, m.b.Len()) 28 | copy(b, m.b.Bytes()) 29 | } 30 | 31 | marshalerPool.Put(m) 32 | return 33 | } 34 | 35 | var marshalerPool = sync.Pool{ 36 | New: func() interface{} { return newMarshaler() }, 37 | } 38 | 39 | type marshaler struct { 40 | Emitter 41 | b bytes.Buffer 42 | } 43 | 44 | func newMarshaler() *marshaler { 45 | m := &marshaler{} 46 | m.s = m.a[:0] 47 | m.w = &m.b 48 | return m 49 | } 50 | -------------------------------------------------------------------------------- /msgpack/encode.go: -------------------------------------------------------------------------------- 1 | package msgpack 2 | 3 | import ( 4 | "bytes" 5 | "io" 6 | "sync" 7 | 8 | "github.com/segmentio/objconv" 9 | ) 10 | 11 | // NewEncoder returns a new MessagePack encoder that writes to w. 12 | func NewEncoder(w io.Writer) *objconv.Encoder { 13 | return objconv.NewEncoder(NewEmitter(w)) 14 | } 15 | 16 | // NewStreamEncoder returns a new MessagePack stream encoder that writes to w. 17 | func NewStreamEncoder(w io.Writer) *objconv.StreamEncoder { 18 | return objconv.NewStreamEncoder(NewEmitter(w)) 19 | } 20 | 21 | // Marshal writes the MessagePack representation of v to a byte slice returned in b. 22 | func Marshal(v interface{}) (b []byte, err error) { 23 | m := marshalerPool.Get().(*marshaler) 24 | m.b.Truncate(0) 25 | 26 | if err = (objconv.Encoder{Emitter: m}).Encode(v); err == nil { 27 | b = make([]byte, m.b.Len()) 28 | copy(b, m.b.Bytes()) 29 | } 30 | 31 | marshalerPool.Put(m) 32 | return 33 | } 34 | 35 | var marshalerPool = sync.Pool{ 36 | New: func() interface{} { return newMarshaler() }, 37 | } 38 | 39 | type marshaler struct { 40 | Emitter 41 | b bytes.Buffer 42 | } 43 | 44 | func newMarshaler() *marshaler { 45 | m := &marshaler{} 46 | m.w = &m.b 47 | return m 48 | } 49 | -------------------------------------------------------------------------------- /resp/decode.go: -------------------------------------------------------------------------------- 1 | package resp 2 | 3 | import ( 4 | "bytes" 5 | "io" 6 | "sync" 7 | 8 | "github.com/segmentio/objconv" 9 | ) 10 | 11 | // NewDecoder returns a new RESP decoder that parses values from r. 12 | func NewDecoder(r io.Reader) *objconv.Decoder { 13 | return objconv.NewDecoder(NewParser(r)) 14 | } 15 | 16 | // NewStreamDecoder returns a new RESP stream decoder that parses values from r. 17 | func NewStreamDecoder(r io.Reader) *objconv.StreamDecoder { 18 | return objconv.NewStreamDecoder(NewParser(r)) 19 | } 20 | 21 | // Unmarshal decodes a RESP representation of v from b. 22 | func Unmarshal(b []byte, v interface{}) error { 23 | u := unmarshalerPool.Get().(*unmarshaler) 24 | u.reset(b) 25 | 26 | err := (objconv.Decoder{Parser: u}).Decode(v) 27 | 28 | u.reset(nil) 29 | unmarshalerPool.Put(u) 30 | return err 31 | } 32 | 33 | var unmarshalerPool = sync.Pool{ 34 | New: func() interface{} { return newUnmarshaler() }, 35 | } 36 | 37 | type unmarshaler struct { 38 | Parser 39 | b bytes.Buffer 40 | } 41 | 42 | func newUnmarshaler() *unmarshaler { 43 | u := &unmarshaler{} 44 | u.r = &u.b 45 | return u 46 | } 47 | 48 | func (u *unmarshaler) reset(b []byte) { 49 | u.b = *bytes.NewBuffer(b) 50 | u.Reset(&u.b) 51 | } 52 | -------------------------------------------------------------------------------- /yaml/decode.go: -------------------------------------------------------------------------------- 1 | package yaml 2 | 3 | import ( 4 | "bytes" 5 | "io" 6 | "sync" 7 | 8 | "github.com/segmentio/objconv" 9 | ) 10 | 11 | // NewDecoder returns a new YAML decoder that parses values from r. 12 | func NewDecoder(r io.Reader) *objconv.Decoder { 13 | return objconv.NewDecoder(NewParser(r)) 14 | } 15 | 16 | // NewStreamDecoder returns a new YAML stream decoder that parses values from r. 17 | func NewStreamDecoder(r io.Reader) *objconv.StreamDecoder { 18 | return objconv.NewStreamDecoder(NewParser(r)) 19 | } 20 | 21 | // Unmarshal decodes a YAML representation of v from b. 22 | func Unmarshal(b []byte, v interface{}) error { 23 | u := unmarshalerPool.Get().(*unmarshaler) 24 | u.reset(b) 25 | 26 | err := (objconv.Decoder{Parser: u}).Decode(v) 27 | 28 | u.reset(nil) 29 | unmarshalerPool.Put(u) 30 | return err 31 | } 32 | 33 | var unmarshalerPool = sync.Pool{ 34 | New: func() interface{} { return newUnmarshaler() }, 35 | } 36 | 37 | type unmarshaler struct { 38 | Parser 39 | b bytes.Buffer 40 | } 41 | 42 | func newUnmarshaler() *unmarshaler { 43 | u := &unmarshaler{} 44 | u.r = &u.b 45 | return u 46 | } 47 | 48 | func (u *unmarshaler) reset(b []byte) { 49 | u.b = *bytes.NewBuffer(b) 50 | u.Reset(&u.b) 51 | } 52 | -------------------------------------------------------------------------------- /cbor/decode.go: -------------------------------------------------------------------------------- 1 | package cbor 2 | 3 | import ( 4 | "bytes" 5 | "io" 6 | "sync" 7 | 8 | "github.com/segmentio/objconv" 9 | ) 10 | 11 | // NewDecoder returns a new MessagePack decoder that parses values from r. 12 | func NewDecoder(r io.Reader) *objconv.Decoder { 13 | return objconv.NewDecoder(NewParser(r)) 14 | } 15 | 16 | // NewStreamDecoder returns a new MessagePack stream decoder that parses values from r. 17 | func NewStreamDecoder(r io.Reader) *objconv.StreamDecoder { 18 | return objconv.NewStreamDecoder(NewParser(r)) 19 | } 20 | 21 | // Unmarshal decodes a MessagePack representation of v from b. 22 | func Unmarshal(b []byte, v interface{}) error { 23 | u := unmarshalerPool.Get().(*unmarshaler) 24 | u.reset(b) 25 | 26 | err := (objconv.Decoder{Parser: u}).Decode(v) 27 | 28 | u.reset(nil) 29 | unmarshalerPool.Put(u) 30 | return err 31 | } 32 | 33 | var unmarshalerPool = sync.Pool{ 34 | New: func() interface{} { return newUnmarshaler() }, 35 | } 36 | 37 | type unmarshaler struct { 38 | Parser 39 | b bytes.Buffer 40 | } 41 | 42 | func newUnmarshaler() *unmarshaler { 43 | u := &unmarshaler{} 44 | u.r = &u.b 45 | return u 46 | } 47 | 48 | func (u *unmarshaler) reset(b []byte) { 49 | u.b = *bytes.NewBuffer(b) 50 | u.Reset(&u.b) 51 | } 52 | -------------------------------------------------------------------------------- /json/decode.go: -------------------------------------------------------------------------------- 1 | package json 2 | 3 | import ( 4 | "bytes" 5 | "io" 6 | "sync" 7 | 8 | "github.com/segmentio/objconv" 9 | ) 10 | 11 | // NewDecoder returns a new JSON decoder that parses values from r. 12 | func NewDecoder(r io.Reader) *objconv.Decoder { 13 | return objconv.NewDecoder(NewParser(r)) 14 | } 15 | 16 | // NewStreamDecoder returns a new JSON stream decoder that parses values from r. 17 | func NewStreamDecoder(r io.Reader) *objconv.StreamDecoder { 18 | return objconv.NewStreamDecoder(NewParser(r)) 19 | } 20 | 21 | // Unmarshal decodes a JSON representation of v from b. 22 | func Unmarshal(b []byte, v interface{}) error { 23 | u := unmarshalerPool.Get().(*unmarshaler) 24 | u.reset(b) 25 | 26 | err := (objconv.Decoder{Parser: u}).Decode(v) 27 | 28 | u.reset(nil) 29 | unmarshalerPool.Put(u) 30 | return err 31 | } 32 | 33 | var unmarshalerPool = sync.Pool{ 34 | New: func() interface{} { return newUnmarshaler() }, 35 | } 36 | 37 | type unmarshaler struct { 38 | Parser 39 | b bytes.Buffer 40 | } 41 | 42 | func newUnmarshaler() *unmarshaler { 43 | u := &unmarshaler{} 44 | u.s = u.c[:0] 45 | u.r = &u.b 46 | return u 47 | } 48 | 49 | func (u *unmarshaler) reset(b []byte) { 50 | u.b = *bytes.NewBuffer(b) 51 | u.Reset(&u.b) 52 | } 53 | -------------------------------------------------------------------------------- /struct_test.go: -------------------------------------------------------------------------------- 1 | package objconv 2 | 3 | import ( 4 | "reflect" 5 | "testing" 6 | ) 7 | 8 | func TestMakeStructField(t *testing.T) { 9 | type A struct{ A int } 10 | type a struct{ a int } 11 | type B struct{ A } 12 | type b struct{ a } 13 | 14 | tests := []struct { 15 | s reflect.StructField 16 | f structField 17 | }{ 18 | { 19 | s: reflect.TypeOf(A{}).Field(0), 20 | f: structField{ 21 | index: []int{0}, 22 | name: "A", 23 | }, 24 | }, 25 | 26 | { 27 | s: reflect.TypeOf(a{}).Field(0), 28 | f: structField{ 29 | index: []int{0}, 30 | name: "a", 31 | }, 32 | }, 33 | 34 | { 35 | s: reflect.TypeOf(B{}).Field(0), 36 | f: structField{ 37 | index: []int{0}, 38 | name: "A", 39 | }, 40 | }, 41 | 42 | { 43 | s: reflect.TypeOf(b{}).Field(0), 44 | f: structField{ 45 | index: []int{0}, 46 | name: "a", 47 | }, 48 | }, 49 | } 50 | 51 | for _, test := range tests { 52 | t.Run("", func(t *testing.T) { 53 | f := makeStructField(test.s, map[reflect.Type]*structType{}) 54 | f.decode = nil // function types are not comparable 55 | f.encode = nil 56 | 57 | if !reflect.DeepEqual(test.f, f) { 58 | t.Errorf("%#v != %#v", test.f, f) 59 | } 60 | }) 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /msgpack/decode.go: -------------------------------------------------------------------------------- 1 | package msgpack 2 | 3 | import ( 4 | "bytes" 5 | "io" 6 | "sync" 7 | 8 | "github.com/segmentio/objconv" 9 | ) 10 | 11 | // NewDecoder returns a new MessagePack decoder that parses values from r. 12 | func NewDecoder(r io.Reader) *objconv.Decoder { 13 | return objconv.NewDecoder(NewParser(r)) 14 | } 15 | 16 | // NewStreamDecoder returns a new MessagePack stream decoder that parses values from r. 17 | func NewStreamDecoder(r io.Reader) *objconv.StreamDecoder { 18 | return objconv.NewStreamDecoder(NewParser(r)) 19 | } 20 | 21 | // Unmarshal decodes a MessagePack representation of v from b. 22 | func Unmarshal(b []byte, v interface{}) error { 23 | u := unmarshalerPool.Get().(*unmarshaler) 24 | u.reset(b) 25 | 26 | err := (objconv.Decoder{Parser: u}).Decode(v) 27 | 28 | u.reset(nil) 29 | unmarshalerPool.Put(u) 30 | return err 31 | } 32 | 33 | var unmarshalerPool = sync.Pool{ 34 | New: func() interface{} { return newUnmarshaler() }, 35 | } 36 | 37 | type unmarshaler struct { 38 | Parser 39 | b bytes.Buffer 40 | } 41 | 42 | func newUnmarshaler() *unmarshaler { 43 | u := &unmarshaler{} 44 | u.r = &u.b 45 | return u 46 | } 47 | 48 | func (u *unmarshaler) reset(b []byte) { 49 | u.b = *bytes.NewBuffer(b) 50 | u.Reset(&u.b) 51 | } 52 | -------------------------------------------------------------------------------- /yaml/vendor/gopkg.in/yaml.v2/LICENSE.libyaml: -------------------------------------------------------------------------------- 1 | The following files were ported to Go from C files of libyaml, and thus 2 | are still covered by their original copyright and license: 3 | 4 | apic.go 5 | emitterc.go 6 | parserc.go 7 | readerc.go 8 | scannerc.go 9 | writerc.go 10 | yamlh.go 11 | yamlprivateh.go 12 | 13 | Copyright (c) 2006 Kirill Simonov 14 | 15 | Permission is hereby granted, free of charge, to any person obtaining a copy of 16 | this software and associated documentation files (the "Software"), to deal in 17 | the Software without restriction, including without limitation the rights to 18 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 19 | of the Software, and to permit persons to whom the Software is furnished to do 20 | so, subject to the following conditions: 21 | 22 | The above copyright notice and this permission notice shall be included in all 23 | copies or substantial portions of the Software. 24 | 25 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 26 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 27 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 28 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 29 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 30 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 31 | SOFTWARE. 32 | -------------------------------------------------------------------------------- /yaml/vendor/gopkg.in/check.v1/LICENSE: -------------------------------------------------------------------------------- 1 | Gocheck - A rich testing framework for Go 2 | 3 | Copyright (c) 2010-2013 Gustavo Niemeyer 4 | 5 | All rights reserved. 6 | 7 | Redistribution and use in source and binary forms, with or without 8 | modification, are permitted provided that the following conditions are met: 9 | 10 | 1. Redistributions of source code must retain the above copyright notice, this 11 | list of conditions and the following disclaimer. 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 20 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | -------------------------------------------------------------------------------- /objutil/zero.go: -------------------------------------------------------------------------------- 1 | package objutil 2 | 3 | import ( 4 | "reflect" 5 | "unsafe" 6 | ) 7 | 8 | // IsZero returns true if the value given as argument is the zero-value of 9 | // the type of v. 10 | func IsZero(v interface{}) bool { 11 | return IsZeroValue(reflect.ValueOf(v)) 12 | } 13 | 14 | func IsZeroValue(v reflect.Value) bool { 15 | if !v.IsValid() { 16 | return true // nil interface{} 17 | } 18 | switch v.Kind() { 19 | case reflect.Map, reflect.Slice, reflect.Ptr, reflect.Interface, reflect.Chan, reflect.Func: 20 | return v.IsNil() 21 | case reflect.Bool: 22 | return !v.Bool() 23 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 24 | return v.Int() == 0 25 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: 26 | return v.Uint() == 0 27 | case reflect.Float32, reflect.Float64: 28 | return v.Float() == 0 29 | case reflect.String: 30 | return v.Len() == 0 31 | case reflect.UnsafePointer: 32 | return unsafe.Pointer(v.Pointer()) == nil 33 | case reflect.Array: 34 | return isZeroArray(v) 35 | case reflect.Struct: 36 | return isZeroStruct(v) 37 | } 38 | return false 39 | } 40 | 41 | func isZeroArray(v reflect.Value) bool { 42 | for i, n := 0, v.Len(); i != n; i++ { 43 | if !IsZeroValue(v.Index(i)) { 44 | return false 45 | } 46 | } 47 | return true 48 | } 49 | 50 | func isZeroStruct(v reflect.Value) bool { 51 | for i, n := 0, v.NumField(); i != n; i++ { 52 | if !IsZeroValue(v.Field(i)) { 53 | return false 54 | } 55 | } 56 | return true 57 | } 58 | -------------------------------------------------------------------------------- /json/encode.go: -------------------------------------------------------------------------------- 1 | package json 2 | 3 | import ( 4 | "bytes" 5 | "io" 6 | "sync" 7 | 8 | "github.com/segmentio/objconv" 9 | ) 10 | 11 | // NewEncoder returns a new JSON encoder that writes to w. 12 | func NewEncoder(w io.Writer) *objconv.Encoder { 13 | return objconv.NewEncoder(NewEmitter(w)) 14 | } 15 | 16 | // NewStreamEncoder returns a new JSON stream encoder that writes to w. 17 | func NewStreamEncoder(w io.Writer) *objconv.StreamEncoder { 18 | return objconv.NewStreamEncoder(NewEmitter(w)) 19 | } 20 | 21 | // NewPrettyEncoder returns a new JSON encoder that writes to w. 22 | func NewPrettyEncoder(w io.Writer) *objconv.Encoder { 23 | return objconv.NewEncoder(NewPrettyEmitter(w)) 24 | } 25 | 26 | // NewPrettyStreamEncoder returns a new JSON stream encoder that writes to w. 27 | func NewPrettyStreamEncoder(w io.Writer) *objconv.StreamEncoder { 28 | return objconv.NewStreamEncoder(NewPrettyEmitter(w)) 29 | } 30 | 31 | // Marshal writes the JSON representation of v to a byte slice returned in b. 32 | func Marshal(v interface{}) (b []byte, err error) { 33 | m := marshalerPool.Get().(*marshaler) 34 | m.b.Truncate(0) 35 | 36 | if err = (objconv.Encoder{Emitter: m}).Encode(v); err == nil { 37 | b = make([]byte, m.b.Len()) 38 | copy(b, m.b.Bytes()) 39 | } 40 | 41 | marshalerPool.Put(m) 42 | return 43 | } 44 | 45 | var marshalerPool = sync.Pool{ 46 | New: func() interface{} { return newMarshaler() }, 47 | } 48 | 49 | type marshaler struct { 50 | Emitter 51 | b bytes.Buffer 52 | } 53 | 54 | func newMarshaler() *marshaler { 55 | m := &marshaler{} 56 | m.s = m.a[:0] 57 | m.w = &m.b 58 | return m 59 | } 60 | -------------------------------------------------------------------------------- /adapters/net/init.go: -------------------------------------------------------------------------------- 1 | package net 2 | 3 | import ( 4 | "net" 5 | "reflect" 6 | 7 | "github.com/segmentio/objconv" 8 | ) 9 | 10 | func init() { 11 | objconv.Install(reflect.TypeOf(net.TCPAddr{}), TCPAddrAdapter()) 12 | objconv.Install(reflect.TypeOf(net.UDPAddr{}), UDPAddrAdapter()) 13 | objconv.Install(reflect.TypeOf(net.UnixAddr{}), UnixAddrAdapter()) 14 | objconv.Install(reflect.TypeOf(net.IPAddr{}), IPAddrAdapter()) 15 | objconv.Install(reflect.TypeOf(net.IP(nil)), IPAdapter()) 16 | } 17 | 18 | // TCPAddrAdapter returns the adapter to encode and decode net.TCPAddr values. 19 | func TCPAddrAdapter() objconv.Adapter { 20 | return objconv.Adapter{ 21 | Encode: encodeTCPAddr, 22 | Decode: decodeTCPAddr, 23 | } 24 | } 25 | 26 | // UDPAddrAdapter returns the adapter to encode and decode net.UDPAddr values. 27 | func UDPAddrAdapter() objconv.Adapter { 28 | return objconv.Adapter{ 29 | Encode: encodeUDPAddr, 30 | Decode: decodeUDPAddr, 31 | } 32 | } 33 | 34 | // UnixAddrAdapter returns the adapter to encode and decode net.UnixAddr values. 35 | func UnixAddrAdapter() objconv.Adapter { 36 | return objconv.Adapter{ 37 | Encode: encodeUnixAddr, 38 | Decode: decodeUnixAddr, 39 | } 40 | } 41 | 42 | // IPAddrAdapter returns the adapter to encode and decode net.IPAddr values. 43 | func IPAddrAdapter() objconv.Adapter { 44 | return objconv.Adapter{ 45 | Encode: encodeIPAddr, 46 | Decode: decodeIPAddr, 47 | } 48 | } 49 | 50 | // IPAdapter returns the adapter to encode and decode net.IP values. 51 | func IPAdapter() objconv.Adapter { 52 | return objconv.Adapter{ 53 | Encode: encodeIP, 54 | Decode: decodeIP, 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /objutil/empty.go: -------------------------------------------------------------------------------- 1 | package objutil 2 | 3 | // Copyright 2009 The Go Authors. All rights reserved. 4 | // Use of this source code is governed by a BSD-style 5 | // license that can be found in the LICENSE file. 6 | 7 | import ( 8 | "reflect" 9 | "unsafe" 10 | ) 11 | 12 | // IsEmpty returns true if the value given as argument would be considered 13 | // empty by the standard library packages, and therefore not serialized if 14 | // `omitempty` is set on a struct field with this value. 15 | func IsEmpty(v interface{}) bool { 16 | return IsEmptyValue(reflect.ValueOf(v)) 17 | } 18 | 19 | // IsEmptyValue returns true if the value given as argument would be considered 20 | // empty by the standard library packages, and therefore not serialized if 21 | // `omitempty` is set on a struct field with this value. 22 | // 23 | // Based on https://golang.org/src/encoding/json/encode.go?h=isEmpty 24 | func IsEmptyValue(v reflect.Value) bool { 25 | if !v.IsValid() { 26 | return true // nil interface{} 27 | } 28 | switch v.Kind() { 29 | case reflect.Array, reflect.Map, reflect.Slice, reflect.String: 30 | return v.Len() == 0 31 | case reflect.Bool: 32 | return !v.Bool() 33 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 34 | return v.Int() == 0 35 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: 36 | return v.Uint() == 0 37 | case reflect.Float32, reflect.Float64: 38 | return v.Float() == 0 39 | case reflect.Interface, reflect.Ptr, reflect.Chan, reflect.Func: 40 | return v.IsNil() 41 | case reflect.UnsafePointer: 42 | return unsafe.Pointer(v.Pointer()) == nil 43 | } 44 | return false 45 | } 46 | -------------------------------------------------------------------------------- /msgpack/msgpack.go: -------------------------------------------------------------------------------- 1 | package msgpack 2 | 3 | import "encoding/binary" 4 | 5 | const ( 6 | Nil = 0xC0 7 | False = 0xC2 8 | True = 0xC3 9 | 10 | Bin8 = 0xC4 11 | Bin16 = 0xC5 12 | Bin32 = 0xC6 13 | 14 | Ext8 = 0xC7 15 | Ext16 = 0xC8 16 | Ext32 = 0xC9 17 | 18 | Float32 = 0xCA 19 | Float64 = 0xCB 20 | 21 | Uint8 = 0xCC 22 | Uint16 = 0xCD 23 | Uint32 = 0xCE 24 | Uint64 = 0xCF 25 | 26 | Int8 = 0xD0 27 | Int16 = 0xD1 28 | Int32 = 0xD2 29 | Int64 = 0xD3 30 | 31 | Fixext1 = 0xD4 32 | Fixext2 = 0xD5 33 | Fixext4 = 0xD6 34 | Fixext8 = 0xD7 35 | Fixext16 = 0xD8 36 | 37 | Str8 = 0xD9 38 | Str16 = 0xDA 39 | Str32 = 0xDB 40 | 41 | Array16 = 0xDC 42 | Array32 = 0xDD 43 | 44 | Map16 = 0xDE 45 | Map32 = 0xDF 46 | 47 | FixmapMask = 0xF0 48 | FixmapTag = 0x80 49 | 50 | FixarrayMask = 0xF0 51 | FixarrayTag = 0x90 52 | 53 | FixstrMask = 0xE0 54 | FixstrTag = 0xA0 55 | 56 | PositiveFixintMask = 0x80 57 | PositiveFixintTag = 0x00 58 | 59 | NegativeFixintMask = 0xE0 60 | NegativeFixintTag = 0xE0 61 | 62 | ExtTime = int8(-1) 63 | ) 64 | 65 | func putUint16(b []byte, v uint16) { 66 | binary.BigEndian.PutUint16(b, v) 67 | } 68 | 69 | func putUint32(b []byte, v uint32) { 70 | binary.BigEndian.PutUint32(b, v) 71 | } 72 | 73 | func putUint64(b []byte, v uint64) { 74 | binary.BigEndian.PutUint64(b, v) 75 | } 76 | 77 | func getUint16(b []byte) uint16 { 78 | return binary.BigEndian.Uint16(b) 79 | } 80 | 81 | func getUint32(b []byte) uint32 { 82 | return binary.BigEndian.Uint32(b) 83 | } 84 | 85 | func getUint64(b []byte) uint64 { 86 | return binary.BigEndian.Uint64(b) 87 | } 88 | 89 | func align(n int, a int) int { 90 | if (n % a) == 0 { 91 | return n 92 | } 93 | return ((n / a) + 1) * a 94 | } 95 | -------------------------------------------------------------------------------- /objutil/empty_test.go: -------------------------------------------------------------------------------- 1 | package objutil 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | "unsafe" 7 | ) 8 | 9 | func TestIsEmptyTrue(t *testing.T) { 10 | tests := []interface{}{ 11 | nil, 12 | 13 | false, 14 | 15 | int(0), 16 | int8(0), 17 | int16(0), 18 | int32(0), 19 | int64(0), 20 | 21 | uint(0), 22 | uint8(0), 23 | uint16(0), 24 | uint32(0), 25 | uint64(0), 26 | uintptr(0), 27 | 28 | float32(0), 29 | float64(0), 30 | 31 | "", 32 | []byte(nil), 33 | []int{}, 34 | [...]int{}, 35 | 36 | (map[string]int)(nil), 37 | map[string]int{}, 38 | 39 | (*int)(nil), 40 | unsafe.Pointer(nil), 41 | 42 | (chan struct{})(nil), 43 | (func())(nil), 44 | } 45 | 46 | for _, test := range tests { 47 | t.Run(fmt.Sprintf("%T", test), func(t *testing.T) { 48 | if !IsEmpty(test) { 49 | t.Errorf("%T, %#v should be an empty value", test, test) 50 | } 51 | }) 52 | } 53 | } 54 | 55 | func TestIsEmptyFalse(t *testing.T) { 56 | answer := 42 57 | 58 | tests := []interface{}{ 59 | true, 60 | 61 | int(1), 62 | int8(1), 63 | int16(1), 64 | int32(1), 65 | int64(1), 66 | 67 | uint(1), 68 | uint8(1), 69 | uint16(1), 70 | uint32(1), 71 | uint64(1), 72 | uintptr(1), 73 | 74 | float32(1), 75 | float64(1), 76 | 77 | "Hello World!", 78 | []byte("Hello World!"), 79 | []int{1, 2, 3}, 80 | [...]int{1, 2, 3}, 81 | 82 | map[string]int{"answer": 42}, 83 | 84 | &answer, 85 | unsafe.Pointer(&answer), 86 | 87 | make(chan struct{}), 88 | func() {}, 89 | } 90 | 91 | for _, test := range tests { 92 | t.Run(fmt.Sprintf("%T", test), func(t *testing.T) { 93 | if IsEmpty(test) { 94 | t.Errorf("%T, %#v should not be an empty value", test, test) 95 | } 96 | }) 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /objutil/tag.go: -------------------------------------------------------------------------------- 1 | package objutil 2 | 3 | import "strings" 4 | 5 | // Tag represents the result of parsing the tag of a struct field. 6 | type Tag struct { 7 | // Name is the field name that should be used when serializing. 8 | Name string 9 | 10 | // Omitempty is true if the tag had `omitempty` set. 11 | Omitempty bool 12 | 13 | // Omitzero is true if the tag had `omitzero` set. 14 | Omitzero bool 15 | } 16 | 17 | // ParseTag parses a raw tag obtained from a struct field, returning the results 18 | // as a tag value. 19 | func ParseTag(s string) Tag { 20 | var name string 21 | var omitzero bool 22 | var omitempty bool 23 | 24 | name, s = parseNextTagToken(s) 25 | 26 | for len(s) != 0 { 27 | var token string 28 | switch token, s = parseNextTagToken(s); token { 29 | case "omitempty": 30 | omitempty = true 31 | case "omitzero": 32 | omitzero = true 33 | } 34 | } 35 | 36 | return Tag{ 37 | Name: name, 38 | Omitempty: omitempty, 39 | Omitzero: omitzero, 40 | } 41 | } 42 | 43 | // ParseTagJSON is similar to ParseTag but only supports features supported by 44 | // the standard encoding/json package. 45 | func ParseTagJSON(s string) Tag { 46 | var name string 47 | var omitempty bool 48 | 49 | name, s = parseNextTagToken(s) 50 | 51 | for len(s) != 0 { 52 | var token string 53 | switch token, s = parseNextTagToken(s); token { 54 | case "omitempty": 55 | omitempty = true 56 | } 57 | } 58 | 59 | return Tag{ 60 | Name: name, 61 | Omitempty: omitempty, 62 | } 63 | } 64 | 65 | func parseNextTagToken(s string) (token string, next string) { 66 | if split := strings.IndexByte(s, ','); split < 0 { 67 | token = s 68 | } else { 69 | token, next = s[:split], s[split+1:] 70 | } 71 | return 72 | } 73 | -------------------------------------------------------------------------------- /adapter.go: -------------------------------------------------------------------------------- 1 | package objconv 2 | 3 | import ( 4 | "reflect" 5 | "sync" 6 | ) 7 | 8 | // An Adapter is a pair of an encoder and a decoder function that can be 9 | // installed on the package to support new types. 10 | type Adapter struct { 11 | Encode func(Encoder, reflect.Value) error 12 | Decode func(Decoder, reflect.Value) error 13 | } 14 | 15 | // Install adds an adapter for typ. 16 | // 17 | // The function panics if one of the encoder and decoder functions of the 18 | // adapter are nil. 19 | // 20 | // A typical use case for this function is to be called during the package 21 | // initialization phase to extend objconv support for new types. 22 | func Install(typ reflect.Type, adapter Adapter) { 23 | if adapter.Encode == nil { 24 | panic("objconv: the encoder function of an adapter cannot be nil") 25 | } 26 | 27 | if adapter.Decode == nil { 28 | panic("objconv: the decoder function of an adapter cannot be nil") 29 | } 30 | 31 | adapterMutex.Lock() 32 | adapterStore[typ] = adapter 33 | adapterMutex.Unlock() 34 | 35 | // We have to clear the struct cache because it may now have become invalid. 36 | // Because installing adapters is done in the package initialization phase 37 | // it's unlikely that any encoding or decoding operations are taking place 38 | // at this time so there should be no performance impact of clearing the 39 | // cache. 40 | structCache.clear() 41 | } 42 | 43 | // AdapterOf returns the adapter for typ, setting ok to true if one was found, 44 | // false otherwise. 45 | func AdapterOf(typ reflect.Type) (a Adapter, ok bool) { 46 | adapterMutex.RLock() 47 | a, ok = adapterStore[typ] 48 | adapterMutex.RUnlock() 49 | return 50 | } 51 | 52 | var ( 53 | adapterMutex sync.RWMutex 54 | adapterStore = make(map[reflect.Type]Adapter) 55 | ) 56 | -------------------------------------------------------------------------------- /objutil/int_test.go: -------------------------------------------------------------------------------- 1 | package objutil 2 | 3 | import "testing" 4 | 5 | var parseIntTests = []struct { 6 | v int64 7 | s string 8 | }{ 9 | {0, "0"}, 10 | {1, "1"}, 11 | {-1, "-1"}, 12 | {1234567890, "1234567890"}, 13 | {-1234567890, "-1234567890"}, 14 | {9223372036854775807, "9223372036854775807"}, 15 | {-9223372036854775808, "-9223372036854775808"}, 16 | } 17 | 18 | func TestParseInt(t *testing.T) { 19 | for _, test := range parseIntTests { 20 | t.Run(test.s, func(t *testing.T) { 21 | v, err := ParseInt([]byte(test.s)) 22 | 23 | if err != nil { 24 | t.Error(err) 25 | } 26 | 27 | if v != test.v { 28 | t.Error(v) 29 | } 30 | }) 31 | } 32 | } 33 | 34 | func BenchmarkParseInt(b *testing.B) { 35 | for _, test := range parseIntTests { 36 | b.Run(test.s, func(b *testing.B) { 37 | s := []byte(test.s) 38 | 39 | for i := 0; i != b.N; i++ { 40 | ParseInt(s) 41 | } 42 | }) 43 | } 44 | } 45 | 46 | var parseUintHexTests = []struct { 47 | v uint64 48 | s string 49 | }{ 50 | {0x0, "0"}, 51 | {0x1, "1"}, 52 | {0xA, "a"}, 53 | {0xA, "A"}, 54 | {0x10, "10"}, 55 | {0xABCDEF, "abcdef"}, 56 | {0xABCDEF, "ABCDEF"}, 57 | {0xFFFFFFFFFFFFFFFF, "FFFFFFFFFFFFFFFF"}, 58 | } 59 | 60 | func TestParseUintHex(t *testing.T) { 61 | for _, test := range parseUintHexTests { 62 | t.Run(test.s, func(t *testing.T) { 63 | v, err := ParseUintHex([]byte(test.s)) 64 | 65 | if err != nil { 66 | t.Error(err) 67 | } 68 | 69 | if v != test.v { 70 | t.Error(v) 71 | } 72 | }) 73 | } 74 | } 75 | 76 | func BenchmarkParseUintHex(b *testing.B) { 77 | for _, test := range parseUintHexTests { 78 | b.Run(test.s, func(b *testing.B) { 79 | s := []byte(test.s) 80 | 81 | for i := 0; i != b.N; i++ { 82 | ParseUintHex(s) 83 | } 84 | }) 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /json/json_test.go: -------------------------------------------------------------------------------- 1 | package json 2 | 3 | import ( 4 | "fmt" 5 | "math" 6 | "strings" 7 | "testing" 8 | 9 | "github.com/segmentio/objconv/objtests" 10 | ) 11 | 12 | func TestCodec(t *testing.T) { 13 | objtests.TestCodec(t, Codec) 14 | } 15 | 16 | func BenchmarkCodec(b *testing.B) { 17 | objtests.BenchmarkCodec(b, Codec) 18 | } 19 | 20 | func TestPrettyCodec(t *testing.T) { 21 | objtests.TestCodec(t, PrettyCodec) 22 | } 23 | 24 | func BenchmarkPrettyCodec(b *testing.B) { 25 | objtests.BenchmarkCodec(b, PrettyCodec) 26 | } 27 | 28 | func TestUnicode(t *testing.T) { 29 | tests := []struct { 30 | in string 31 | out string 32 | }{ 33 | {`"\u2022"`, "•"}, 34 | {`"\uDC00D800"`, "�"}, 35 | } 36 | 37 | for _, test := range tests { 38 | t.Run(test.out, func(t *testing.T) { 39 | var s string 40 | 41 | if err := Unmarshal([]byte(test.in), &s); err != nil { 42 | t.Error(err) 43 | } 44 | 45 | if s != test.out { 46 | t.Error(s) 47 | } 48 | }) 49 | } 50 | } 51 | 52 | func TestMapValueOverflow(t *testing.T) { 53 | src := fmt.Sprintf( 54 | `{"A":"good","skip1":"%s","B":"bad","skip2":"%sA"}`, 55 | strings.Repeat("0", 102), 56 | strings.Repeat("0", 110), 57 | ) 58 | 59 | val := struct{ A string }{} 60 | 61 | if err := Unmarshal([]byte(src), &val); err != nil { 62 | t.Error(err) 63 | return 64 | } 65 | 66 | if val.A != "good" { 67 | t.Error(val.A) 68 | } 69 | } 70 | 71 | func TestEmitImpossibleFloats(t *testing.T) { 72 | values := []float64{ 73 | math.NaN(), 74 | math.Inf(+1), 75 | math.Inf(-1), 76 | } 77 | 78 | for _, v := range values { 79 | t.Run(fmt.Sprintf("emitting %v must return an error", v), func(t *testing.T) { 80 | e := Emitter{} 81 | 82 | if err := e.EmitFloat(v, 64); err == nil { 83 | t.Error("no error was returned") 84 | } 85 | }) 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /objutil/tag_test.go: -------------------------------------------------------------------------------- 1 | package objutil 2 | 3 | import "testing" 4 | 5 | func TestParseTag(t *testing.T) { 6 | tests := []struct { 7 | tag string 8 | res Tag 9 | }{ 10 | { 11 | tag: "", 12 | res: Tag{}, 13 | }, 14 | { 15 | tag: "hello", 16 | res: Tag{Name: "hello"}, 17 | }, 18 | { 19 | tag: ",omitempty", 20 | res: Tag{Omitempty: true}, 21 | }, 22 | { 23 | tag: "-", 24 | res: Tag{Name: "-"}, 25 | }, 26 | { 27 | tag: "hello,omitempty", 28 | res: Tag{Name: "hello", Omitempty: true}, 29 | }, 30 | { 31 | tag: "-,omitempty", 32 | res: Tag{Name: "-", Omitempty: true}, 33 | }, 34 | { 35 | tag: "hello,omitzero", 36 | res: Tag{Name: "hello", Omitzero: true}, 37 | }, 38 | { 39 | tag: "-,omitempty,omitzero", 40 | res: Tag{Name: "-", Omitempty: true, Omitzero: true}, 41 | }, 42 | } 43 | 44 | for _, test := range tests { 45 | t.Run(test.tag, func(t *testing.T) { 46 | if res := ParseTag(test.tag); res != test.res { 47 | t.Errorf("%s: %#v != %#v", test.tag, test.res, res) 48 | } 49 | }) 50 | } 51 | } 52 | 53 | func TestParseTagJSON(t *testing.T) { 54 | tests := []struct { 55 | tag string 56 | res Tag 57 | }{ 58 | { 59 | tag: "", 60 | res: Tag{}, 61 | }, 62 | { 63 | tag: "hello", 64 | res: Tag{Name: "hello"}, 65 | }, 66 | { 67 | tag: ",omitempty", 68 | res: Tag{Omitempty: true}, 69 | }, 70 | { 71 | tag: "-", 72 | res: Tag{Name: "-"}, 73 | }, 74 | { 75 | tag: "hello,omitempty", 76 | res: Tag{Name: "hello", Omitempty: true}, 77 | }, 78 | { 79 | tag: "-,omitempty", 80 | res: Tag{Name: "-", Omitempty: true}, 81 | }, 82 | } 83 | 84 | for _, test := range tests { 85 | t.Run(test.tag, func(t *testing.T) { 86 | if res := ParseTag(test.tag); res != test.res { 87 | t.Errorf("%s: %#v != %#v", test.tag, test.res, res) 88 | } 89 | }) 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /objutil/zero_test.go: -------------------------------------------------------------------------------- 1 | package objutil 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | "unsafe" 7 | ) 8 | 9 | func TestIsZeroTrue(t *testing.T) { 10 | tests := []interface{}{ 11 | nil, 12 | 13 | false, 14 | 15 | int(0), 16 | int8(0), 17 | int16(0), 18 | int32(0), 19 | int64(0), 20 | 21 | uint(0), 22 | uint8(0), 23 | uint16(0), 24 | uint32(0), 25 | uint64(0), 26 | uintptr(0), 27 | 28 | float32(0), 29 | float64(0), 30 | 31 | "", 32 | []byte(nil), 33 | []int(nil), 34 | [...]int{}, 35 | [...]int{0, 0, 0}, 36 | 37 | (map[string]int)(nil), 38 | 39 | (*int)(nil), 40 | unsafe.Pointer(nil), 41 | 42 | struct{}{}, 43 | struct{ A int }{}, 44 | 45 | (chan struct{})(nil), 46 | (func())(nil), 47 | } 48 | 49 | for _, test := range tests { 50 | t.Run(fmt.Sprintf("%T", test), func(t *testing.T) { 51 | if !IsZero(test) { 52 | t.Errorf("%T, %#v should be an empty value", test, test) 53 | } 54 | }) 55 | } 56 | } 57 | 58 | func TestIsZeroFalse(t *testing.T) { 59 | answer := 42 60 | 61 | tests := []interface{}{ 62 | true, 63 | 64 | int(1), 65 | int8(1), 66 | int16(1), 67 | int32(1), 68 | int64(1), 69 | 70 | uint(1), 71 | uint8(1), 72 | uint16(1), 73 | uint32(1), 74 | uint64(1), 75 | uintptr(1), 76 | 77 | float32(1), 78 | float64(1), 79 | 80 | "Hello World!", 81 | []byte{}, 82 | []int{}, 83 | []int{1, 2, 3}, 84 | [...]int{1, 2, 3}, 85 | 86 | map[string]int{}, 87 | map[string]int{"answer": 42}, 88 | 89 | &answer, 90 | unsafe.Pointer(&answer), 91 | 92 | struct{ A int }{42}, 93 | 94 | make(chan struct{}), 95 | func() {}, 96 | } 97 | 98 | for _, test := range tests { 99 | t.Run(fmt.Sprintf("%T", test), func(t *testing.T) { 100 | if IsZero(test) { 101 | t.Errorf("%T, %#v should not be an empty value", test, test) 102 | } 103 | }) 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /sort.go: -------------------------------------------------------------------------------- 1 | package objconv 2 | 3 | import ( 4 | "bytes" 5 | "reflect" 6 | "sort" 7 | ) 8 | 9 | type sortIntValues []reflect.Value 10 | 11 | func (s sortIntValues) Len() int { return len(s) } 12 | func (s sortIntValues) Swap(i int, j int) { s[i], s[j] = s[j], s[i] } 13 | func (s sortIntValues) Less(i int, j int) bool { return s[i].Int() < s[j].Int() } 14 | 15 | type sortUintValues []reflect.Value 16 | 17 | func (s sortUintValues) Len() int { return len(s) } 18 | func (s sortUintValues) Swap(i int, j int) { s[i], s[j] = s[j], s[i] } 19 | func (s sortUintValues) Less(i int, j int) bool { return s[i].Uint() < s[j].Uint() } 20 | 21 | type sortFloatValues []reflect.Value 22 | 23 | func (s sortFloatValues) Len() int { return len(s) } 24 | func (s sortFloatValues) Swap(i int, j int) { s[i], s[j] = s[j], s[i] } 25 | func (s sortFloatValues) Less(i int, j int) bool { return s[i].Float() < s[j].Float() } 26 | 27 | type sortStringValues []reflect.Value 28 | 29 | func (s sortStringValues) Len() int { return len(s) } 30 | func (s sortStringValues) Swap(i int, j int) { s[i], s[j] = s[j], s[i] } 31 | func (s sortStringValues) Less(i int, j int) bool { return s[i].String() < s[j].String() } 32 | 33 | type sortBytesValues []reflect.Value 34 | 35 | func (s sortBytesValues) Len() int { return len(s) } 36 | func (s sortBytesValues) Swap(i int, j int) { s[i], s[j] = s[j], s[i] } 37 | func (s sortBytesValues) Less(i int, j int) bool { 38 | return bytes.Compare(s[i].Bytes(), s[j].Bytes()) < 0 39 | } 40 | 41 | func sortValues(typ reflect.Type, v []reflect.Value) { 42 | switch typ.Kind() { 43 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 44 | sort.Sort(sortIntValues(v)) 45 | 46 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: 47 | sort.Sort(sortUintValues(v)) 48 | 49 | case reflect.Float32, reflect.Float64: 50 | sort.Sort(sortFloatValues(v)) 51 | 52 | case reflect.String: 53 | sort.Sort(sortStringValues(v)) 54 | 55 | case reflect.Slice: 56 | if typ.Elem().Kind() == reflect.Uint8 { 57 | sort.Sort(sortBytesValues(v)) 58 | } 59 | } 60 | 61 | // For all other types we give up on trying to sort the values, 62 | // anyway it's likely not gonna be a serializable type, or something 63 | // that doesn't make sense. 64 | } 65 | -------------------------------------------------------------------------------- /cbor/cbor.go: -------------------------------------------------------------------------------- 1 | package cbor 2 | 3 | import ( 4 | "encoding/binary" 5 | 6 | "github.com/segmentio/objconv/objutil" 7 | ) 8 | 9 | const ( // major types 10 | majorType0 byte = iota 11 | majorType1 12 | majorType2 13 | majorType3 14 | majorType4 15 | majorType5 16 | majorType6 17 | majorType7 18 | ) 19 | 20 | const ( // integer sizes 21 | iUint8 = 24 + iota 22 | iUint16 23 | iUint32 24 | iUint64 25 | ) 26 | 27 | const ( // simple values 28 | svFalse = 20 + iota 29 | svTrue 30 | svNull 31 | svUndefined 32 | svExtension 33 | svFloat16 34 | svFloat32 35 | svFloat64 36 | svBreak = 31 37 | ) 38 | 39 | const ( // tags 40 | tagDateTime = 0 41 | tagTimestamp = 1 42 | ) 43 | 44 | const ( 45 | intMax = uint64(objutil.IntMax) 46 | int64Max = uint64(objutil.Int64Max) 47 | noTag = uint64(objutil.Uint64Max) 48 | ) 49 | 50 | func majorByte(maj byte, val byte) byte { 51 | return (maj << 5) | val 52 | } 53 | 54 | func majorType(b byte) (maj byte, val byte) { 55 | const mask = byte(0xE0) 56 | return ((b & mask) >> 5), (b & ^mask) 57 | } 58 | 59 | func putUint16(b []byte, v uint16) { 60 | binary.BigEndian.PutUint16(b, v) 61 | } 62 | 63 | func putUint32(b []byte, v uint32) { 64 | binary.BigEndian.PutUint32(b, v) 65 | } 66 | 67 | func putUint64(b []byte, v uint64) { 68 | binary.BigEndian.PutUint64(b, v) 69 | } 70 | 71 | func getUint16(b []byte) uint16 { 72 | return binary.BigEndian.Uint16(b) 73 | } 74 | 75 | func getUint32(b []byte) uint32 { 76 | return binary.BigEndian.Uint32(b) 77 | } 78 | 79 | func getUint64(b []byte) uint64 { 80 | return binary.BigEndian.Uint64(b) 81 | } 82 | 83 | func align(n int, a int) int { 84 | if (n % a) == 0 { 85 | return n 86 | } 87 | return ((n / a) + 1) * a 88 | } 89 | 90 | func f16tof32bits(yy uint16) (d uint32) { 91 | y := uint32(yy) 92 | s := (y >> 15) & 0x01 93 | e := (y >> 10) & 0x1f 94 | m := y & 0x03ff 95 | 96 | if e == 0 { 97 | if m == 0 { // +/- 0 98 | return s << 31 99 | } else { // Denormalized number -- renormalize it 100 | for (m & 0x00000400) == 0 { 101 | m <<= 1 102 | e -= 1 103 | } 104 | e += 1 105 | const zz uint32 = 0x0400 106 | m &= ^zz 107 | } 108 | } else if e == 31 { 109 | if m == 0 { // Inf 110 | return (s << 31) | 0x7f800000 111 | } else { // NaN 112 | return (s << 31) | 0x7f800000 | (m << 13) 113 | } 114 | } 115 | 116 | e = e + (127 - 15) 117 | m = m << 13 118 | return (s << 31) | (e << 23) | m 119 | } 120 | -------------------------------------------------------------------------------- /yaml/vendor/gopkg.in/check.v1/bootstrap_test.go: -------------------------------------------------------------------------------- 1 | // These initial tests are for bootstrapping. They verify that we can 2 | // basically use the testing infrastructure itself to check if the test 3 | // system is working. 4 | // 5 | // These tests use will break down the test runner badly in case of 6 | // errors because if they simply fail, we can't be sure the developer 7 | // will ever see anything (because failing means the failing system 8 | // somehow isn't working! :-) 9 | // 10 | // Do not assume *any* internal functionality works as expected besides 11 | // what's actually tested here. 12 | 13 | package check_test 14 | 15 | import ( 16 | "fmt" 17 | "gopkg.in/check.v1" 18 | "strings" 19 | ) 20 | 21 | type BootstrapS struct{} 22 | 23 | var boostrapS = check.Suite(&BootstrapS{}) 24 | 25 | func (s *BootstrapS) TestCountSuite(c *check.C) { 26 | suitesRun += 1 27 | } 28 | 29 | func (s *BootstrapS) TestFailedAndFail(c *check.C) { 30 | if c.Failed() { 31 | critical("c.Failed() must be false first!") 32 | } 33 | c.Fail() 34 | if !c.Failed() { 35 | critical("c.Fail() didn't put the test in a failed state!") 36 | } 37 | c.Succeed() 38 | } 39 | 40 | func (s *BootstrapS) TestFailedAndSucceed(c *check.C) { 41 | c.Fail() 42 | c.Succeed() 43 | if c.Failed() { 44 | critical("c.Succeed() didn't put the test back in a non-failed state") 45 | } 46 | } 47 | 48 | func (s *BootstrapS) TestLogAndGetTestLog(c *check.C) { 49 | c.Log("Hello there!") 50 | log := c.GetTestLog() 51 | if log != "Hello there!\n" { 52 | critical(fmt.Sprintf("Log() or GetTestLog() is not working! Got: %#v", log)) 53 | } 54 | } 55 | 56 | func (s *BootstrapS) TestLogfAndGetTestLog(c *check.C) { 57 | c.Logf("Hello %v", "there!") 58 | log := c.GetTestLog() 59 | if log != "Hello there!\n" { 60 | critical(fmt.Sprintf("Logf() or GetTestLog() is not working! Got: %#v", log)) 61 | } 62 | } 63 | 64 | func (s *BootstrapS) TestRunShowsErrors(c *check.C) { 65 | output := String{} 66 | check.Run(&FailHelper{}, &check.RunConf{Output: &output}) 67 | if strings.Index(output.value, "Expected failure!") == -1 { 68 | critical(fmt.Sprintf("RunWithWriter() output did not contain the "+ 69 | "expected failure! Got: %#v", 70 | output.value)) 71 | } 72 | } 73 | 74 | func (s *BootstrapS) TestRunDoesntShowSuccesses(c *check.C) { 75 | output := String{} 76 | check.Run(&SuccessHelper{}, &check.RunConf{Output: &output}) 77 | if strings.Index(output.value, "Expected success!") != -1 { 78 | critical(fmt.Sprintf("RunWithWriter() output contained a successful "+ 79 | "test! Got: %#v", 80 | output.value)) 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /yaml/vendor/gopkg.in/check.v1/reporter.go: -------------------------------------------------------------------------------- 1 | package check 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | "sync" 7 | ) 8 | 9 | // ----------------------------------------------------------------------- 10 | // Output writer manages atomic output writing according to settings. 11 | 12 | type outputWriter struct { 13 | m sync.Mutex 14 | writer io.Writer 15 | wroteCallProblemLast bool 16 | Stream bool 17 | Verbose bool 18 | } 19 | 20 | func newOutputWriter(writer io.Writer, stream, verbose bool) *outputWriter { 21 | return &outputWriter{writer: writer, Stream: stream, Verbose: verbose} 22 | } 23 | 24 | func (ow *outputWriter) Write(content []byte) (n int, err error) { 25 | ow.m.Lock() 26 | n, err = ow.writer.Write(content) 27 | ow.m.Unlock() 28 | return 29 | } 30 | 31 | func (ow *outputWriter) WriteCallStarted(label string, c *C) { 32 | if ow.Stream { 33 | header := renderCallHeader(label, c, "", "\n") 34 | ow.m.Lock() 35 | ow.writer.Write([]byte(header)) 36 | ow.m.Unlock() 37 | } 38 | } 39 | 40 | func (ow *outputWriter) WriteCallProblem(label string, c *C) { 41 | var prefix string 42 | if !ow.Stream { 43 | prefix = "\n-----------------------------------" + 44 | "-----------------------------------\n" 45 | } 46 | header := renderCallHeader(label, c, prefix, "\n\n") 47 | ow.m.Lock() 48 | ow.wroteCallProblemLast = true 49 | ow.writer.Write([]byte(header)) 50 | if !ow.Stream { 51 | c.logb.WriteTo(ow.writer) 52 | } 53 | ow.m.Unlock() 54 | } 55 | 56 | func (ow *outputWriter) WriteCallSuccess(label string, c *C) { 57 | if ow.Stream || (ow.Verbose && c.kind == testKd) { 58 | // TODO Use a buffer here. 59 | var suffix string 60 | if c.reason != "" { 61 | suffix = " (" + c.reason + ")" 62 | } 63 | if c.status() == succeededSt { 64 | suffix += "\t" + c.timerString() 65 | } 66 | suffix += "\n" 67 | if ow.Stream { 68 | suffix += "\n" 69 | } 70 | header := renderCallHeader(label, c, "", suffix) 71 | ow.m.Lock() 72 | // Resist temptation of using line as prefix above due to race. 73 | if !ow.Stream && ow.wroteCallProblemLast { 74 | header = "\n-----------------------------------" + 75 | "-----------------------------------\n" + 76 | header 77 | } 78 | ow.wroteCallProblemLast = false 79 | ow.writer.Write([]byte(header)) 80 | ow.m.Unlock() 81 | } 82 | } 83 | 84 | func renderCallHeader(label string, c *C, prefix, suffix string) string { 85 | pc := c.method.PC() 86 | return fmt.Sprintf("%s%s: %s: %s%s", prefix, label, niceFuncPath(pc), 87 | niceFuncName(pc), suffix) 88 | } 89 | -------------------------------------------------------------------------------- /resp/decode_test.go: -------------------------------------------------------------------------------- 1 | package resp 2 | 3 | import ( 4 | "reflect" 5 | "strings" 6 | "testing" 7 | 8 | "github.com/segmentio/objconv" 9 | ) 10 | 11 | var respDecodeTests = []struct { 12 | v interface{} 13 | s string 14 | }{ 15 | {nil, "$-1\r\n"}, 16 | {nil, "*-1\r\n"}, 17 | 18 | {0, ":0\r\n"}, 19 | {-1, ":-1\r\n"}, 20 | {42, ":42\r\n"}, 21 | 22 | {"", "+\r\n"}, 23 | {"Hello World!", "+Hello World!\r\n"}, 24 | {"Hello\nWorld!", "+Hello\nWorld!\r\n"}, 25 | {"Hello\r\nWorld!", "$13\r\nHello\r\nWorld!\r\n"}, 26 | 27 | {[]byte{}, "$0\r\n\r\n"}, 28 | {[]byte("Hello World!"), "$12\r\nHello World!\r\n"}, 29 | 30 | {NewError(""), "-\r\n"}, 31 | {NewError("oops"), "-oops\r\n"}, 32 | {NewError("ERR A"), "-ERR A\r\n"}, 33 | 34 | {[]int{}, "*0\r\n"}, 35 | {[]int{1, 2, 3}, "*3\r\n:1\r\n:2\r\n:3\r\n"}, 36 | } 37 | 38 | func TestUnmarshal(t *testing.T) { 39 | for _, test := range respDecodeTests { 40 | t.Run(testName(test.s), func(t *testing.T) { 41 | var typ reflect.Type 42 | 43 | if test.v == nil { 44 | typ = reflect.TypeOf((*interface{})(nil)).Elem() 45 | } else { 46 | typ = reflect.TypeOf(test.v) 47 | } 48 | 49 | val := reflect.New(typ) 50 | err := Unmarshal([]byte(test.s), val.Interface()) 51 | 52 | if err != nil { 53 | t.Error(err) 54 | } 55 | 56 | v1 := test.v 57 | v2 := val.Elem().Interface() 58 | 59 | if !reflect.DeepEqual(v1, v2) { 60 | t.Error(v2) 61 | } 62 | }) 63 | } 64 | } 65 | 66 | func BenchmarkUnmarshal(b *testing.B) { 67 | for _, test := range respDecodeTests { 68 | var t reflect.Type 69 | 70 | if test.v == nil { 71 | t = reflect.TypeOf((*interface{})(nil)).Elem() 72 | } else { 73 | t = reflect.TypeOf(test.v) 74 | } 75 | 76 | v := reflect.New(t).Interface() 77 | s := []byte(test.s) 78 | 79 | b.Run(testName(test.s), func(b *testing.B) { 80 | for i := 0; i != b.N; i++ { 81 | if err := Unmarshal(s, v); err != nil { 82 | b.Fatal(err) 83 | } 84 | } 85 | b.SetBytes(int64(len(test.s))) 86 | }) 87 | } 88 | } 89 | 90 | func BenchmarkDecoder(b *testing.B) { 91 | r := strings.NewReader("") 92 | p := NewParser(nil) 93 | d := objconv.NewDecoder(p) 94 | 95 | for _, test := range respDecodeTests { 96 | var t reflect.Type 97 | 98 | if test.v == nil { 99 | t = reflect.TypeOf((*interface{})(nil)).Elem() 100 | } else { 101 | t = reflect.TypeOf(test.v) 102 | } 103 | 104 | v := reflect.New(t).Interface() 105 | 106 | b.Run(testName(test.s), func(b *testing.B) { 107 | for i := 0; i != b.N; i++ { 108 | r.Reset(test.s) 109 | p.Reset(r) 110 | 111 | if err := d.Decode(v); err != nil { 112 | b.Fatal(err) 113 | } 114 | } 115 | b.SetBytes(int64(len(test.s))) 116 | }) 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /yaml/vendor/gopkg.in/yaml.v2/writerc.go: -------------------------------------------------------------------------------- 1 | package yaml 2 | 3 | // Set the writer error and return false. 4 | func yaml_emitter_set_writer_error(emitter *yaml_emitter_t, problem string) bool { 5 | emitter.error = yaml_WRITER_ERROR 6 | emitter.problem = problem 7 | return false 8 | } 9 | 10 | // Flush the output buffer. 11 | func yaml_emitter_flush(emitter *yaml_emitter_t) bool { 12 | if emitter.write_handler == nil { 13 | panic("write handler not set") 14 | } 15 | 16 | // Check if the buffer is empty. 17 | if emitter.buffer_pos == 0 { 18 | return true 19 | } 20 | 21 | // If the output encoding is UTF-8, we don't need to recode the buffer. 22 | if emitter.encoding == yaml_UTF8_ENCODING { 23 | if err := emitter.write_handler(emitter, emitter.buffer[:emitter.buffer_pos]); err != nil { 24 | return yaml_emitter_set_writer_error(emitter, "write error: "+err.Error()) 25 | } 26 | emitter.buffer_pos = 0 27 | return true 28 | } 29 | 30 | // Recode the buffer into the raw buffer. 31 | var low, high int 32 | if emitter.encoding == yaml_UTF16LE_ENCODING { 33 | low, high = 0, 1 34 | } else { 35 | high, low = 1, 0 36 | } 37 | 38 | pos := 0 39 | for pos < emitter.buffer_pos { 40 | // See the "reader.c" code for more details on UTF-8 encoding. Note 41 | // that we assume that the buffer contains a valid UTF-8 sequence. 42 | 43 | // Read the next UTF-8 character. 44 | octet := emitter.buffer[pos] 45 | 46 | var w int 47 | var value rune 48 | switch { 49 | case octet&0x80 == 0x00: 50 | w, value = 1, rune(octet&0x7F) 51 | case octet&0xE0 == 0xC0: 52 | w, value = 2, rune(octet&0x1F) 53 | case octet&0xF0 == 0xE0: 54 | w, value = 3, rune(octet&0x0F) 55 | case octet&0xF8 == 0xF0: 56 | w, value = 4, rune(octet&0x07) 57 | } 58 | for k := 1; k < w; k++ { 59 | octet = emitter.buffer[pos+k] 60 | value = (value << 6) + (rune(octet) & 0x3F) 61 | } 62 | pos += w 63 | 64 | // Write the character. 65 | if value < 0x10000 { 66 | var b [2]byte 67 | b[high] = byte(value >> 8) 68 | b[low] = byte(value & 0xFF) 69 | emitter.raw_buffer = append(emitter.raw_buffer, b[0], b[1]) 70 | } else { 71 | // Write the character using a surrogate pair (check "reader.c"). 72 | var b [4]byte 73 | value -= 0x10000 74 | b[high] = byte(0xD8 + (value >> 18)) 75 | b[low] = byte((value >> 10) & 0xFF) 76 | b[high+2] = byte(0xDC + ((value >> 8) & 0xFF)) 77 | b[low+2] = byte(value & 0xFF) 78 | emitter.raw_buffer = append(emitter.raw_buffer, b[0], b[1], b[2], b[3]) 79 | } 80 | } 81 | 82 | // Write the raw buffer. 83 | if err := emitter.write_handler(emitter, emitter.raw_buffer); err != nil { 84 | return yaml_emitter_set_writer_error(emitter, "write error: "+err.Error()) 85 | } 86 | emitter.buffer_pos = 0 87 | emitter.raw_buffer = emitter.raw_buffer[:0] 88 | return true 89 | } 90 | -------------------------------------------------------------------------------- /yaml/vendor/gopkg.in/check.v1/printer_test.go: -------------------------------------------------------------------------------- 1 | package check_test 2 | 3 | import ( 4 | . "gopkg.in/check.v1" 5 | ) 6 | 7 | var _ = Suite(&PrinterS{}) 8 | 9 | type PrinterS struct{} 10 | 11 | func (s *PrinterS) TestCountSuite(c *C) { 12 | suitesRun += 1 13 | } 14 | 15 | var printTestFuncLine int 16 | 17 | func init() { 18 | printTestFuncLine = getMyLine() + 3 19 | } 20 | 21 | func printTestFunc() { 22 | println(1) // Comment1 23 | if 2 == 2 { // Comment2 24 | println(3) // Comment3 25 | } 26 | switch 5 { 27 | case 6: println(6) // Comment6 28 | println(7) 29 | } 30 | switch interface{}(9).(type) {// Comment9 31 | case int: println(10) 32 | println(11) 33 | } 34 | select { 35 | case <-(chan bool)(nil): println(14) 36 | println(15) 37 | default: println(16) 38 | println(17) 39 | } 40 | println(19, 41 | 20) 42 | _ = func() { println(21) 43 | println(22) 44 | } 45 | println(24, func() { 46 | println(25) 47 | }) 48 | // Leading comment 49 | // with multiple lines. 50 | println(29) // Comment29 51 | } 52 | 53 | var printLineTests = []struct { 54 | line int 55 | output string 56 | }{ 57 | {1, "println(1) // Comment1"}, 58 | {2, "if 2 == 2 { // Comment2\n ...\n}"}, 59 | {3, "println(3) // Comment3"}, 60 | {5, "switch 5 {\n...\n}"}, 61 | {6, "case 6:\n println(6) // Comment6\n ..."}, 62 | {7, "println(7)"}, 63 | {9, "switch interface{}(9).(type) { // Comment9\n...\n}"}, 64 | {10, "case int:\n println(10)\n ..."}, 65 | {14, "case <-(chan bool)(nil):\n println(14)\n ..."}, 66 | {15, "println(15)"}, 67 | {16, "default:\n println(16)\n ..."}, 68 | {17, "println(17)"}, 69 | {19, "println(19,\n 20)"}, 70 | {20, "println(19,\n 20)"}, 71 | {21, "_ = func() {\n println(21)\n println(22)\n}"}, 72 | {22, "println(22)"}, 73 | {24, "println(24, func() {\n println(25)\n})"}, 74 | {25, "println(25)"}, 75 | {26, "println(24, func() {\n println(25)\n})"}, 76 | {29, "// Leading comment\n// with multiple lines.\nprintln(29) // Comment29"}, 77 | } 78 | 79 | func (s *PrinterS) TestPrintLine(c *C) { 80 | for _, test := range printLineTests { 81 | output, err := PrintLine("printer_test.go", printTestFuncLine+test.line) 82 | c.Assert(err, IsNil) 83 | c.Assert(output, Equals, test.output) 84 | } 85 | } 86 | 87 | var indentTests = []struct { 88 | in, out string 89 | }{ 90 | {"", ""}, 91 | {"\n", "\n"}, 92 | {"a", ">>>a"}, 93 | {"a\n", ">>>a\n"}, 94 | {"a\nb", ">>>a\n>>>b"}, 95 | {" ", ">>> "}, 96 | } 97 | 98 | func (s *PrinterS) TestIndent(c *C) { 99 | for _, test := range indentTests { 100 | out := Indent(test.in, ">>>") 101 | c.Assert(out, Equals, test.out) 102 | } 103 | 104 | } 105 | -------------------------------------------------------------------------------- /adapters/net/decode.go: -------------------------------------------------------------------------------- 1 | package net 2 | 3 | import ( 4 | "errors" 5 | "net" 6 | "reflect" 7 | "strconv" 8 | "strings" 9 | 10 | "github.com/segmentio/objconv" 11 | ) 12 | 13 | func decodeTCPAddr(d objconv.Decoder, to reflect.Value) (err error) { 14 | var a net.TCPAddr 15 | var s string 16 | 17 | if err = d.Decode(&s); err != nil { 18 | return 19 | } 20 | 21 | if a.IP, a.Port, a.Zone, err = parseNetAddr(s); err != nil { 22 | return 23 | } 24 | 25 | if to.IsValid() { 26 | to.Set(reflect.ValueOf(a)) 27 | } 28 | return 29 | } 30 | 31 | func decodeUDPAddr(d objconv.Decoder, to reflect.Value) (err error) { 32 | var a net.UDPAddr 33 | var s string 34 | 35 | if err = d.Decode(&s); err != nil { 36 | return 37 | } 38 | 39 | if a.IP, a.Port, a.Zone, err = parseNetAddr(s); err != nil { 40 | return 41 | } 42 | 43 | if to.IsValid() { 44 | to.Set(reflect.ValueOf(a)) 45 | } 46 | return 47 | } 48 | 49 | func decodeUnixAddr(d objconv.Decoder, to reflect.Value) (err error) { 50 | var a net.UnixAddr 51 | var s string 52 | 53 | if err = d.Decode(&s); err != nil { 54 | return 55 | } 56 | 57 | if i := strings.Index(s, "://"); i >= 0 { 58 | a.Net, a.Name = s[:i], s[i+3:] 59 | } else { 60 | a.Net, a.Name = "unix", s 61 | } 62 | 63 | if to.IsValid() { 64 | to.Set(reflect.ValueOf(a)) 65 | } 66 | return 67 | } 68 | 69 | func decodeIPAddr(d objconv.Decoder, to reflect.Value) (err error) { 70 | var a net.IPAddr 71 | var s string 72 | 73 | if err = d.Decode(&s); err != nil { 74 | return 75 | } 76 | 77 | if i := strings.IndexByte(s, '%'); i >= 0 { 78 | s, a.Zone = s[:i], s[i+1:] 79 | } 80 | 81 | if a.IP = net.ParseIP(s); a.IP == nil { 82 | err = errors.New("objconv: bad IP address: " + s) 83 | return 84 | } 85 | 86 | if to.IsValid() { 87 | to.Set(reflect.ValueOf(a)) 88 | } 89 | return 90 | } 91 | 92 | func decodeIP(d objconv.Decoder, to reflect.Value) (err error) { 93 | var ip net.IP 94 | var s string 95 | 96 | if err = d.Decode(&s); err != nil { 97 | return 98 | } 99 | 100 | if ip = net.ParseIP(s); ip == nil { 101 | err = errors.New("objconv: bad IP address: " + s) 102 | return 103 | } 104 | 105 | if to.IsValid() { 106 | to.Set(reflect.ValueOf(ip)) 107 | } 108 | return 109 | } 110 | 111 | func parseNetAddr(s string) (ip net.IP, port int, zone string, err error) { 112 | var h string 113 | var p string 114 | 115 | if h, p, err = net.SplitHostPort(s); err != nil { 116 | h, p = s, "" 117 | } 118 | 119 | if len(h) != 0 { 120 | if off := strings.IndexByte(h, '%'); off >= 0 { 121 | h, zone = h[:off], h[off+1:] 122 | } 123 | if ip = net.ParseIP(h); ip == nil { 124 | err = errors.New("objconv: bad IP address: " + s) 125 | return 126 | } 127 | } 128 | 129 | if len(p) != 0 { 130 | if port, err = strconv.Atoi(p); err != nil || port < 0 || port > 65535 { 131 | err = errors.New("objconv: bad port number: " + s) 132 | return 133 | } 134 | } 135 | 136 | return 137 | } 138 | -------------------------------------------------------------------------------- /yaml/vendor/gopkg.in/yaml.v2/sorter.go: -------------------------------------------------------------------------------- 1 | package yaml 2 | 3 | import ( 4 | "reflect" 5 | "unicode" 6 | ) 7 | 8 | type keyList []reflect.Value 9 | 10 | func (l keyList) Len() int { return len(l) } 11 | func (l keyList) Swap(i, j int) { l[i], l[j] = l[j], l[i] } 12 | func (l keyList) Less(i, j int) bool { 13 | a := l[i] 14 | b := l[j] 15 | ak := a.Kind() 16 | bk := b.Kind() 17 | for (ak == reflect.Interface || ak == reflect.Ptr) && !a.IsNil() { 18 | a = a.Elem() 19 | ak = a.Kind() 20 | } 21 | for (bk == reflect.Interface || bk == reflect.Ptr) && !b.IsNil() { 22 | b = b.Elem() 23 | bk = b.Kind() 24 | } 25 | af, aok := keyFloat(a) 26 | bf, bok := keyFloat(b) 27 | if aok && bok { 28 | if af != bf { 29 | return af < bf 30 | } 31 | if ak != bk { 32 | return ak < bk 33 | } 34 | return numLess(a, b) 35 | } 36 | if ak != reflect.String || bk != reflect.String { 37 | return ak < bk 38 | } 39 | ar, br := []rune(a.String()), []rune(b.String()) 40 | for i := 0; i < len(ar) && i < len(br); i++ { 41 | if ar[i] == br[i] { 42 | continue 43 | } 44 | al := unicode.IsLetter(ar[i]) 45 | bl := unicode.IsLetter(br[i]) 46 | if al && bl { 47 | return ar[i] < br[i] 48 | } 49 | if al || bl { 50 | return bl 51 | } 52 | var ai, bi int 53 | var an, bn int64 54 | for ai = i; ai < len(ar) && unicode.IsDigit(ar[ai]); ai++ { 55 | an = an*10 + int64(ar[ai]-'0') 56 | } 57 | for bi = i; bi < len(br) && unicode.IsDigit(br[bi]); bi++ { 58 | bn = bn*10 + int64(br[bi]-'0') 59 | } 60 | if an != bn { 61 | return an < bn 62 | } 63 | if ai != bi { 64 | return ai < bi 65 | } 66 | return ar[i] < br[i] 67 | } 68 | return len(ar) < len(br) 69 | } 70 | 71 | // keyFloat returns a float value for v if it is a number/bool 72 | // and whether it is a number/bool or not. 73 | func keyFloat(v reflect.Value) (f float64, ok bool) { 74 | switch v.Kind() { 75 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 76 | return float64(v.Int()), true 77 | case reflect.Float32, reflect.Float64: 78 | return v.Float(), true 79 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: 80 | return float64(v.Uint()), true 81 | case reflect.Bool: 82 | if v.Bool() { 83 | return 1, true 84 | } 85 | return 0, true 86 | } 87 | return 0, false 88 | } 89 | 90 | // numLess returns whether a < b. 91 | // a and b must necessarily have the same kind. 92 | func numLess(a, b reflect.Value) bool { 93 | switch a.Kind() { 94 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 95 | return a.Int() < b.Int() 96 | case reflect.Float32, reflect.Float64: 97 | return a.Float() < b.Float() 98 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: 99 | return a.Uint() < b.Uint() 100 | case reflect.Bool: 101 | return !a.Bool() && b.Bool() 102 | } 103 | panic("not a number") 104 | } 105 | -------------------------------------------------------------------------------- /yaml/vendor/gopkg.in/check.v1/benchmark_test.go: -------------------------------------------------------------------------------- 1 | // These tests verify the test running logic. 2 | 3 | package check_test 4 | 5 | import ( 6 | "time" 7 | . "gopkg.in/check.v1" 8 | ) 9 | 10 | var benchmarkS = Suite(&BenchmarkS{}) 11 | 12 | type BenchmarkS struct{} 13 | 14 | func (s *BenchmarkS) TestCountSuite(c *C) { 15 | suitesRun += 1 16 | } 17 | 18 | func (s *BenchmarkS) TestBasicTestTiming(c *C) { 19 | helper := FixtureHelper{sleepOn: "Test1", sleep: 1000000 * time.Nanosecond} 20 | output := String{} 21 | runConf := RunConf{Output: &output, Verbose: true} 22 | Run(&helper, &runConf) 23 | 24 | expected := "PASS: check_test\\.go:[0-9]+: FixtureHelper\\.Test1\t0\\.0[0-9]+s\n" + 25 | "PASS: check_test\\.go:[0-9]+: FixtureHelper\\.Test2\t0\\.0[0-9]+s\n" 26 | c.Assert(output.value, Matches, expected) 27 | } 28 | 29 | func (s *BenchmarkS) TestStreamTestTiming(c *C) { 30 | helper := FixtureHelper{sleepOn: "SetUpSuite", sleep: 1000000 * time.Nanosecond} 31 | output := String{} 32 | runConf := RunConf{Output: &output, Stream: true} 33 | Run(&helper, &runConf) 34 | 35 | expected := "(?s).*\nPASS: check_test\\.go:[0-9]+: FixtureHelper\\.SetUpSuite\t[0-9]+\\.[0-9]+s\n.*" 36 | c.Assert(output.value, Matches, expected) 37 | } 38 | 39 | func (s *BenchmarkS) TestBenchmark(c *C) { 40 | helper := FixtureHelper{sleep: 100000} 41 | output := String{} 42 | runConf := RunConf{ 43 | Output: &output, 44 | Benchmark: true, 45 | BenchmarkTime: 10000000, 46 | Filter: "Benchmark1", 47 | } 48 | Run(&helper, &runConf) 49 | c.Check(helper.calls[0], Equals, "SetUpSuite") 50 | c.Check(helper.calls[1], Equals, "SetUpTest") 51 | c.Check(helper.calls[2], Equals, "Benchmark1") 52 | c.Check(helper.calls[3], Equals, "TearDownTest") 53 | c.Check(helper.calls[4], Equals, "SetUpTest") 54 | c.Check(helper.calls[5], Equals, "Benchmark1") 55 | c.Check(helper.calls[6], Equals, "TearDownTest") 56 | // ... and more. 57 | 58 | expected := "PASS: check_test\\.go:[0-9]+: FixtureHelper\\.Benchmark1\t\\s+[0-9]+\t\\s+[0-9]+ ns/op\n" 59 | c.Assert(output.value, Matches, expected) 60 | } 61 | 62 | func (s *BenchmarkS) TestBenchmarkBytes(c *C) { 63 | helper := FixtureHelper{sleep: 100000} 64 | output := String{} 65 | runConf := RunConf{ 66 | Output: &output, 67 | Benchmark: true, 68 | BenchmarkTime: 10000000, 69 | Filter: "Benchmark2", 70 | } 71 | Run(&helper, &runConf) 72 | 73 | expected := "PASS: check_test\\.go:[0-9]+: FixtureHelper\\.Benchmark2\t\\s+[0-9]+\t\\s+[0-9]+ ns/op\t\\s+ *[1-9]\\.[0-9]{2} MB/s\n" 74 | c.Assert(output.value, Matches, expected) 75 | } 76 | 77 | func (s *BenchmarkS) TestBenchmarkMem(c *C) { 78 | helper := FixtureHelper{sleep: 100000} 79 | output := String{} 80 | runConf := RunConf{ 81 | Output: &output, 82 | Benchmark: true, 83 | BenchmarkMem: true, 84 | BenchmarkTime: 10000000, 85 | Filter: "Benchmark3", 86 | } 87 | Run(&helper, &runConf) 88 | 89 | expected := "PASS: check_test\\.go:[0-9]+: FixtureHelper\\.Benchmark3\t\\s+ [0-9]+\t\\s+ *[0-9]+ ns/op\t\\s+ [0-9]+ B/op\t\\s+ [1-9]+ allocs/op\n" 90 | c.Assert(output.value, Matches, expected) 91 | } 92 | -------------------------------------------------------------------------------- /objutil/duration.go: -------------------------------------------------------------------------------- 1 | package objutil 2 | 3 | // Copyright 2009 The Go Authors. All rights reserved. 4 | // Use of this source code is governed by a BSD-style 5 | // license that can be found in the LICENSE file. 6 | 7 | import "time" 8 | 9 | // AppendDuration appends a human-readable representation of d to b. 10 | // 11 | // The function copies the implementation of time.Duration.String but prevents 12 | // Go from making a dynamic memory allocation on the returned value. 13 | func AppendDuration(b []byte, d time.Duration) []byte { 14 | // Largest time is 2540400h10m10.000000000s 15 | var buf [32]byte 16 | w := len(buf) 17 | 18 | u := uint64(d) 19 | neg := d < 0 20 | if neg { 21 | u = -u 22 | } 23 | 24 | if u < uint64(time.Second) { 25 | // Special case: if duration is smaller than a second, 26 | // use smaller units, like 1.2ms 27 | var prec int 28 | w-- 29 | buf[w] = 's' 30 | w-- 31 | switch { 32 | case u == 0: 33 | return append(b, '0', 's') 34 | case u < uint64(time.Microsecond): 35 | // print nanoseconds 36 | prec = 0 37 | buf[w] = 'n' 38 | case u < uint64(time.Millisecond): 39 | // print microseconds 40 | prec = 3 41 | // U+00B5 'µ' micro sign == 0xC2 0xB5 42 | w-- // Need room for two bytes. 43 | copy(buf[w:], "µ") 44 | default: 45 | // print milliseconds 46 | prec = 6 47 | buf[w] = 'm' 48 | } 49 | w, u = fmtFrac(buf[:w], u, prec) 50 | w = fmtInt(buf[:w], u) 51 | } else { 52 | w-- 53 | buf[w] = 's' 54 | 55 | w, u = fmtFrac(buf[:w], u, 9) 56 | 57 | // u is now integer seconds 58 | w = fmtInt(buf[:w], u%60) 59 | u /= 60 60 | 61 | // u is now integer minutes 62 | if u > 0 { 63 | w-- 64 | buf[w] = 'm' 65 | w = fmtInt(buf[:w], u%60) 66 | u /= 60 67 | 68 | // u is now integer hours 69 | // Stop at hours because days can be different lengths. 70 | if u > 0 { 71 | w-- 72 | buf[w] = 'h' 73 | w = fmtInt(buf[:w], u) 74 | } 75 | } 76 | } 77 | 78 | if neg { 79 | w-- 80 | buf[w] = '-' 81 | } 82 | 83 | return append(b, buf[w:]...) 84 | } 85 | 86 | // fmtFrac formats the fraction of v/10**prec (e.g., ".12345") into the 87 | // tail of buf, omitting trailing zeros. it omits the decimal 88 | // point too when the fraction is 0. It returns the index where the 89 | // output bytes begin and the value v/10**prec. 90 | func fmtFrac(buf []byte, v uint64, prec int) (nw int, nv uint64) { 91 | // Omit trailing zeros up to and including decimal point. 92 | w := len(buf) 93 | print := false 94 | for i := 0; i < prec; i++ { 95 | digit := v % 10 96 | print = print || digit != 0 97 | if print { 98 | w-- 99 | buf[w] = byte(digit) + '0' 100 | } 101 | v /= 10 102 | } 103 | if print { 104 | w-- 105 | buf[w] = '.' 106 | } 107 | return w, v 108 | } 109 | 110 | // fmtInt formats v into the tail of buf. 111 | // It returns the index where the output begins. 112 | func fmtInt(buf []byte, v uint64) int { 113 | w := len(buf) 114 | if v == 0 { 115 | w-- 116 | buf[w] = '0' 117 | } else { 118 | for v > 0 { 119 | w-- 120 | buf[w] = byte(v%10) + '0' 121 | v /= 10 122 | } 123 | } 124 | return w 125 | } 126 | -------------------------------------------------------------------------------- /codec.go: -------------------------------------------------------------------------------- 1 | package objconv 2 | 3 | import ( 4 | "io" 5 | "sync" 6 | ) 7 | 8 | // A Codec is a factory for encoder and decoders that work on byte streams. 9 | type Codec struct { 10 | NewEmitter func(io.Writer) Emitter 11 | NewParser func(io.Reader) Parser 12 | } 13 | 14 | // NewEncoder returns a new encoder that outputs to w. 15 | func (c Codec) NewEncoder(w io.Writer) *Encoder { 16 | return NewEncoder(c.NewEmitter(w)) 17 | } 18 | 19 | // NewDecoder returns a new decoder that takes input from r. 20 | func (c Codec) NewDecoder(r io.Reader) *Decoder { 21 | return NewDecoder(c.NewParser(r)) 22 | } 23 | 24 | // NewStreamEncoder returns a new stream encoder that outputs to w. 25 | func (c Codec) NewStreamEncoder(w io.Writer) *StreamEncoder { 26 | return NewStreamEncoder(c.NewEmitter(w)) 27 | } 28 | 29 | // NewStreamDecoder returns a new stream decoder that takes input from r. 30 | func (c Codec) NewStreamDecoder(r io.Reader) *StreamDecoder { 31 | return NewStreamDecoder(c.NewParser(r)) 32 | } 33 | 34 | // A Registry associates mime types to codecs. 35 | // 36 | // It is safe to use a registry concurrently from multiple goroutines. 37 | type Registry struct { 38 | mutex sync.RWMutex 39 | codecs map[string]Codec 40 | } 41 | 42 | // Register adds a codec for a mimetype to r. 43 | func (reg *Registry) Register(mimetype string, codec Codec) { 44 | defer reg.mutex.Unlock() 45 | reg.mutex.Lock() 46 | 47 | if reg.codecs == nil { 48 | reg.codecs = make(map[string]Codec) 49 | } 50 | 51 | reg.codecs[mimetype] = codec 52 | } 53 | 54 | // Unregister removes the codec for a mimetype from r. 55 | func (reg *Registry) Unregister(mimetype string) { 56 | defer reg.mutex.Unlock() 57 | reg.mutex.Lock() 58 | 59 | delete(reg.codecs, mimetype) 60 | } 61 | 62 | // Lookup returns the codec associated with mimetype, ok is set to true or false 63 | // based on whether a codec was found. 64 | func (reg *Registry) Lookup(mimetype string) (codec Codec, ok bool) { 65 | reg.mutex.RLock() 66 | codec, ok = reg.codecs[mimetype] 67 | reg.mutex.RUnlock() 68 | return 69 | } 70 | 71 | // Codecs returns a map of all codecs registered in reg. 72 | func (reg *Registry) Codecs() (codecs map[string]Codec) { 73 | codecs = make(map[string]Codec) 74 | reg.mutex.RLock() 75 | for mimetype, codec := range reg.codecs { 76 | codecs[mimetype] = codec 77 | } 78 | reg.mutex.RUnlock() 79 | return 80 | } 81 | 82 | // The global registry to which packages add their codecs. 83 | var registry Registry 84 | 85 | // Register adds a codec for a mimetype to the global registry. 86 | func Register(mimetype string, codec Codec) { 87 | registry.Register(mimetype, codec) 88 | } 89 | 90 | // Unregister removes the codec for a mimetype from the global registry. 91 | func Unregister(mimetype string) { 92 | registry.Unregister(mimetype) 93 | } 94 | 95 | // Lookup returns the codec associated with mimetype, ok is set to true or false 96 | // based on whether a codec was found. 97 | func Lookup(mimetype string) (Codec, bool) { 98 | return registry.Lookup(mimetype) 99 | } 100 | 101 | // Codecs returns a map of all codecs registered in the global registry. 102 | func Codecs() map[string]Codec { 103 | return registry.Codecs() 104 | } 105 | -------------------------------------------------------------------------------- /resp/encode_test.go: -------------------------------------------------------------------------------- 1 | package resp 2 | 3 | import ( 4 | "bytes" 5 | "errors" 6 | "fmt" 7 | "io/ioutil" 8 | "strings" 9 | "testing" 10 | "time" 11 | ) 12 | 13 | var respEncodeTests = []struct { 14 | v interface{} 15 | s string 16 | }{ 17 | {nil, "$-1\r\n"}, 18 | 19 | {true, "+true\r\n"}, 20 | {false, "+false\r\n"}, 21 | 22 | {0, ":0\r\n"}, 23 | {-1, ":-1\r\n"}, 24 | {42, ":42\r\n"}, 25 | 26 | {0.0, "+0\r\n"}, 27 | {0.5, "+0.5\r\n"}, 28 | 29 | {"", "+\r\n"}, 30 | {"Hello World!", "+Hello World!\r\n"}, 31 | {"Hello\nWorld!", "+Hello\nWorld!\r\n"}, 32 | {"Hello\r\nWorld!", "$13\r\nHello\r\nWorld!\r\n"}, 33 | 34 | {[]byte(nil), "$0\r\n\r\n"}, 35 | {[]byte("Hello World!"), "$12\r\nHello World!\r\n"}, 36 | 37 | {errors.New(""), "-\r\n"}, 38 | {errors.New("oops"), "-oops\r\n"}, 39 | {errors.New("A\r\nB\r\nC\r\n"), "-A\r\n"}, 40 | 41 | {time.Date(2016, 12, 20, 0, 20, 1, 0, time.UTC), "+2016-12-20T00:20:01Z\r\n"}, 42 | {time.Second, "+1s\r\n"}, 43 | 44 | {[]int{}, "*0\r\n"}, 45 | {[]int{1, 2, 3}, "*3\r\n:1\r\n:2\r\n:3\r\n"}, 46 | 47 | {struct{}{}, "*0\r\n"}, 48 | {struct{ A int }{42}, "*2\r\n+A\r\n:42\r\n"}, 49 | } 50 | 51 | func TestMarshal(t *testing.T) { 52 | for _, test := range respEncodeTests { 53 | t.Run(testName(test.s), func(t *testing.T) { 54 | b, err := Marshal(test.v) 55 | 56 | if err != nil { 57 | t.Error(err) 58 | } 59 | 60 | if s := string(b); s != test.s { 61 | t.Error(s) 62 | } 63 | }) 64 | } 65 | } 66 | 67 | func TestStreamEncoder(t *testing.T) { 68 | tests := []struct { 69 | a []int 70 | s string 71 | }{ 72 | { 73 | a: []int{}, 74 | s: "*0\r\n", 75 | }, 76 | { 77 | a: []int{1}, 78 | s: "*1\r\n:1\r\n", 79 | }, 80 | { 81 | a: []int{1, 2}, 82 | s: "*2\r\n:1\r\n:2\r\n", 83 | }, 84 | { 85 | a: []int{1, 2, 3}, 86 | s: "*3\r\n:1\r\n:2\r\n:3\r\n", 87 | }, 88 | } 89 | 90 | for _, test := range tests { 91 | t.Run(fmt.Sprintf("%#v", test), func(t *testing.T) { 92 | b := &bytes.Buffer{} 93 | e := NewStreamEncoder(b) 94 | 95 | for _, v := range test.a { 96 | if err := e.Encode(v); err != nil { 97 | t.Error(err) 98 | } 99 | } 100 | 101 | if err := e.Close(); err != nil { 102 | t.Error(err) 103 | } 104 | 105 | if s := b.String(); s != test.s { 106 | t.Errorf("%#v", s) 107 | } 108 | }) 109 | } 110 | } 111 | 112 | func BenchmarkEncoder(b *testing.B) { 113 | e := NewEncoder(ioutil.Discard) 114 | 115 | for _, test := range respEncodeTests { 116 | b.Run(testName(test.s), func(b *testing.B) { 117 | for i := 0; i != b.N; i++ { 118 | if err := e.Encode(test.v); err != nil { 119 | b.Fatal(err) 120 | } 121 | } 122 | b.SetBytes(int64(len(test.s))) 123 | }) 124 | } 125 | } 126 | 127 | func BenchmarkMarshal(b *testing.B) { 128 | for _, test := range respEncodeTests { 129 | b.Run(testName(test.s), func(b *testing.B) { 130 | for i := 0; i != b.N; i++ { 131 | if _, err := Marshal(test.v); err != nil { 132 | b.Fatal(err) 133 | } 134 | } 135 | b.SetBytes(int64(len(test.s))) 136 | }) 137 | } 138 | } 139 | 140 | func testName(s string) string { 141 | return strings.Replace(s, "\r\n", "", -1) 142 | } 143 | -------------------------------------------------------------------------------- /objutil/limits.go: -------------------------------------------------------------------------------- 1 | package objutil 2 | 3 | import ( 4 | "fmt" 5 | "reflect" 6 | ) 7 | 8 | const ( 9 | // UintMax is the maximum value of a uint. 10 | UintMax = ^uint(0) 11 | 12 | // UintMin is the minimum value of a uint. 13 | UintMin = 0 14 | 15 | // Uint8Max is the maximum value of a uint8. 16 | Uint8Max = 255 17 | 18 | // Uint8Min is the minimum value of a uint8. 19 | Uint8Min = 0 20 | 21 | // Uint16Max is the maximum value of a uint16. 22 | Uint16Max = 65535 23 | 24 | // Uint16Min is the minimum value of a uint16. 25 | Uint16Min = 0 26 | 27 | // Uint32Max is the maximum value of a uint32. 28 | Uint32Max = 4294967295 29 | 30 | // Uint32Min is the minimum value of a uint32. 31 | Uint32Min = 0 32 | 33 | // Uint64Max is the maximum value of a uint64. 34 | Uint64Max = 18446744073709551615 35 | 36 | // Uint64Min is the minimum value of a uint64. 37 | Uint64Min = 0 38 | 39 | // UintptrMax is the maximum value of a uintptr. 40 | UintptrMax = ^uintptr(0) 41 | 42 | // UintptrMin is the minimum value of a uintptr. 43 | UintptrMin = 0 44 | 45 | // IntMax is the maximum value of a int. 46 | IntMax = int(UintMax >> 1) 47 | 48 | // IntMin is the minimum value of a int. 49 | IntMin = -IntMax - 1 50 | 51 | // Int8Max is the maximum value of a int8. 52 | Int8Max = 127 53 | 54 | // Int8Min is the minimum value of a int8. 55 | Int8Min = -128 56 | 57 | // Int16Max is the maximum value of a int16. 58 | Int16Max = 32767 59 | 60 | // Int16Min is the minimum value of a int16. 61 | Int16Min = -32768 62 | 63 | // Int32Max is the maximum value of a int32. 64 | Int32Max = 2147483647 65 | 66 | // Int32Min is the minimum value of a int32. 67 | Int32Min = -2147483648 68 | 69 | // Int64Max is the maximum value of a int64. 70 | Int64Max = 9223372036854775807 71 | 72 | // Int64Min is the minimum value of a int64. 73 | Int64Min = -9223372036854775808 74 | 75 | // Float32IntMax is the maximum consecutive integer value representable by a float32. 76 | Float32IntMax = 16777216 77 | 78 | // Float32IntMin is the minimum consecutive integer value representable by a float32. 79 | Float32IntMin = -16777216 80 | 81 | // Float64IntMax is the maximum consecutive integer value representable by a float64. 82 | Float64IntMax = 9007199254740992 83 | 84 | // Float64IntMin is the minimum consecutive integer value representable by a float64. 85 | Float64IntMin = -9007199254740992 86 | ) 87 | 88 | // CheckUint64Bounds verifies that v is smaller than max, t represents the 89 | // original type of v. 90 | func CheckUint64Bounds(v uint64, max uint64, t reflect.Type) (err error) { 91 | if v > max { 92 | err = fmt.Errorf("objconv: %d overflows the maximum value of %d for %s", v, max, t) 93 | } 94 | return 95 | } 96 | 97 | // CheckInt64Bounds verifies that v is within min and max, t represents the 98 | // original type of v. 99 | func CheckInt64Bounds(v int64, min int64, max uint64, t reflect.Type) (err error) { 100 | if v < min { 101 | err = fmt.Errorf("objconv: %d overflows the minimum value of %d for %s", v, min, t) 102 | } 103 | if v > 0 && uint64(v) > max { 104 | err = fmt.Errorf("objconv: %d overflows the maximum value of %d for %s", v, max, t) 105 | } 106 | return 107 | } 108 | -------------------------------------------------------------------------------- /yaml/vendor/gopkg.in/yaml.v2/README.md: -------------------------------------------------------------------------------- 1 | # YAML support for the Go language 2 | 3 | Introduction 4 | ------------ 5 | 6 | The yaml package enables Go programs to comfortably encode and decode YAML 7 | values. It was developed within [Canonical](https://www.canonical.com) as 8 | part of the [juju](https://juju.ubuntu.com) project, and is based on a 9 | pure Go port of the well-known [libyaml](http://pyyaml.org/wiki/LibYAML) 10 | C library to parse and generate YAML data quickly and reliably. 11 | 12 | Compatibility 13 | ------------- 14 | 15 | The yaml package supports most of YAML 1.1 and 1.2, including support for 16 | anchors, tags, map merging, etc. Multi-document unmarshalling is not yet 17 | implemented, and base-60 floats from YAML 1.1 are purposefully not 18 | supported since they're a poor design and are gone in YAML 1.2. 19 | 20 | Installation and usage 21 | ---------------------- 22 | 23 | The import path for the package is *gopkg.in/yaml.v2*. 24 | 25 | To install it, run: 26 | 27 | go get gopkg.in/yaml.v2 28 | 29 | API documentation 30 | ----------------- 31 | 32 | If opened in a browser, the import path itself leads to the API documentation: 33 | 34 | * [https://gopkg.in/yaml.v2](https://gopkg.in/yaml.v2) 35 | 36 | API stability 37 | ------------- 38 | 39 | The package API for yaml v2 will remain stable as described in [gopkg.in](https://gopkg.in). 40 | 41 | 42 | License 43 | ------- 44 | 45 | The yaml package is licensed under the Apache License 2.0. Please see the LICENSE file for details. 46 | 47 | 48 | Example 49 | ------- 50 | 51 | ```Go 52 | package main 53 | 54 | import ( 55 | "fmt" 56 | "log" 57 | 58 | "gopkg.in/yaml.v2" 59 | ) 60 | 61 | var data = ` 62 | a: Easy! 63 | b: 64 | c: 2 65 | d: [3, 4] 66 | ` 67 | 68 | type T struct { 69 | A string 70 | B struct { 71 | RenamedC int `yaml:"c"` 72 | D []int `yaml:",flow"` 73 | } 74 | } 75 | 76 | func main() { 77 | t := T{} 78 | 79 | err := yaml.Unmarshal([]byte(data), &t) 80 | if err != nil { 81 | log.Fatalf("error: %v", err) 82 | } 83 | fmt.Printf("--- t:\n%v\n\n", t) 84 | 85 | d, err := yaml.Marshal(&t) 86 | if err != nil { 87 | log.Fatalf("error: %v", err) 88 | } 89 | fmt.Printf("--- t dump:\n%s\n\n", string(d)) 90 | 91 | m := make(map[interface{}]interface{}) 92 | 93 | err = yaml.Unmarshal([]byte(data), &m) 94 | if err != nil { 95 | log.Fatalf("error: %v", err) 96 | } 97 | fmt.Printf("--- m:\n%v\n\n", m) 98 | 99 | d, err = yaml.Marshal(&m) 100 | if err != nil { 101 | log.Fatalf("error: %v", err) 102 | } 103 | fmt.Printf("--- m dump:\n%s\n\n", string(d)) 104 | } 105 | ``` 106 | 107 | This example will generate the following output: 108 | 109 | ``` 110 | --- t: 111 | {Easy! {2 [3 4]}} 112 | 113 | --- t dump: 114 | a: Easy! 115 | b: 116 | c: 2 117 | d: [3, 4] 118 | 119 | 120 | --- m: 121 | map[a:Easy! b:map[c:2 d:[3 4]]] 122 | 123 | --- m dump: 124 | a: Easy! 125 | b: 126 | c: 2 127 | d: 128 | - 3 129 | - 4 130 | ``` 131 | 132 | -------------------------------------------------------------------------------- /objutil/int.go: -------------------------------------------------------------------------------- 1 | package objutil 2 | 3 | import "fmt" 4 | 5 | // ParseInt parses a decimanl representation of an int64 from b. 6 | // 7 | // The function is equivalent to calling strconv.ParseInt(string(b), 10, 64) but 8 | // it prevents Go from making a memory allocation for converting a byte slice to 9 | // a string (escape analysis fails due to the error returned by strconv.ParseInt). 10 | // 11 | // Because it only works with base 10 the function is also significantly faster 12 | // than strconv.ParseInt. 13 | func ParseInt(b []byte) (int64, error) { 14 | var val int64 15 | 16 | if len(b) == 0 { 17 | return 0, errorInvalidUint64(b) 18 | } 19 | 20 | if b[0] == '-' { 21 | const max = Int64Min 22 | const lim = max / 10 23 | 24 | if b = b[1:]; len(b) == 0 { 25 | return 0, errorInvalidUint64(b) 26 | } 27 | 28 | for _, d := range b { 29 | if !(d >= '0' && d <= '9') { 30 | return 0, errorInvalidInt64(b) 31 | } 32 | 33 | if val < lim { 34 | return 0, errorOverflowInt64(b) 35 | } 36 | 37 | val *= 10 38 | x := int64(d - '0') 39 | 40 | if val < (max + x) { 41 | return 0, errorOverflowInt64(b) 42 | } 43 | 44 | val -= x 45 | } 46 | } else { 47 | const max = Int64Max 48 | const lim = max / 10 49 | 50 | for _, d := range b { 51 | if !(d >= '0' && d <= '9') { 52 | return 0, errorInvalidInt64(b) 53 | } 54 | x := int64(d - '0') 55 | 56 | if val > lim { 57 | return 0, errorOverflowInt64(b) 58 | } 59 | 60 | if val *= 10; val > (max - x) { 61 | return 0, errorOverflowInt64(b) 62 | } 63 | 64 | val += x 65 | } 66 | } 67 | 68 | return val, nil 69 | } 70 | 71 | // ParseUintHex parses a hexadecimanl representation of a uint64 from b. 72 | // 73 | // The function is equivalent to calling strconv.ParseUint(string(b), 16, 64) but 74 | // it prevents Go from making a memory allocation for converting a byte slice to 75 | // a string (escape analysis fails due to the error returned by strconv.ParseUint). 76 | // 77 | // Because it only works with base 16 the function is also significantly faster 78 | // than strconv.ParseUint. 79 | func ParseUintHex(b []byte) (uint64, error) { 80 | const max = Uint64Max 81 | const lim = max / 0x10 82 | var val uint64 83 | 84 | if len(b) == 0 { 85 | return 0, errorInvalidUint64(b) 86 | } 87 | 88 | for _, d := range b { 89 | var x uint64 90 | 91 | switch { 92 | case d >= '0' && d <= '9': 93 | x = uint64(d - '0') 94 | 95 | case d >= 'A' && d <= 'F': 96 | x = uint64(d-'A') + 0xA 97 | 98 | case d >= 'a' && d <= 'f': 99 | x = uint64(d-'a') + 0xA 100 | 101 | default: 102 | return 0, errorInvalidUint64(b) 103 | } 104 | 105 | if val > lim { 106 | return 0, errorOverflowUint64(b) 107 | } 108 | 109 | if val *= 0x10; val > (max - x) { 110 | return 0, errorOverflowUint64(b) 111 | } 112 | 113 | val += x 114 | } 115 | 116 | return val, nil 117 | } 118 | 119 | func errorInvalidInt64(b []byte) error { 120 | return fmt.Errorf("objconv: %#v is not a valid decimal representation of a signed 64 bits integer", string(b)) 121 | } 122 | 123 | func errorOverflowInt64(b []byte) error { 124 | return fmt.Errorf("objconv: %#v overflows the maximum values of a signed 64 bits integer", string(b)) 125 | } 126 | 127 | func errorInvalidUint64(b []byte) error { 128 | return fmt.Errorf("objconv: %#v is not a valid decimal representation of an unsigned 64 bits integer", string(b)) 129 | } 130 | 131 | func errorOverflowUint64(b []byte) error { 132 | return fmt.Errorf("objconv: %#v overflows the maximum values of an unsigned 64 bits integer", string(b)) 133 | } 134 | -------------------------------------------------------------------------------- /yaml/emit.go: -------------------------------------------------------------------------------- 1 | package yaml 2 | 3 | import ( 4 | "encoding/base64" 5 | "io" 6 | "time" 7 | 8 | yaml "gopkg.in/yaml.v2" 9 | ) 10 | 11 | // Emitter implements a YAML emitter that satisfies the objconv.Emitter 12 | // interface. 13 | type Emitter struct { 14 | w io.Writer 15 | // The stack is used to keep track of the container being built by the 16 | // emitter, which may be an arrayEmitter or mapEmitter. 17 | stack []emitter 18 | } 19 | 20 | func NewEmitter(w io.Writer) *Emitter { 21 | return &Emitter{w: w} 22 | } 23 | 24 | func (e *Emitter) Reset(w io.Writer) { 25 | e.w = w 26 | e.stack = e.stack[:0] 27 | } 28 | 29 | func (e *Emitter) EmitNil() error { 30 | return e.emit(nil) 31 | } 32 | 33 | func (e *Emitter) EmitBool(v bool) error { 34 | return e.emit(v) 35 | } 36 | 37 | func (e *Emitter) EmitInt(v int64, _ int) error { 38 | return e.emit(v) 39 | } 40 | 41 | func (e *Emitter) EmitUint(v uint64, _ int) error { 42 | return e.emit(v) 43 | } 44 | 45 | func (e *Emitter) EmitFloat(v float64, _ int) error { 46 | return e.emit(v) 47 | } 48 | 49 | func (e *Emitter) EmitString(v string) error { 50 | return e.emit(v) 51 | } 52 | 53 | func (e *Emitter) EmitBytes(v []byte) error { 54 | return e.emit(base64.StdEncoding.EncodeToString(v)) 55 | } 56 | 57 | func (e *Emitter) EmitTime(v time.Time) error { 58 | return e.emit(v.Format(time.RFC3339Nano)) 59 | } 60 | 61 | func (e *Emitter) EmitDuration(v time.Duration) error { 62 | return e.emit(v.String()) 63 | } 64 | 65 | func (e *Emitter) EmitError(v error) error { 66 | return e.emit(v.Error()) 67 | } 68 | 69 | func (e *Emitter) EmitArrayBegin(_ int) (err error) { 70 | e.push(&arrayEmitter{}) 71 | return 72 | } 73 | 74 | func (e *Emitter) EmitArrayEnd() (err error) { 75 | e.emit(e.pop().value()) 76 | return 77 | } 78 | 79 | func (e *Emitter) EmitArrayNext() (err error) { 80 | return 81 | } 82 | 83 | func (e *Emitter) EmitMapBegin(_ int) (err error) { 84 | e.push(&mapEmitter{}) 85 | return 86 | } 87 | 88 | func (e *Emitter) EmitMapEnd() (err error) { 89 | e.emit(e.pop().value()) 90 | return 91 | } 92 | 93 | func (e *Emitter) EmitMapValue() (err error) { 94 | return 95 | } 96 | 97 | func (e *Emitter) EmitMapNext() (err error) { 98 | return 99 | } 100 | 101 | func (e *Emitter) TextEmitter() bool { 102 | return true 103 | } 104 | 105 | func (e *Emitter) emit(v interface{}) (err error) { 106 | var b []byte 107 | 108 | if n := len(e.stack); n != 0 { 109 | e.stack[n-1].emit(v) 110 | return 111 | } 112 | 113 | if b, err = yaml.Marshal(v); err != nil { 114 | return 115 | } 116 | 117 | _, err = e.w.Write(b) 118 | return 119 | } 120 | 121 | func (e *Emitter) push(v emitter) { 122 | e.stack = append(e.stack, v) 123 | } 124 | 125 | func (e *Emitter) pop() emitter { 126 | i := len(e.stack) - 1 127 | v := e.stack[i] 128 | e.stack = e.stack[:i] 129 | return v 130 | } 131 | 132 | type emitter interface { 133 | emit(interface{}) 134 | value() interface{} 135 | } 136 | 137 | type arrayEmitter struct { 138 | self []interface{} 139 | } 140 | 141 | func (e *arrayEmitter) emit(v interface{}) { 142 | e.self = append(e.self, v) 143 | } 144 | 145 | func (e *arrayEmitter) value() interface{} { 146 | return e.self 147 | } 148 | 149 | type mapEmitter struct { 150 | self yaml.MapSlice 151 | val bool 152 | } 153 | 154 | func (e *mapEmitter) emit(v interface{}) { 155 | if e.val { 156 | e.val = false 157 | e.self[len(e.self)-1].Value = v 158 | } else { 159 | e.val = true 160 | e.self = append(e.self, yaml.MapItem{Key: v}) 161 | } 162 | } 163 | 164 | func (e *mapEmitter) value() interface{} { 165 | return e.self 166 | } 167 | -------------------------------------------------------------------------------- /cmd/objconv/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bufio" 5 | "flag" 6 | "fmt" 7 | "io" 8 | "os" 9 | "reflect" 10 | "sort" 11 | "strings" 12 | 13 | "github.com/segmentio/objconv" 14 | _ "github.com/segmentio/objconv/cbor" 15 | _ "github.com/segmentio/objconv/json" 16 | _ "github.com/segmentio/objconv/msgpack" 17 | _ "github.com/segmentio/objconv/resp" 18 | _ "github.com/segmentio/objconv/yaml" 19 | ) 20 | 21 | // document is used to preserve the order of keys in maps. 22 | type document []item 23 | 24 | type item struct { 25 | K interface{} 26 | V interface{} 27 | } 28 | 29 | func (doc document) EncodeValue(e objconv.Encoder) error { 30 | i := 0 31 | return e.EncodeMap(len(doc), func(k objconv.Encoder, v objconv.Encoder) (err error) { 32 | if err = k.Encode(doc[i].K); err != nil { 33 | return 34 | } 35 | if err = v.Encode(doc[i].V); err != nil { 36 | return 37 | } 38 | i++ 39 | return 40 | }) 41 | } 42 | 43 | func (doc *document) DecodeValue(d objconv.Decoder) error { 44 | return d.DecodeMap(func(k objconv.Decoder, v objconv.Decoder) (err error) { 45 | var item item 46 | if err = k.Decode(&item.K); err != nil { 47 | return 48 | } 49 | if err = v.Decode(&item.V); err != nil { 50 | return 51 | } 52 | *doc = append(*doc, item) 53 | return 54 | }) 55 | } 56 | 57 | func main() { 58 | var r = bufio.NewReader(os.Stdin) 59 | var w = bufio.NewWriter(os.Stdout) 60 | var input string 61 | var output string 62 | var list bool 63 | var pretty bool 64 | 65 | flag.StringVar(&input, "i", "json", "The format of the input stream") 66 | flag.StringVar(&output, "o", "json", "The format of the output stream") 67 | flag.BoolVar(&list, "l", false, "Prints a list of all the formats available") 68 | flag.BoolVar(&pretty, "p", false, "Prints in pretty format when available") 69 | flag.Parse() 70 | 71 | if list { 72 | codecs(os.Stdout) 73 | return 74 | } 75 | 76 | if err := conv(w, output, r, input, pretty); err != nil { 77 | fmt.Fprintf(os.Stderr, "error: %v\n", err) 78 | os.Exit(1) 79 | } 80 | 81 | w.Flush() 82 | } 83 | 84 | func codecs(w io.Writer) { 85 | var names []string 86 | for name := range objconv.Codecs() { 87 | names = append(names, name) 88 | } 89 | sort.Strings(names) 90 | for _, name := range names { 91 | fmt.Fprintf(w, "- %s\n", name) 92 | } 93 | return 94 | } 95 | 96 | func conv(w io.Writer, output string, r io.Reader, input string, pretty bool) (err error) { 97 | var ic objconv.Codec 98 | var oc objconv.Codec 99 | var ok bool 100 | 101 | if ic, ok = objconv.Lookup(input); !ok { 102 | err = fmt.Errorf("unknown input format: %s", input) 103 | return 104 | } 105 | 106 | if oc, ok = objconv.Lookup(output); !ok { 107 | err = fmt.Errorf("unknown output format: %s", output) 108 | return 109 | } 110 | 111 | var d = objconv.NewStreamDecoder(ic.NewParser(r)) 112 | var e *objconv.StreamEncoder 113 | var v interface{} 114 | var m = oc.NewEmitter(w) 115 | 116 | if pretty { 117 | if p, ok := m.(objconv.PrettyEmitter); ok { 118 | m = p.PrettyEmitter() 119 | } 120 | } 121 | 122 | if e, err = d.Encoder(m); err != nil { 123 | if err == io.EOF { // empty input 124 | err = nil 125 | } 126 | return 127 | } 128 | 129 | // Overwrite the type used for decoding maps so we can preserve the order 130 | // of the keys. 131 | d.MapType = reflect.TypeOf(document(nil)) 132 | 133 | for d.Decode(&v) == nil { 134 | if err = e.Encode(v); err != nil { 135 | return 136 | } 137 | v = nil 138 | } 139 | 140 | if err = e.Close(); err != nil { 141 | return 142 | } 143 | 144 | // Not ideal but does the job, if the output is JSON we add a newline 145 | // character at the end to make it easier to read in terminals. 146 | if strings.Contains(output, "json") { 147 | fmt.Fprintln(w) 148 | } 149 | 150 | err = d.Err() 151 | return 152 | } 153 | -------------------------------------------------------------------------------- /emit.go: -------------------------------------------------------------------------------- 1 | package objconv 2 | 3 | import "time" 4 | 5 | // The Emitter interface must be implemented by types that provide encoding 6 | // of a specific format (like json, resp, ...). 7 | // 8 | // Emitters are not expected to be safe for use by multiple goroutines. 9 | type Emitter interface { 10 | // EmitNil writes a nil value to the writer. 11 | EmitNil() error 12 | 13 | // EmitBool writes a boolean value to the writer. 14 | EmitBool(bool) error 15 | 16 | // EmitInt writes an integer value to the writer. 17 | EmitInt(v int64, bitSize int) error 18 | 19 | // EmitUint writes an unsigned integer value to the writer. 20 | EmitUint(v uint64, bitSize int) error 21 | 22 | // EmitFloat writes a floating point value to the writer. 23 | EmitFloat(v float64, bitSize int) error 24 | 25 | // EmitString writes a string value to the writer. 26 | EmitString(string) error 27 | 28 | // EmitBytes writes a []byte value to the writer. 29 | EmitBytes([]byte) error 30 | 31 | // EmitTime writes a time.Time value to the writer. 32 | EmitTime(time.Time) error 33 | 34 | // EmitDuration writes a time.Duration value to the writer. 35 | EmitDuration(time.Duration) error 36 | 37 | // EmitError writes an error value to the writer. 38 | EmitError(error) error 39 | 40 | // EmitArrayBegin writes the beginning of an array value to the writer. 41 | // The method receives the length of the array. 42 | EmitArrayBegin(int) error 43 | 44 | // EmitArrayEnd writes the end of an array value to the writer. 45 | EmitArrayEnd() error 46 | 47 | // EmitArrayNext is called after each array value except to the last one. 48 | EmitArrayNext() error 49 | 50 | // EmitMapBegin writes the beginning of a map value to the writer. 51 | // The method receives the length of the map. 52 | EmitMapBegin(int) error 53 | 54 | // EmitMapEnd writes the end of a map value to the writer. 55 | EmitMapEnd() error 56 | 57 | // EmitMapValue is called after each map key was written. 58 | EmitMapValue() error 59 | 60 | // EmitMapNext is called after each map value was written except the last one. 61 | EmitMapNext() error 62 | } 63 | 64 | // The PrettyEmitter interface may be implemented by emitters supporting a more 65 | // human-friendlly format. 66 | type PrettyEmitter interface { 67 | // PrettyEmitter returns a new emitter that outputs to the same writer in a 68 | // pretty format. 69 | PrettyEmitter() Emitter 70 | } 71 | 72 | // The textEmitter interface may be implemented by emitters of human-readable 73 | // formats. Such emitters instruct the encoder to prefer using 74 | // encoding.TextMarshaler over encoding.BinaryMarshaler for example. 75 | type textEmitter interface { 76 | // EmitsText returns true if the emitter produces a human-readable format. 77 | TextEmitter() bool 78 | } 79 | 80 | func isTextEmitter(emitter Emitter) bool { 81 | e, _ := emitter.(textEmitter) 82 | return e != nil && e.TextEmitter() 83 | } 84 | 85 | type discardEmitter struct{} 86 | 87 | func (e discardEmitter) EmitNil() error { return nil } 88 | func (e discardEmitter) EmitBool(v bool) error { return nil } 89 | func (e discardEmitter) EmitInt(v int64, _ int) error { return nil } 90 | func (e discardEmitter) EmitUint(v uint64, _ int) error { return nil } 91 | func (e discardEmitter) EmitFloat(v float64, _ int) error { return nil } 92 | func (e discardEmitter) EmitString(v string) error { return nil } 93 | func (e discardEmitter) EmitBytes(v []byte) error { return nil } 94 | func (e discardEmitter) EmitTime(v time.Time) error { return nil } 95 | func (e discardEmitter) EmitDuration(v time.Duration) error { return nil } 96 | func (e discardEmitter) EmitError(v error) error { return nil } 97 | func (e discardEmitter) EmitArrayBegin(v int) error { return nil } 98 | func (e discardEmitter) EmitArrayEnd() error { return nil } 99 | func (e discardEmitter) EmitArrayNext() error { return nil } 100 | func (e discardEmitter) EmitMapBegin(v int) error { return nil } 101 | func (e discardEmitter) EmitMapEnd() error { return nil } 102 | func (e discardEmitter) EmitMapNext() error { return nil } 103 | func (e discardEmitter) EmitMapValue() error { return nil } 104 | 105 | var ( 106 | // Discard is a special emitter that outputs nothing and simply discards 107 | // the values. 108 | // 109 | // This emitter is mostly useful to benchmark the encoder, but it can also be 110 | // used to disable an encoder output if necessary. 111 | Discard Emitter = discardEmitter{} 112 | ) 113 | -------------------------------------------------------------------------------- /yaml/vendor/gopkg.in/check.v1/printer.go: -------------------------------------------------------------------------------- 1 | package check 2 | 3 | import ( 4 | "bytes" 5 | "go/ast" 6 | "go/parser" 7 | "go/printer" 8 | "go/token" 9 | "os" 10 | ) 11 | 12 | func indent(s, with string) (r string) { 13 | eol := true 14 | for i := 0; i != len(s); i++ { 15 | c := s[i] 16 | switch { 17 | case eol && c == '\n' || c == '\r': 18 | case c == '\n' || c == '\r': 19 | eol = true 20 | case eol: 21 | eol = false 22 | s = s[:i] + with + s[i:] 23 | i += len(with) 24 | } 25 | } 26 | return s 27 | } 28 | 29 | func printLine(filename string, line int) (string, error) { 30 | fset := token.NewFileSet() 31 | file, err := os.Open(filename) 32 | if err != nil { 33 | return "", err 34 | } 35 | fnode, err := parser.ParseFile(fset, filename, file, parser.ParseComments) 36 | if err != nil { 37 | return "", err 38 | } 39 | config := &printer.Config{Mode: printer.UseSpaces, Tabwidth: 4} 40 | lp := &linePrinter{fset: fset, fnode: fnode, line: line, config: config} 41 | ast.Walk(lp, fnode) 42 | result := lp.output.Bytes() 43 | // Comments leave \n at the end. 44 | n := len(result) 45 | for n > 0 && result[n-1] == '\n' { 46 | n-- 47 | } 48 | return string(result[:n]), nil 49 | } 50 | 51 | type linePrinter struct { 52 | config *printer.Config 53 | fset *token.FileSet 54 | fnode *ast.File 55 | line int 56 | output bytes.Buffer 57 | stmt ast.Stmt 58 | } 59 | 60 | func (lp *linePrinter) emit() bool { 61 | if lp.stmt != nil { 62 | lp.trim(lp.stmt) 63 | lp.printWithComments(lp.stmt) 64 | lp.stmt = nil 65 | return true 66 | } 67 | return false 68 | } 69 | 70 | func (lp *linePrinter) printWithComments(n ast.Node) { 71 | nfirst := lp.fset.Position(n.Pos()).Line 72 | nlast := lp.fset.Position(n.End()).Line 73 | for _, g := range lp.fnode.Comments { 74 | cfirst := lp.fset.Position(g.Pos()).Line 75 | clast := lp.fset.Position(g.End()).Line 76 | if clast == nfirst-1 && lp.fset.Position(n.Pos()).Column == lp.fset.Position(g.Pos()).Column { 77 | for _, c := range g.List { 78 | lp.output.WriteString(c.Text) 79 | lp.output.WriteByte('\n') 80 | } 81 | } 82 | if cfirst >= nfirst && cfirst <= nlast && n.End() <= g.List[0].Slash { 83 | // The printer will not include the comment if it starts past 84 | // the node itself. Trick it into printing by overlapping the 85 | // slash with the end of the statement. 86 | g.List[0].Slash = n.End() - 1 87 | } 88 | } 89 | node := &printer.CommentedNode{n, lp.fnode.Comments} 90 | lp.config.Fprint(&lp.output, lp.fset, node) 91 | } 92 | 93 | func (lp *linePrinter) Visit(n ast.Node) (w ast.Visitor) { 94 | if n == nil { 95 | if lp.output.Len() == 0 { 96 | lp.emit() 97 | } 98 | return nil 99 | } 100 | first := lp.fset.Position(n.Pos()).Line 101 | last := lp.fset.Position(n.End()).Line 102 | if first <= lp.line && last >= lp.line { 103 | // Print the innermost statement containing the line. 104 | if stmt, ok := n.(ast.Stmt); ok { 105 | if _, ok := n.(*ast.BlockStmt); !ok { 106 | lp.stmt = stmt 107 | } 108 | } 109 | if first == lp.line && lp.emit() { 110 | return nil 111 | } 112 | return lp 113 | } 114 | return nil 115 | } 116 | 117 | func (lp *linePrinter) trim(n ast.Node) bool { 118 | stmt, ok := n.(ast.Stmt) 119 | if !ok { 120 | return true 121 | } 122 | line := lp.fset.Position(n.Pos()).Line 123 | if line != lp.line { 124 | return false 125 | } 126 | switch stmt := stmt.(type) { 127 | case *ast.IfStmt: 128 | stmt.Body = lp.trimBlock(stmt.Body) 129 | case *ast.SwitchStmt: 130 | stmt.Body = lp.trimBlock(stmt.Body) 131 | case *ast.TypeSwitchStmt: 132 | stmt.Body = lp.trimBlock(stmt.Body) 133 | case *ast.CaseClause: 134 | stmt.Body = lp.trimList(stmt.Body) 135 | case *ast.CommClause: 136 | stmt.Body = lp.trimList(stmt.Body) 137 | case *ast.BlockStmt: 138 | stmt.List = lp.trimList(stmt.List) 139 | } 140 | return true 141 | } 142 | 143 | func (lp *linePrinter) trimBlock(stmt *ast.BlockStmt) *ast.BlockStmt { 144 | if !lp.trim(stmt) { 145 | return lp.emptyBlock(stmt) 146 | } 147 | stmt.Rbrace = stmt.Lbrace 148 | return stmt 149 | } 150 | 151 | func (lp *linePrinter) trimList(stmts []ast.Stmt) []ast.Stmt { 152 | for i := 0; i != len(stmts); i++ { 153 | if !lp.trim(stmts[i]) { 154 | stmts[i] = lp.emptyStmt(stmts[i]) 155 | break 156 | } 157 | } 158 | return stmts 159 | } 160 | 161 | func (lp *linePrinter) emptyStmt(n ast.Node) *ast.ExprStmt { 162 | return &ast.ExprStmt{&ast.Ellipsis{n.Pos(), nil}} 163 | } 164 | 165 | func (lp *linePrinter) emptyBlock(n ast.Node) *ast.BlockStmt { 166 | p := n.Pos() 167 | return &ast.BlockStmt{p, []ast.Stmt{lp.emptyStmt(n)}, p} 168 | } 169 | -------------------------------------------------------------------------------- /yaml/vendor/gopkg.in/check.v1/reporter_test.go: -------------------------------------------------------------------------------- 1 | package check_test 2 | 3 | import ( 4 | "fmt" 5 | "path/filepath" 6 | "runtime" 7 | 8 | . "gopkg.in/check.v1" 9 | ) 10 | 11 | var _ = Suite(&reporterS{}) 12 | 13 | type reporterS struct { 14 | testFile string 15 | } 16 | 17 | func (s *reporterS) SetUpSuite(c *C) { 18 | _, fileName, _, ok := runtime.Caller(0) 19 | c.Assert(ok, Equals, true) 20 | s.testFile = filepath.Base(fileName) 21 | } 22 | 23 | func (s *reporterS) TestWrite(c *C) { 24 | testString := "test string" 25 | output := String{} 26 | 27 | dummyStream := true 28 | dummyVerbose := true 29 | o := NewOutputWriter(&output, dummyStream, dummyVerbose) 30 | 31 | o.Write([]byte(testString)) 32 | c.Assert(output.value, Equals, testString) 33 | } 34 | 35 | func (s *reporterS) TestWriteCallStartedWithStreamFlag(c *C) { 36 | testLabel := "test started label" 37 | stream := true 38 | output := String{} 39 | 40 | dummyVerbose := true 41 | o := NewOutputWriter(&output, stream, dummyVerbose) 42 | 43 | o.WriteCallStarted(testLabel, c) 44 | expected := fmt.Sprintf("%s: %s:\\d+: %s\n", testLabel, s.testFile, c.TestName()) 45 | c.Assert(output.value, Matches, expected) 46 | } 47 | 48 | func (s *reporterS) TestWriteCallStartedWithoutStreamFlag(c *C) { 49 | stream := false 50 | output := String{} 51 | 52 | dummyLabel := "dummy" 53 | dummyVerbose := true 54 | o := NewOutputWriter(&output, stream, dummyVerbose) 55 | 56 | o.WriteCallStarted(dummyLabel, c) 57 | c.Assert(output.value, Equals, "") 58 | } 59 | 60 | func (s *reporterS) TestWriteCallProblemWithStreamFlag(c *C) { 61 | testLabel := "test problem label" 62 | stream := true 63 | output := String{} 64 | 65 | dummyVerbose := true 66 | o := NewOutputWriter(&output, stream, dummyVerbose) 67 | 68 | o.WriteCallProblem(testLabel, c) 69 | expected := fmt.Sprintf("%s: %s:\\d+: %s\n\n", testLabel, s.testFile, c.TestName()) 70 | c.Assert(output.value, Matches, expected) 71 | } 72 | 73 | func (s *reporterS) TestWriteCallProblemWithoutStreamFlag(c *C) { 74 | testLabel := "test problem label" 75 | stream := false 76 | output := String{} 77 | 78 | dummyVerbose := true 79 | o := NewOutputWriter(&output, stream, dummyVerbose) 80 | 81 | o.WriteCallProblem(testLabel, c) 82 | expected := fmt.Sprintf(""+ 83 | "\n"+ 84 | "----------------------------------------------------------------------\n"+ 85 | "%s: %s:\\d+: %s\n\n", testLabel, s.testFile, c.TestName()) 86 | c.Assert(output.value, Matches, expected) 87 | } 88 | 89 | func (s *reporterS) TestWriteCallProblemWithoutStreamFlagWithLog(c *C) { 90 | testLabel := "test problem label" 91 | testLog := "test log" 92 | stream := false 93 | output := String{} 94 | 95 | dummyVerbose := true 96 | o := NewOutputWriter(&output, stream, dummyVerbose) 97 | 98 | c.Log(testLog) 99 | o.WriteCallProblem(testLabel, c) 100 | expected := fmt.Sprintf(""+ 101 | "\n"+ 102 | "----------------------------------------------------------------------\n"+ 103 | "%s: %s:\\d+: %s\n\n%s\n", testLabel, s.testFile, c.TestName(), testLog) 104 | c.Assert(output.value, Matches, expected) 105 | } 106 | 107 | func (s *reporterS) TestWriteCallSuccessWithStreamFlag(c *C) { 108 | testLabel := "test success label" 109 | stream := true 110 | output := String{} 111 | 112 | dummyVerbose := true 113 | o := NewOutputWriter(&output, stream, dummyVerbose) 114 | 115 | o.WriteCallSuccess(testLabel, c) 116 | expected := fmt.Sprintf("%s: %s:\\d+: %s\t\\d\\.\\d+s\n\n", testLabel, s.testFile, c.TestName()) 117 | c.Assert(output.value, Matches, expected) 118 | } 119 | 120 | func (s *reporterS) TestWriteCallSuccessWithStreamFlagAndReason(c *C) { 121 | testLabel := "test success label" 122 | testReason := "test skip reason" 123 | stream := true 124 | output := String{} 125 | 126 | dummyVerbose := true 127 | o := NewOutputWriter(&output, stream, dummyVerbose) 128 | c.FakeSkip(testReason) 129 | 130 | o.WriteCallSuccess(testLabel, c) 131 | expected := fmt.Sprintf("%s: %s:\\d+: %s \\(%s\\)\t\\d\\.\\d+s\n\n", 132 | testLabel, s.testFile, c.TestName(), testReason) 133 | c.Assert(output.value, Matches, expected) 134 | } 135 | 136 | func (s *reporterS) TestWriteCallSuccessWithoutStreamFlagWithVerboseFlag(c *C) { 137 | testLabel := "test success label" 138 | stream := false 139 | verbose := true 140 | output := String{} 141 | 142 | o := NewOutputWriter(&output, stream, verbose) 143 | 144 | o.WriteCallSuccess(testLabel, c) 145 | expected := fmt.Sprintf("%s: %s:\\d+: %s\t\\d\\.\\d+s\n", testLabel, s.testFile, c.TestName()) 146 | c.Assert(output.value, Matches, expected) 147 | } 148 | 149 | func (s *reporterS) TestWriteCallSuccessWithoutStreamFlagWithoutVerboseFlag(c *C) { 150 | testLabel := "test success label" 151 | stream := false 152 | verbose := false 153 | output := String{} 154 | 155 | o := NewOutputWriter(&output, stream, verbose) 156 | 157 | o.WriteCallSuccess(testLabel, c) 158 | c.Assert(output.value, Equals, "") 159 | } 160 | -------------------------------------------------------------------------------- /json/bench_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Large data benchmark. 6 | // The JSON data is a summary of agl's changes in the 7 | // go, webkit, and chromium open source projects. 8 | // We benchmark converting between the JSON form 9 | // and in-memory data structures. 10 | 11 | package json 12 | 13 | import ( 14 | "bytes" 15 | "compress/gzip" 16 | "io/ioutil" 17 | "os" 18 | "runtime" 19 | "strings" 20 | "sync" 21 | "testing" 22 | ) 23 | 24 | type codeResponse struct { 25 | Tree *codeNode `json:"tree"` 26 | Username string `json:"username"` 27 | } 28 | 29 | type codeNode struct { 30 | Name string `json:"name"` 31 | Kids []*codeNode `json:"kids"` 32 | CLWeight float64 `json:"cl_weight"` 33 | Touches int `json:"touches"` 34 | MinT int64 `json:"min_t"` 35 | MaxT int64 `json:"max_t"` 36 | MeanT int64 `json:"mean_t"` 37 | } 38 | 39 | var codeOnce sync.Once 40 | var codeJSON []byte 41 | var codeStruct codeResponse 42 | 43 | func codeInit() { 44 | codeOnce.Do(func() { 45 | f, err := os.Open(runtime.GOROOT() + "/src/encoding/json/testdata/code.json.gz") 46 | if err != nil { 47 | panic(err) 48 | } 49 | defer f.Close() 50 | gz, err := gzip.NewReader(f) 51 | if err != nil { 52 | panic(err) 53 | } 54 | data, err := ioutil.ReadAll(gz) 55 | if err != nil { 56 | panic(err) 57 | } 58 | 59 | codeJSON = data 60 | 61 | if err := Unmarshal(codeJSON, &codeStruct); err != nil { 62 | panic("unmarshal code.json: " + err.Error()) 63 | } 64 | }) 65 | } 66 | 67 | func BenchmarkCodeEncoder(b *testing.B) { 68 | codeInit() 69 | b.ResetTimer() 70 | enc := NewEncoder(ioutil.Discard) 71 | for i := 0; i < b.N; i++ { 72 | if err := enc.Encode(&codeStruct); err != nil { 73 | b.Fatal("Encode:", err) 74 | } 75 | } 76 | b.SetBytes(int64(len(codeJSON))) 77 | } 78 | 79 | func BenchmarkCodeMarshal(b *testing.B) { 80 | codeInit() 81 | b.ResetTimer() 82 | for i := 0; i < b.N; i++ { 83 | if _, err := Marshal(&codeStruct); err != nil { 84 | b.Fatal("Marshal:", err) 85 | } 86 | } 87 | b.SetBytes(int64(len(codeJSON))) 88 | } 89 | 90 | func BenchmarkCodeDecoder(b *testing.B) { 91 | codeInit() 92 | b.ResetTimer() 93 | var buf bytes.Buffer 94 | dec := NewDecoder(&buf) 95 | var r codeResponse 96 | for i := 0; i < b.N; i++ { 97 | buf.Write(codeJSON) 98 | // hide EOF 99 | buf.WriteByte('\n') 100 | buf.WriteByte('\n') 101 | buf.WriteByte('\n') 102 | if err := dec.Decode(&r); err != nil { 103 | b.Fatal("Decode:", err) 104 | } 105 | } 106 | b.SetBytes(int64(len(codeJSON))) 107 | } 108 | 109 | func BenchmarkDecoderStream(b *testing.B) { 110 | var buf bytes.Buffer 111 | dec := NewDecoder(&buf) 112 | buf.WriteString(`"` + strings.Repeat("x", 1000000) + `"` + "\n\n\n") 113 | var x interface{} 114 | if err := dec.Decode(&x); err != nil { 115 | b.Fatal("Decode:", err) 116 | } 117 | ones := strings.Repeat(" 1\n", 300000) + "\n\n\n" 118 | b.ResetTimer() 119 | for i := 0; i < b.N; i++ { 120 | if i%300000 == 0 { 121 | buf.WriteString(ones) 122 | } 123 | x = nil 124 | if err := dec.Decode(&x); err != nil || x != int64(1) { 125 | b.Fatalf("Decode: %v after %d", err, i) 126 | } 127 | } 128 | } 129 | 130 | func BenchmarkCodeUnmarshal(b *testing.B) { 131 | codeInit() 132 | b.ResetTimer() 133 | for i := 0; i < b.N; i++ { 134 | var r codeResponse 135 | if err := Unmarshal(codeJSON, &r); err != nil { 136 | b.Fatal("Unmarshal:", err) 137 | } 138 | } 139 | b.SetBytes(int64(len(codeJSON))) 140 | } 141 | 142 | func BenchmarkCodeUnmarshalReuse(b *testing.B) { 143 | codeInit() 144 | b.ResetTimer() 145 | var r codeResponse 146 | for i := 0; i < b.N; i++ { 147 | if err := Unmarshal(codeJSON, &r); err != nil { 148 | b.Fatal("Unmarshal:", err) 149 | } 150 | } 151 | b.SetBytes(int64(len(codeJSON))) 152 | } 153 | 154 | func BenchmarkUnmarshalString(b *testing.B) { 155 | data := []byte(`"hello, world"`) 156 | var s string 157 | 158 | for i := 0; i < b.N; i++ { 159 | if err := Unmarshal(data, &s); err != nil { 160 | b.Fatal("Unmarshal:", err) 161 | } 162 | } 163 | } 164 | 165 | func BenchmarkUnmarshalFloat64(b *testing.B) { 166 | var f float64 167 | data := []byte(`3.14`) 168 | 169 | for i := 0; i < b.N; i++ { 170 | if err := Unmarshal(data, &f); err != nil { 171 | b.Fatal("Unmarshal:", err) 172 | } 173 | } 174 | } 175 | 176 | func BenchmarkUnmarshalInt64(b *testing.B) { 177 | var x int64 178 | data := []byte(`3`) 179 | 180 | for i := 0; i < b.N; i++ { 181 | if err := Unmarshal(data, &x); err != nil { 182 | b.Fatal("Unmarshal:", err) 183 | } 184 | } 185 | } 186 | 187 | func BenchmarkIssue10335(b *testing.B) { 188 | b.ReportAllocs() 189 | var s struct{} 190 | j := []byte(`{"a":{ }}`) 191 | for n := 0; n < b.N; n++ { 192 | if err := Unmarshal(j, &s); err != nil { 193 | b.Fatal(err) 194 | } 195 | } 196 | } 197 | -------------------------------------------------------------------------------- /struct.go: -------------------------------------------------------------------------------- 1 | package objconv 2 | 3 | import ( 4 | "reflect" 5 | "sync" 6 | 7 | "github.com/segmentio/objconv/objutil" 8 | ) 9 | 10 | // structField represents a single field of a struct and carries information 11 | // useful to the algorithms of the objconv package. 12 | type structField struct { 13 | // The index of the field in the structure. 14 | index []int 15 | 16 | // The name of the field in the structure. 17 | name string 18 | 19 | // Omitempty is set to true when the field should be omitted if it has an 20 | // empty value. 21 | omitempty bool 22 | 23 | // Omitzero is set to true when the field should be omitted if it has a zero 24 | // value. 25 | omitzero bool 26 | 27 | // cache for the encoder and decoder methods 28 | encode encodeFunc 29 | decode decodeFunc 30 | } 31 | 32 | func makeStructField(f reflect.StructField, c map[reflect.Type]*structType) structField { 33 | var t objutil.Tag 34 | 35 | if tag := f.Tag.Get("objconv"); len(tag) != 0 { 36 | t = objutil.ParseTag(tag) 37 | } else { 38 | // To maximize compatibility with existing code we fallback to checking 39 | // if the field has a `json` tag. 40 | // 41 | // This tag doesn't support any of the extra features that are supported 42 | // by the `objconv` tag, and it should stay this way. It has to match 43 | // the behavior of the standard encoding/json package to avoid any 44 | // implicit changes in what would be intuitively expected. 45 | t = objutil.ParseTagJSON(f.Tag.Get("json")) 46 | } 47 | 48 | s := structField{ 49 | index: f.Index, 50 | name: f.Name, 51 | omitempty: t.Omitempty, 52 | omitzero: t.Omitzero, 53 | 54 | encode: makeEncodeFunc(f.Type, encodeFuncOpts{ 55 | recurse: true, 56 | structs: c, 57 | }), 58 | 59 | decode: makeDecodeFunc(f.Type, decodeFuncOpts{ 60 | recurse: true, 61 | structs: c, 62 | }), 63 | } 64 | 65 | if len(t.Name) != 0 { 66 | s.name = t.Name 67 | } 68 | 69 | return s 70 | } 71 | 72 | func (f *structField) omit(v reflect.Value) bool { 73 | return (f.omitempty && objutil.IsEmptyValue(v)) || (f.omitzero && objutil.IsZeroValue(v)) 74 | } 75 | 76 | // structType is used to represent a Go structure in internal data structures 77 | // that cache meta information to make field lookups faster and avoid having to 78 | // use reflection to lookup the same type information over and over again. 79 | type structType struct { 80 | fields []structField // the serializable fields of the struct 81 | fieldsByName map[string]*structField // cache of fields by name 82 | } 83 | 84 | // newStructType takes a Go type as argument and extract information to make a 85 | // new structType value. 86 | // The type has to be a struct type or a panic will be raised. 87 | func newStructType(t reflect.Type, c map[reflect.Type]*structType) *structType { 88 | if s := c[t]; s != nil { 89 | return s 90 | } 91 | 92 | n := t.NumField() 93 | s := &structType{ 94 | fields: make([]structField, 0, n), 95 | fieldsByName: make(map[string]*structField), 96 | } 97 | c[t] = s 98 | 99 | for i := 0; i != n; i++ { 100 | ft := t.Field(i) 101 | 102 | if ft.Anonymous || len(ft.PkgPath) != 0 { // anonymous or non-exported 103 | continue 104 | } 105 | 106 | sf := makeStructField(ft, c) 107 | 108 | if sf.name == "-" { // skip 109 | continue 110 | } 111 | 112 | s.fields = append(s.fields, sf) 113 | s.fieldsByName[sf.name] = &s.fields[len(s.fields)-1] 114 | } 115 | 116 | return s 117 | } 118 | 119 | // structTypeCache is a simple cache for mapping Go types to Struct values. 120 | type structTypeCache struct { 121 | mutex sync.RWMutex 122 | store map[reflect.Type]*structType 123 | } 124 | 125 | // lookup takes a Go type as argument and returns the matching structType value, 126 | // potentially creating it if it didn't already exist. 127 | // This method is safe to call from multiple goroutines. 128 | func (cache *structTypeCache) lookup(t reflect.Type) (s *structType) { 129 | cache.mutex.RLock() 130 | s = cache.store[t] 131 | cache.mutex.RUnlock() 132 | 133 | if s == nil { 134 | // There's a race confition here where this value may be generated 135 | // multiple times. 136 | // The impact in practice is really small as it's unlikely to happen 137 | // often, we take the approach of keeping the logic simple and avoid 138 | // a more complex synchronization logic required to solve this edge 139 | // case. 140 | s = newStructType(t, map[reflect.Type]*structType{}) 141 | cache.mutex.Lock() 142 | cache.store[t] = s 143 | cache.mutex.Unlock() 144 | } 145 | 146 | return 147 | } 148 | 149 | // clear empties the cache. 150 | func (cache *structTypeCache) clear() { 151 | cache.mutex.Lock() 152 | for typ := range cache.store { 153 | delete(cache.store, typ) 154 | } 155 | cache.mutex.Unlock() 156 | } 157 | 158 | var ( 159 | // This struct cache is used to avoid reusing reflection over and over when 160 | // the objconv functions are called. The performance improvements on iterating 161 | // over struct fields are huge, this is a really important optimization: 162 | structCache = structTypeCache{ 163 | store: make(map[reflect.Type]*structType), 164 | } 165 | ) 166 | -------------------------------------------------------------------------------- /cbor/emit.go: -------------------------------------------------------------------------------- 1 | package cbor 2 | 3 | import ( 4 | "io" 5 | "math" 6 | "reflect" 7 | "time" 8 | "unsafe" 9 | 10 | "github.com/segmentio/objconv/objutil" 11 | ) 12 | 13 | // Emitter implements a MessagePack emitter that satisfies the objconv.Emitter 14 | // interface. 15 | type Emitter struct { 16 | w io.Writer 17 | b [16]byte 18 | 19 | // This stack is used to keep track of the array map lengths being parsed. 20 | // The sback array is the initial backend array for the stack. 21 | stack []int 22 | sback [16]int 23 | } 24 | 25 | func NewEmitter(w io.Writer) *Emitter { 26 | e := &Emitter{w: w} 27 | e.stack = e.sback[:0] 28 | return e 29 | } 30 | 31 | func (e *Emitter) Reset(w io.Writer) { 32 | e.w = w 33 | e.stack = e.stack[:0] 34 | } 35 | 36 | func (e *Emitter) EmitNil() (err error) { 37 | e.b[0] = majorByte(majorType7, svNull) 38 | _, err = e.w.Write(e.b[:1]) 39 | return 40 | } 41 | 42 | func (e *Emitter) EmitBool(v bool) (err error) { 43 | if v { 44 | e.b[0] = majorByte(majorType7, svTrue) 45 | } else { 46 | e.b[0] = majorByte(majorType7, svFalse) 47 | } 48 | _, err = e.w.Write(e.b[:1]) 49 | return 50 | } 51 | 52 | func (e *Emitter) EmitInt(v int64, _ int) (err error) { 53 | if v >= 0 { 54 | return e.emitUint(majorType0, uint64(v)) 55 | } 56 | return e.emitUint(majorType1, uint64(-(v + 1))) 57 | } 58 | 59 | func (e *Emitter) EmitUint(v uint64, _ int) (err error) { 60 | return e.emitUint(majorType0, v) 61 | } 62 | 63 | func (e *Emitter) EmitFloat(v float64, bitSize int) (err error) { 64 | n := 0 65 | 66 | if bitSize == 32 { 67 | n = 5 68 | e.b[0] = majorByte(majorType7, svFloat32) 69 | putUint32(e.b[1:], math.Float32bits(float32(v))) 70 | } else { 71 | n = 9 72 | e.b[0] = majorByte(majorType7, svFloat64) 73 | putUint64(e.b[1:], math.Float64bits(v)) 74 | } 75 | 76 | _, err = e.w.Write(e.b[:n]) 77 | return 78 | } 79 | 80 | func (e *Emitter) EmitString(v string) (err error) { 81 | if err = e.emitUint(majorType3, uint64(len(v))); err != nil { 82 | return 83 | } 84 | s := *(*reflect.StringHeader)(unsafe.Pointer(&v)) 85 | b := reflect.SliceHeader{ 86 | Data: s.Data, 87 | Len: s.Len, 88 | Cap: s.Len, 89 | } 90 | _, err = e.w.Write(*((*[]byte)(unsafe.Pointer(&b)))) 91 | return 92 | } 93 | 94 | func (e *Emitter) EmitBytes(v []byte) (err error) { 95 | if err = e.emitUint(majorType2, uint64(len(v))); err != nil { 96 | return 97 | } 98 | if len(v) != 0 { 99 | _, err = e.w.Write(v) 100 | } 101 | return 102 | } 103 | 104 | func (e *Emitter) EmitTime(v time.Time) (err error) { 105 | e.b[0] = majorByte(majorType6, tagDateTime) 106 | 107 | if _, err = e.w.Write(e.b[:1]); err != nil { 108 | return 109 | } 110 | 111 | var a [64]byte 112 | var b = v.AppendFormat(a[:0], time.RFC3339Nano) 113 | 114 | if err = e.emitUint(majorType3, uint64(len(b))); err != nil { 115 | return 116 | } 117 | 118 | _, err = e.w.Write(append(e.b[:0], b...)) 119 | return 120 | } 121 | 122 | func (e *Emitter) EmitDuration(v time.Duration) (err error) { 123 | return e.EmitString(string(objutil.AppendDuration(e.b[:0], v))) 124 | } 125 | 126 | func (e *Emitter) EmitError(v error) (err error) { 127 | return e.EmitString(v.Error()) 128 | } 129 | 130 | func (e *Emitter) EmitArrayBegin(n int) (err error) { 131 | e.stack = append(e.stack, n) 132 | 133 | if n >= 0 { 134 | return e.emitUint(majorType4, uint64(n)) 135 | } 136 | 137 | e.b[0] = majorByte(majorType4, 31) 138 | _, err = e.w.Write(e.b[:1]) 139 | return 140 | } 141 | 142 | func (e *Emitter) EmitArrayEnd() (err error) { 143 | i := len(e.stack) - 1 144 | n := e.stack[i] 145 | e.stack = e.stack[:i] 146 | 147 | if n < 0 { 148 | e.b[0] = 0xFF 149 | _, err = e.w.Write(e.b[:1]) 150 | } 151 | return 152 | } 153 | 154 | func (e *Emitter) EmitArrayNext() (err error) { 155 | return 156 | } 157 | 158 | func (e *Emitter) EmitMapBegin(n int) (err error) { 159 | e.stack = append(e.stack, n) 160 | 161 | if n >= 0 { 162 | return e.emitUint(majorType5, uint64(n)) 163 | } 164 | 165 | e.b[0] = majorByte(majorType5, 31) 166 | _, err = e.w.Write(e.b[:1]) 167 | return 168 | } 169 | 170 | func (e *Emitter) EmitMapEnd() (err error) { 171 | i := len(e.stack) - 1 172 | n := e.stack[i] 173 | e.stack = e.stack[:i] 174 | 175 | if n < 0 { 176 | e.b[0] = 0xFF 177 | _, err = e.w.Write(e.b[:1]) 178 | } 179 | return 180 | } 181 | 182 | func (e *Emitter) EmitMapValue() (err error) { 183 | return 184 | } 185 | 186 | func (e *Emitter) EmitMapNext() (err error) { 187 | return 188 | } 189 | 190 | func (e *Emitter) emitUint(m byte, v uint64) (err error) { 191 | var n int 192 | 193 | switch { 194 | case v <= 23: 195 | n = 1 196 | e.b[0] = majorByte(m, byte(v)) 197 | 198 | case v <= objutil.Uint8Max: 199 | n = 2 200 | e.b[0] = majorByte(m, iUint8) 201 | e.b[1] = uint8(v) 202 | 203 | case v <= objutil.Uint16Max: 204 | n = 3 205 | e.b[0] = majorByte(m, iUint16) 206 | putUint16(e.b[1:], uint16(v)) 207 | 208 | case v <= objutil.Uint32Max: 209 | n = 5 210 | e.b[0] = majorByte(m, iUint32) 211 | putUint32(e.b[1:], uint32(v)) 212 | 213 | default: 214 | n = 9 215 | e.b[0] = majorByte(m, iUint64) 216 | putUint64(e.b[1:], v) 217 | } 218 | 219 | _, err = e.w.Write(e.b[:n]) 220 | return 221 | } 222 | -------------------------------------------------------------------------------- /parse.go: -------------------------------------------------------------------------------- 1 | package objconv 2 | 3 | import "time" 4 | 5 | // The Parser interface must be implemented by types that provide decoding of a 6 | // specific format (like json, resp, ...). 7 | // 8 | // Parsers are not expected to be safe for use by multiple goroutines. 9 | type Parser interface { 10 | // ParseType is called by a decoder to ask the parser what is the type of 11 | // the next value that can be parsed. 12 | // 13 | // ParseType must be idempotent, it must be possible to call it multiple 14 | // without actually changing the state of the parser. 15 | ParseType() (Type, error) 16 | 17 | // ParseNil parses a nil value. 18 | ParseNil() error 19 | 20 | // ParseBool parses a boolean value. 21 | ParseBool() (bool, error) 22 | 23 | // ParseInt parses an integer value. 24 | ParseInt() (int64, error) 25 | 26 | // ParseUint parses an unsigned integer value. 27 | ParseUint() (uint64, error) 28 | 29 | // ParseFloat parses a floating point value. 30 | ParseFloat() (float64, error) 31 | 32 | // ParseString parses a string value. 33 | // 34 | // The string is returned as a byte slice because it is expected to be 35 | // pointing at an internal memory buffer, the decoder will make a copy of 36 | // the value. This design allows more memory allocation optimizations. 37 | ParseString() ([]byte, error) 38 | 39 | // ParseBytes parses a byte array value. 40 | // 41 | // The returned byte slice is expected to be pointing at an internal memory 42 | // buffer, the decoder will make a copy of the value. This design allows more 43 | // memory allocation optimizations. 44 | ParseBytes() ([]byte, error) 45 | 46 | // ParseTime parses a time value. 47 | ParseTime() (time.Time, error) 48 | 49 | // ParseDuration parses a duration value. 50 | ParseDuration() (time.Duration, error) 51 | 52 | // ParseError parses an error value. 53 | ParseError() (error, error) 54 | 55 | // ParseArrayBegin is called by the array-decoding algorithm when it starts. 56 | // 57 | // The method should return the length of the array being decoded, or a 58 | // negative value if it is unknown (some formats like json don't keep track 59 | // of the length of the array). 60 | ParseArrayBegin() (int, error) 61 | 62 | // ParseArrayEnd is called by the array-decoding algorithm when it 63 | // completes. 64 | // 65 | // The method receives the iteration counter as argument, which indicates 66 | // how many values were decoded from the array. 67 | ParseArrayEnd(int) error 68 | 69 | // ParseArrayNext is called by the array-decoding algorithm between each 70 | // value parsed in the array. 71 | // 72 | // The method receives the iteration counter as argument, which indicates 73 | // how many values were decoded from the array. 74 | // 75 | // If the ParseArrayBegin method returned a negative value this method 76 | // should return objconv.End to indicated that there is no more elements to 77 | // parse in the array. In this case the method is also called right before 78 | // decoding the first element ot handle the case where the array is empty 79 | // and the end-of-array marker can be read right away. 80 | ParseArrayNext(int) error 81 | 82 | // ParseMapBegin is called by the map-decoding algorithm when it starts. 83 | // 84 | // The method should return the length of the map being decoded, or a 85 | // negative value if it is unknown (some formats like json don't keep track 86 | // of the length of the map). 87 | ParseMapBegin() (int, error) 88 | 89 | // ParseMapEnd is called by the map-decoding algorithm when it completes. 90 | // 91 | // The method receives the iteration counter as argument, which indicates 92 | // how many values were decoded from the map. 93 | ParseMapEnd(int) error 94 | 95 | // ParseMapValue is called by the map-decoding algorithm after parsing a key 96 | // but before parsing the associated value. 97 | // 98 | // The method receives the iteration counter as argument, which indicates 99 | // how many values were decoded from the map. 100 | ParseMapValue(int) error 101 | 102 | // ParseMapNext is called by the map-decoding algorithm between each 103 | // value parsed in the map. 104 | // 105 | // The method receives the iteration counter as argument, which indicates 106 | // how many values were decoded from the map. 107 | // 108 | // If the ParseMapBegin method returned a negative value this method should 109 | // return objconv.End to indicated that there is no more elements to parse 110 | // in the map. In this case the method is also called right before decoding 111 | // the first element ot handle the case where the array is empty and the 112 | // end-of-map marker can be read right away. 113 | ParseMapNext(int) error 114 | } 115 | 116 | // The bytesDecoder interface may optionnaly be implemented by a Parser to 117 | // provide an extra step in decoding a byte slice. This is sometimes necessary 118 | // if the associated Emitter has transformed bytes slices because the format is 119 | // not capable of representing binary data. 120 | type bytesDecoder interface { 121 | // DecodeBytes is called when the destination variable for a string or a 122 | // byte slice is a byte slice, allowing the parser to apply a transformation 123 | // before the value is stored. 124 | DecodeBytes([]byte) ([]byte, error) 125 | } 126 | 127 | // The textParser interface may be implemented by parsers of human-readable 128 | // formats. Such parsers instruct the encoder to prefer using 129 | // encoding.TextUnmarshaler over encoding.BinaryUnmarshaler for example. 130 | type textParser interface { 131 | // EmitsText returns true if the parser produces a human-readable format. 132 | TextParser() bool 133 | } 134 | 135 | func isTextParser(parser Parser) bool { 136 | p, _ := parser.(textParser) 137 | return p != nil && p.TextParser() 138 | } 139 | -------------------------------------------------------------------------------- /yaml/vendor/gopkg.in/yaml.v2/yamlprivateh.go: -------------------------------------------------------------------------------- 1 | package yaml 2 | 3 | const ( 4 | // The size of the input raw buffer. 5 | input_raw_buffer_size = 512 6 | 7 | // The size of the input buffer. 8 | // It should be possible to decode the whole raw buffer. 9 | input_buffer_size = input_raw_buffer_size * 3 10 | 11 | // The size of the output buffer. 12 | output_buffer_size = 128 13 | 14 | // The size of the output raw buffer. 15 | // It should be possible to encode the whole output buffer. 16 | output_raw_buffer_size = (output_buffer_size*2 + 2) 17 | 18 | // The size of other stacks and queues. 19 | initial_stack_size = 16 20 | initial_queue_size = 16 21 | initial_string_size = 16 22 | ) 23 | 24 | // Check if the character at the specified position is an alphabetical 25 | // character, a digit, '_', or '-'. 26 | func is_alpha(b []byte, i int) bool { 27 | return b[i] >= '0' && b[i] <= '9' || b[i] >= 'A' && b[i] <= 'Z' || b[i] >= 'a' && b[i] <= 'z' || b[i] == '_' || b[i] == '-' 28 | } 29 | 30 | // Check if the character at the specified position is a digit. 31 | func is_digit(b []byte, i int) bool { 32 | return b[i] >= '0' && b[i] <= '9' 33 | } 34 | 35 | // Get the value of a digit. 36 | func as_digit(b []byte, i int) int { 37 | return int(b[i]) - '0' 38 | } 39 | 40 | // Check if the character at the specified position is a hex-digit. 41 | func is_hex(b []byte, i int) bool { 42 | return b[i] >= '0' && b[i] <= '9' || b[i] >= 'A' && b[i] <= 'F' || b[i] >= 'a' && b[i] <= 'f' 43 | } 44 | 45 | // Get the value of a hex-digit. 46 | func as_hex(b []byte, i int) int { 47 | bi := b[i] 48 | if bi >= 'A' && bi <= 'F' { 49 | return int(bi) - 'A' + 10 50 | } 51 | if bi >= 'a' && bi <= 'f' { 52 | return int(bi) - 'a' + 10 53 | } 54 | return int(bi) - '0' 55 | } 56 | 57 | // Check if the character is ASCII. 58 | func is_ascii(b []byte, i int) bool { 59 | return b[i] <= 0x7F 60 | } 61 | 62 | // Check if the character at the start of the buffer can be printed unescaped. 63 | func is_printable(b []byte, i int) bool { 64 | return ((b[i] == 0x0A) || // . == #x0A 65 | (b[i] >= 0x20 && b[i] <= 0x7E) || // #x20 <= . <= #x7E 66 | (b[i] == 0xC2 && b[i+1] >= 0xA0) || // #0xA0 <= . <= #xD7FF 67 | (b[i] > 0xC2 && b[i] < 0xED) || 68 | (b[i] == 0xED && b[i+1] < 0xA0) || 69 | (b[i] == 0xEE) || 70 | (b[i] == 0xEF && // #xE000 <= . <= #xFFFD 71 | !(b[i+1] == 0xBB && b[i+2] == 0xBF) && // && . != #xFEFF 72 | !(b[i+1] == 0xBF && (b[i+2] == 0xBE || b[i+2] == 0xBF)))) 73 | } 74 | 75 | // Check if the character at the specified position is NUL. 76 | func is_z(b []byte, i int) bool { 77 | return b[i] == 0x00 78 | } 79 | 80 | // Check if the beginning of the buffer is a BOM. 81 | func is_bom(b []byte, i int) bool { 82 | return b[0] == 0xEF && b[1] == 0xBB && b[2] == 0xBF 83 | } 84 | 85 | // Check if the character at the specified position is space. 86 | func is_space(b []byte, i int) bool { 87 | return b[i] == ' ' 88 | } 89 | 90 | // Check if the character at the specified position is tab. 91 | func is_tab(b []byte, i int) bool { 92 | return b[i] == '\t' 93 | } 94 | 95 | // Check if the character at the specified position is blank (space or tab). 96 | func is_blank(b []byte, i int) bool { 97 | //return is_space(b, i) || is_tab(b, i) 98 | return b[i] == ' ' || b[i] == '\t' 99 | } 100 | 101 | // Check if the character at the specified position is a line break. 102 | func is_break(b []byte, i int) bool { 103 | return (b[i] == '\r' || // CR (#xD) 104 | b[i] == '\n' || // LF (#xA) 105 | b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85) 106 | b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028) 107 | b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9) // PS (#x2029) 108 | } 109 | 110 | func is_crlf(b []byte, i int) bool { 111 | return b[i] == '\r' && b[i+1] == '\n' 112 | } 113 | 114 | // Check if the character is a line break or NUL. 115 | func is_breakz(b []byte, i int) bool { 116 | //return is_break(b, i) || is_z(b, i) 117 | return ( // is_break: 118 | b[i] == '\r' || // CR (#xD) 119 | b[i] == '\n' || // LF (#xA) 120 | b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85) 121 | b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028) 122 | b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029) 123 | // is_z: 124 | b[i] == 0) 125 | } 126 | 127 | // Check if the character is a line break, space, or NUL. 128 | func is_spacez(b []byte, i int) bool { 129 | //return is_space(b, i) || is_breakz(b, i) 130 | return ( // is_space: 131 | b[i] == ' ' || 132 | // is_breakz: 133 | b[i] == '\r' || // CR (#xD) 134 | b[i] == '\n' || // LF (#xA) 135 | b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85) 136 | b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028) 137 | b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029) 138 | b[i] == 0) 139 | } 140 | 141 | // Check if the character is a line break, space, tab, or NUL. 142 | func is_blankz(b []byte, i int) bool { 143 | //return is_blank(b, i) || is_breakz(b, i) 144 | return ( // is_blank: 145 | b[i] == ' ' || b[i] == '\t' || 146 | // is_breakz: 147 | b[i] == '\r' || // CR (#xD) 148 | b[i] == '\n' || // LF (#xA) 149 | b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85) 150 | b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028) 151 | b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029) 152 | b[i] == 0) 153 | } 154 | 155 | // Determine the width of the character. 156 | func width(b byte) int { 157 | // Don't replace these by a switch without first 158 | // confirming that it is being inlined. 159 | if b&0x80 == 0x00 { 160 | return 1 161 | } 162 | if b&0xE0 == 0xC0 { 163 | return 2 164 | } 165 | if b&0xF0 == 0xE0 { 166 | return 3 167 | } 168 | if b&0xF8 == 0xF0 { 169 | return 4 170 | } 171 | return 0 172 | 173 | } 174 | -------------------------------------------------------------------------------- /yaml/vendor/gopkg.in/yaml.v2/resolve.go: -------------------------------------------------------------------------------- 1 | package yaml 2 | 3 | import ( 4 | "encoding/base64" 5 | "math" 6 | "strconv" 7 | "strings" 8 | "unicode/utf8" 9 | ) 10 | 11 | type resolveMapItem struct { 12 | value interface{} 13 | tag string 14 | } 15 | 16 | var resolveTable = make([]byte, 256) 17 | var resolveMap = make(map[string]resolveMapItem) 18 | 19 | func init() { 20 | t := resolveTable 21 | t[int('+')] = 'S' // Sign 22 | t[int('-')] = 'S' 23 | for _, c := range "0123456789" { 24 | t[int(c)] = 'D' // Digit 25 | } 26 | for _, c := range "yYnNtTfFoO~" { 27 | t[int(c)] = 'M' // In map 28 | } 29 | t[int('.')] = '.' // Float (potentially in map) 30 | 31 | var resolveMapList = []struct { 32 | v interface{} 33 | tag string 34 | l []string 35 | }{ 36 | {true, yaml_BOOL_TAG, []string{"y", "Y", "yes", "Yes", "YES"}}, 37 | {true, yaml_BOOL_TAG, []string{"true", "True", "TRUE"}}, 38 | {true, yaml_BOOL_TAG, []string{"on", "On", "ON"}}, 39 | {false, yaml_BOOL_TAG, []string{"n", "N", "no", "No", "NO"}}, 40 | {false, yaml_BOOL_TAG, []string{"false", "False", "FALSE"}}, 41 | {false, yaml_BOOL_TAG, []string{"off", "Off", "OFF"}}, 42 | {nil, yaml_NULL_TAG, []string{"", "~", "null", "Null", "NULL"}}, 43 | {math.NaN(), yaml_FLOAT_TAG, []string{".nan", ".NaN", ".NAN"}}, 44 | {math.Inf(+1), yaml_FLOAT_TAG, []string{".inf", ".Inf", ".INF"}}, 45 | {math.Inf(+1), yaml_FLOAT_TAG, []string{"+.inf", "+.Inf", "+.INF"}}, 46 | {math.Inf(-1), yaml_FLOAT_TAG, []string{"-.inf", "-.Inf", "-.INF"}}, 47 | {"<<", yaml_MERGE_TAG, []string{"<<"}}, 48 | } 49 | 50 | m := resolveMap 51 | for _, item := range resolveMapList { 52 | for _, s := range item.l { 53 | m[s] = resolveMapItem{item.v, item.tag} 54 | } 55 | } 56 | } 57 | 58 | const longTagPrefix = "tag:yaml.org,2002:" 59 | 60 | func shortTag(tag string) string { 61 | // TODO This can easily be made faster and produce less garbage. 62 | if strings.HasPrefix(tag, longTagPrefix) { 63 | return "!!" + tag[len(longTagPrefix):] 64 | } 65 | return tag 66 | } 67 | 68 | func longTag(tag string) string { 69 | if strings.HasPrefix(tag, "!!") { 70 | return longTagPrefix + tag[2:] 71 | } 72 | return tag 73 | } 74 | 75 | func resolvableTag(tag string) bool { 76 | switch tag { 77 | case "", yaml_STR_TAG, yaml_BOOL_TAG, yaml_INT_TAG, yaml_FLOAT_TAG, yaml_NULL_TAG: 78 | return true 79 | } 80 | return false 81 | } 82 | 83 | func resolve(tag string, in string) (rtag string, out interface{}) { 84 | if !resolvableTag(tag) { 85 | return tag, in 86 | } 87 | 88 | defer func() { 89 | switch tag { 90 | case "", rtag, yaml_STR_TAG, yaml_BINARY_TAG: 91 | return 92 | } 93 | failf("cannot decode %s `%s` as a %s", shortTag(rtag), in, shortTag(tag)) 94 | }() 95 | 96 | // Any data is accepted as a !!str or !!binary. 97 | // Otherwise, the prefix is enough of a hint about what it might be. 98 | hint := byte('N') 99 | if in != "" { 100 | hint = resolveTable[in[0]] 101 | } 102 | if hint != 0 && tag != yaml_STR_TAG && tag != yaml_BINARY_TAG { 103 | // Handle things we can lookup in a map. 104 | if item, ok := resolveMap[in]; ok { 105 | return item.tag, item.value 106 | } 107 | 108 | // Base 60 floats are a bad idea, were dropped in YAML 1.2, and 109 | // are purposefully unsupported here. They're still quoted on 110 | // the way out for compatibility with other parser, though. 111 | 112 | switch hint { 113 | case 'M': 114 | // We've already checked the map above. 115 | 116 | case '.': 117 | // Not in the map, so maybe a normal float. 118 | floatv, err := strconv.ParseFloat(in, 64) 119 | if err == nil { 120 | return yaml_FLOAT_TAG, floatv 121 | } 122 | 123 | case 'D', 'S': 124 | // Int, float, or timestamp. 125 | plain := strings.Replace(in, "_", "", -1) 126 | intv, err := strconv.ParseInt(plain, 0, 64) 127 | if err == nil { 128 | if intv == int64(int(intv)) { 129 | return yaml_INT_TAG, int(intv) 130 | } else { 131 | return yaml_INT_TAG, intv 132 | } 133 | } 134 | uintv, err := strconv.ParseUint(plain, 0, 64) 135 | if err == nil { 136 | return yaml_INT_TAG, uintv 137 | } 138 | floatv, err := strconv.ParseFloat(plain, 64) 139 | if err == nil { 140 | return yaml_FLOAT_TAG, floatv 141 | } 142 | if strings.HasPrefix(plain, "0b") { 143 | intv, err := strconv.ParseInt(plain[2:], 2, 64) 144 | if err == nil { 145 | if intv == int64(int(intv)) { 146 | return yaml_INT_TAG, int(intv) 147 | } else { 148 | return yaml_INT_TAG, intv 149 | } 150 | } 151 | uintv, err := strconv.ParseUint(plain[2:], 2, 64) 152 | if err == nil { 153 | return yaml_INT_TAG, uintv 154 | } 155 | } else if strings.HasPrefix(plain, "-0b") { 156 | intv, err := strconv.ParseInt(plain[3:], 2, 64) 157 | if err == nil { 158 | if intv == int64(int(intv)) { 159 | return yaml_INT_TAG, -int(intv) 160 | } else { 161 | return yaml_INT_TAG, -intv 162 | } 163 | } 164 | } 165 | // XXX Handle timestamps here. 166 | 167 | default: 168 | panic("resolveTable item not yet handled: " + string(rune(hint)) + " (with " + in + ")") 169 | } 170 | } 171 | if tag == yaml_BINARY_TAG { 172 | return yaml_BINARY_TAG, in 173 | } 174 | if utf8.ValidString(in) { 175 | return yaml_STR_TAG, in 176 | } 177 | return yaml_BINARY_TAG, encodeBase64(in) 178 | } 179 | 180 | // encodeBase64 encodes s as base64 that is broken up into multiple lines 181 | // as appropriate for the resulting length. 182 | func encodeBase64(s string) string { 183 | const lineLen = 70 184 | encLen := base64.StdEncoding.EncodedLen(len(s)) 185 | lines := encLen/lineLen + 1 186 | buf := make([]byte, encLen*2+lines) 187 | in := buf[0:encLen] 188 | out := buf[encLen:] 189 | base64.StdEncoding.Encode(in, []byte(s)) 190 | k := 0 191 | for i := 0; i < len(in); i += lineLen { 192 | j := i + lineLen 193 | if j > len(in) { 194 | j = len(in) 195 | } 196 | k += copy(out[k:], in[i:j]) 197 | if lines > 1 { 198 | out[k] = '\n' 199 | k++ 200 | } 201 | } 202 | return string(out[:k]) 203 | } 204 | -------------------------------------------------------------------------------- /yaml/vendor/gopkg.in/check.v1/benchmark.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012 The Go Authors. All rights reserved. 2 | // 3 | // Redistribution and use in source and binary forms, with or without 4 | // modification, are permitted provided that the following conditions are 5 | // met: 6 | // 7 | // * Redistributions of source code must retain the above copyright 8 | // notice, this list of conditions and the following disclaimer. 9 | // * Redistributions in binary form must reproduce the above 10 | // copyright notice, this list of conditions and the following disclaimer 11 | // in the documentation and/or other materials provided with the 12 | // distribution. 13 | // * Neither the name of Google Inc. nor the names of its 14 | // contributors may be used to endorse or promote products derived from 15 | // this software without specific prior written permission. 16 | // 17 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | package check 30 | 31 | import ( 32 | "fmt" 33 | "runtime" 34 | "time" 35 | ) 36 | 37 | var memStats runtime.MemStats 38 | 39 | // testingB is a type passed to Benchmark functions to manage benchmark 40 | // timing and to specify the number of iterations to run. 41 | type timer struct { 42 | start time.Time // Time test or benchmark started 43 | duration time.Duration 44 | N int 45 | bytes int64 46 | timerOn bool 47 | benchTime time.Duration 48 | // The initial states of memStats.Mallocs and memStats.TotalAlloc. 49 | startAllocs uint64 50 | startBytes uint64 51 | // The net total of this test after being run. 52 | netAllocs uint64 53 | netBytes uint64 54 | } 55 | 56 | // StartTimer starts timing a test. This function is called automatically 57 | // before a benchmark starts, but it can also used to resume timing after 58 | // a call to StopTimer. 59 | func (c *C) StartTimer() { 60 | if !c.timerOn { 61 | c.start = time.Now() 62 | c.timerOn = true 63 | 64 | runtime.ReadMemStats(&memStats) 65 | c.startAllocs = memStats.Mallocs 66 | c.startBytes = memStats.TotalAlloc 67 | } 68 | } 69 | 70 | // StopTimer stops timing a test. This can be used to pause the timer 71 | // while performing complex initialization that you don't 72 | // want to measure. 73 | func (c *C) StopTimer() { 74 | if c.timerOn { 75 | c.duration += time.Now().Sub(c.start) 76 | c.timerOn = false 77 | runtime.ReadMemStats(&memStats) 78 | c.netAllocs += memStats.Mallocs - c.startAllocs 79 | c.netBytes += memStats.TotalAlloc - c.startBytes 80 | } 81 | } 82 | 83 | // ResetTimer sets the elapsed benchmark time to zero. 84 | // It does not affect whether the timer is running. 85 | func (c *C) ResetTimer() { 86 | if c.timerOn { 87 | c.start = time.Now() 88 | runtime.ReadMemStats(&memStats) 89 | c.startAllocs = memStats.Mallocs 90 | c.startBytes = memStats.TotalAlloc 91 | } 92 | c.duration = 0 93 | c.netAllocs = 0 94 | c.netBytes = 0 95 | } 96 | 97 | // SetBytes informs the number of bytes that the benchmark processes 98 | // on each iteration. If this is called in a benchmark it will also 99 | // report MB/s. 100 | func (c *C) SetBytes(n int64) { 101 | c.bytes = n 102 | } 103 | 104 | func (c *C) nsPerOp() int64 { 105 | if c.N <= 0 { 106 | return 0 107 | } 108 | return c.duration.Nanoseconds() / int64(c.N) 109 | } 110 | 111 | func (c *C) mbPerSec() float64 { 112 | if c.bytes <= 0 || c.duration <= 0 || c.N <= 0 { 113 | return 0 114 | } 115 | return (float64(c.bytes) * float64(c.N) / 1e6) / c.duration.Seconds() 116 | } 117 | 118 | func (c *C) timerString() string { 119 | if c.N <= 0 { 120 | return fmt.Sprintf("%3.3fs", float64(c.duration.Nanoseconds())/1e9) 121 | } 122 | mbs := c.mbPerSec() 123 | mb := "" 124 | if mbs != 0 { 125 | mb = fmt.Sprintf("\t%7.2f MB/s", mbs) 126 | } 127 | nsop := c.nsPerOp() 128 | ns := fmt.Sprintf("%10d ns/op", nsop) 129 | if c.N > 0 && nsop < 100 { 130 | // The format specifiers here make sure that 131 | // the ones digits line up for all three possible formats. 132 | if nsop < 10 { 133 | ns = fmt.Sprintf("%13.2f ns/op", float64(c.duration.Nanoseconds())/float64(c.N)) 134 | } else { 135 | ns = fmt.Sprintf("%12.1f ns/op", float64(c.duration.Nanoseconds())/float64(c.N)) 136 | } 137 | } 138 | memStats := "" 139 | if c.benchMem { 140 | allocedBytes := fmt.Sprintf("%8d B/op", int64(c.netBytes)/int64(c.N)) 141 | allocs := fmt.Sprintf("%8d allocs/op", int64(c.netAllocs)/int64(c.N)) 142 | memStats = fmt.Sprintf("\t%s\t%s", allocedBytes, allocs) 143 | } 144 | return fmt.Sprintf("%8d\t%s%s%s", c.N, ns, mb, memStats) 145 | } 146 | 147 | func min(x, y int) int { 148 | if x > y { 149 | return y 150 | } 151 | return x 152 | } 153 | 154 | func max(x, y int) int { 155 | if x < y { 156 | return y 157 | } 158 | return x 159 | } 160 | 161 | // roundDown10 rounds a number down to the nearest power of 10. 162 | func roundDown10(n int) int { 163 | var tens = 0 164 | // tens = floor(log_10(n)) 165 | for n > 10 { 166 | n = n / 10 167 | tens++ 168 | } 169 | // result = 10^tens 170 | result := 1 171 | for i := 0; i < tens; i++ { 172 | result *= 10 173 | } 174 | return result 175 | } 176 | 177 | // roundUp rounds x up to a number of the form [1eX, 2eX, 5eX]. 178 | func roundUp(n int) int { 179 | base := roundDown10(n) 180 | if n < (2 * base) { 181 | return 2 * base 182 | } 183 | if n < (5 * base) { 184 | return 5 * base 185 | } 186 | return 10 * base 187 | } 188 | -------------------------------------------------------------------------------- /yaml/vendor/gopkg.in/check.v1/check_test.go: -------------------------------------------------------------------------------- 1 | // This file contains just a few generic helpers which are used by the 2 | // other test files. 3 | 4 | package check_test 5 | 6 | import ( 7 | "flag" 8 | "fmt" 9 | "os" 10 | "regexp" 11 | "runtime" 12 | "testing" 13 | "time" 14 | 15 | "gopkg.in/check.v1" 16 | ) 17 | 18 | // We count the number of suites run at least to get a vague hint that the 19 | // test suite is behaving as it should. Otherwise a bug introduced at the 20 | // very core of the system could go unperceived. 21 | const suitesRunExpected = 8 22 | 23 | var suitesRun int = 0 24 | 25 | func Test(t *testing.T) { 26 | check.TestingT(t) 27 | if suitesRun != suitesRunExpected && flag.Lookup("check.f").Value.String() == "" { 28 | critical(fmt.Sprintf("Expected %d suites to run rather than %d", 29 | suitesRunExpected, suitesRun)) 30 | } 31 | } 32 | 33 | // ----------------------------------------------------------------------- 34 | // Helper functions. 35 | 36 | // Break down badly. This is used in test cases which can't yet assume 37 | // that the fundamental bits are working. 38 | func critical(error string) { 39 | fmt.Fprintln(os.Stderr, "CRITICAL: "+error) 40 | os.Exit(1) 41 | } 42 | 43 | // Return the file line where it's called. 44 | func getMyLine() int { 45 | if _, _, line, ok := runtime.Caller(1); ok { 46 | return line 47 | } 48 | return -1 49 | } 50 | 51 | // ----------------------------------------------------------------------- 52 | // Helper type implementing a basic io.Writer for testing output. 53 | 54 | // Type implementing the io.Writer interface for analyzing output. 55 | type String struct { 56 | value string 57 | } 58 | 59 | // The only function required by the io.Writer interface. Will append 60 | // written data to the String.value string. 61 | func (s *String) Write(p []byte) (n int, err error) { 62 | s.value += string(p) 63 | return len(p), nil 64 | } 65 | 66 | // Trivial wrapper to test errors happening on a different file 67 | // than the test itself. 68 | func checkEqualWrapper(c *check.C, obtained, expected interface{}) (result bool, line int) { 69 | return c.Check(obtained, check.Equals, expected), getMyLine() 70 | } 71 | 72 | // ----------------------------------------------------------------------- 73 | // Helper suite for testing basic fail behavior. 74 | 75 | type FailHelper struct { 76 | testLine int 77 | } 78 | 79 | func (s *FailHelper) TestLogAndFail(c *check.C) { 80 | s.testLine = getMyLine() - 1 81 | c.Log("Expected failure!") 82 | c.Fail() 83 | } 84 | 85 | // ----------------------------------------------------------------------- 86 | // Helper suite for testing basic success behavior. 87 | 88 | type SuccessHelper struct{} 89 | 90 | func (s *SuccessHelper) TestLogAndSucceed(c *check.C) { 91 | c.Log("Expected success!") 92 | } 93 | 94 | // ----------------------------------------------------------------------- 95 | // Helper suite for testing ordering and behavior of fixture. 96 | 97 | type FixtureHelper struct { 98 | calls []string 99 | panicOn string 100 | skip bool 101 | skipOnN int 102 | sleepOn string 103 | sleep time.Duration 104 | bytes int64 105 | } 106 | 107 | func (s *FixtureHelper) trace(name string, c *check.C) { 108 | s.calls = append(s.calls, name) 109 | if name == s.panicOn { 110 | panic(name) 111 | } 112 | if s.sleep > 0 && s.sleepOn == name { 113 | time.Sleep(s.sleep) 114 | } 115 | if s.skip && s.skipOnN == len(s.calls)-1 { 116 | c.Skip("skipOnN == n") 117 | } 118 | } 119 | 120 | func (s *FixtureHelper) SetUpSuite(c *check.C) { 121 | s.trace("SetUpSuite", c) 122 | } 123 | 124 | func (s *FixtureHelper) TearDownSuite(c *check.C) { 125 | s.trace("TearDownSuite", c) 126 | } 127 | 128 | func (s *FixtureHelper) SetUpTest(c *check.C) { 129 | s.trace("SetUpTest", c) 130 | } 131 | 132 | func (s *FixtureHelper) TearDownTest(c *check.C) { 133 | s.trace("TearDownTest", c) 134 | } 135 | 136 | func (s *FixtureHelper) Test1(c *check.C) { 137 | s.trace("Test1", c) 138 | } 139 | 140 | func (s *FixtureHelper) Test2(c *check.C) { 141 | s.trace("Test2", c) 142 | } 143 | 144 | func (s *FixtureHelper) Benchmark1(c *check.C) { 145 | s.trace("Benchmark1", c) 146 | for i := 0; i < c.N; i++ { 147 | time.Sleep(s.sleep) 148 | } 149 | } 150 | 151 | func (s *FixtureHelper) Benchmark2(c *check.C) { 152 | s.trace("Benchmark2", c) 153 | c.SetBytes(1024) 154 | for i := 0; i < c.N; i++ { 155 | time.Sleep(s.sleep) 156 | } 157 | } 158 | 159 | func (s *FixtureHelper) Benchmark3(c *check.C) { 160 | var x []int64 161 | s.trace("Benchmark3", c) 162 | for i := 0; i < c.N; i++ { 163 | time.Sleep(s.sleep) 164 | x = make([]int64, 5) 165 | _ = x 166 | } 167 | } 168 | 169 | // ----------------------------------------------------------------------- 170 | // Helper which checks the state of the test and ensures that it matches 171 | // the given expectations. Depends on c.Errorf() working, so shouldn't 172 | // be used to test this one function. 173 | 174 | type expectedState struct { 175 | name string 176 | result interface{} 177 | failed bool 178 | log string 179 | } 180 | 181 | // Verify the state of the test. Note that since this also verifies if 182 | // the test is supposed to be in a failed state, no other checks should 183 | // be done in addition to what is being tested. 184 | func checkState(c *check.C, result interface{}, expected *expectedState) { 185 | failed := c.Failed() 186 | c.Succeed() 187 | log := c.GetTestLog() 188 | matched, matchError := regexp.MatchString("^"+expected.log+"$", log) 189 | if matchError != nil { 190 | c.Errorf("Error in matching expression used in testing %s", 191 | expected.name) 192 | } else if !matched { 193 | c.Errorf("%s logged:\n----------\n%s----------\n\nExpected:\n----------\n%s\n----------", 194 | expected.name, log, expected.log) 195 | } 196 | if result != expected.result { 197 | c.Errorf("%s returned %#v rather than %#v", 198 | expected.name, result, expected.result) 199 | } 200 | if failed != expected.failed { 201 | if failed { 202 | c.Errorf("%s has failed when it shouldn't", expected.name) 203 | } else { 204 | c.Errorf("%s has not failed when it should", expected.name) 205 | } 206 | } 207 | } 208 | -------------------------------------------------------------------------------- /yaml/vendor/gopkg.in/check.v1/run.go: -------------------------------------------------------------------------------- 1 | package check 2 | 3 | import ( 4 | "bufio" 5 | "flag" 6 | "fmt" 7 | "os" 8 | "testing" 9 | "time" 10 | ) 11 | 12 | // ----------------------------------------------------------------------- 13 | // Test suite registry. 14 | 15 | var allSuites []interface{} 16 | 17 | // Suite registers the given value as a test suite to be run. Any methods 18 | // starting with the Test prefix in the given value will be considered as 19 | // a test method. 20 | func Suite(suite interface{}) interface{} { 21 | allSuites = append(allSuites, suite) 22 | return suite 23 | } 24 | 25 | // ----------------------------------------------------------------------- 26 | // Public running interface. 27 | 28 | var ( 29 | oldFilterFlag = flag.String("gocheck.f", "", "Regular expression selecting which tests and/or suites to run") 30 | oldVerboseFlag = flag.Bool("gocheck.v", false, "Verbose mode") 31 | oldStreamFlag = flag.Bool("gocheck.vv", false, "Super verbose mode (disables output caching)") 32 | oldBenchFlag = flag.Bool("gocheck.b", false, "Run benchmarks") 33 | oldBenchTime = flag.Duration("gocheck.btime", 1*time.Second, "approximate run time for each benchmark") 34 | oldListFlag = flag.Bool("gocheck.list", false, "List the names of all tests that will be run") 35 | oldWorkFlag = flag.Bool("gocheck.work", false, "Display and do not remove the test working directory") 36 | 37 | newFilterFlag = flag.String("check.f", "", "Regular expression selecting which tests and/or suites to run") 38 | newVerboseFlag = flag.Bool("check.v", false, "Verbose mode") 39 | newStreamFlag = flag.Bool("check.vv", false, "Super verbose mode (disables output caching)") 40 | newBenchFlag = flag.Bool("check.b", false, "Run benchmarks") 41 | newBenchTime = flag.Duration("check.btime", 1*time.Second, "approximate run time for each benchmark") 42 | newBenchMem = flag.Bool("check.bmem", false, "Report memory benchmarks") 43 | newListFlag = flag.Bool("check.list", false, "List the names of all tests that will be run") 44 | newWorkFlag = flag.Bool("check.work", false, "Display and do not remove the test working directory") 45 | ) 46 | 47 | // TestingT runs all test suites registered with the Suite function, 48 | // printing results to stdout, and reporting any failures back to 49 | // the "testing" package. 50 | func TestingT(testingT *testing.T) { 51 | benchTime := *newBenchTime 52 | if benchTime == 1*time.Second { 53 | benchTime = *oldBenchTime 54 | } 55 | conf := &RunConf{ 56 | Filter: *oldFilterFlag + *newFilterFlag, 57 | Verbose: *oldVerboseFlag || *newVerboseFlag, 58 | Stream: *oldStreamFlag || *newStreamFlag, 59 | Benchmark: *oldBenchFlag || *newBenchFlag, 60 | BenchmarkTime: benchTime, 61 | BenchmarkMem: *newBenchMem, 62 | KeepWorkDir: *oldWorkFlag || *newWorkFlag, 63 | } 64 | if *oldListFlag || *newListFlag { 65 | w := bufio.NewWriter(os.Stdout) 66 | for _, name := range ListAll(conf) { 67 | fmt.Fprintln(w, name) 68 | } 69 | w.Flush() 70 | return 71 | } 72 | result := RunAll(conf) 73 | println(result.String()) 74 | if !result.Passed() { 75 | testingT.Fail() 76 | } 77 | } 78 | 79 | // RunAll runs all test suites registered with the Suite function, using the 80 | // provided run configuration. 81 | func RunAll(runConf *RunConf) *Result { 82 | result := Result{} 83 | for _, suite := range allSuites { 84 | result.Add(Run(suite, runConf)) 85 | } 86 | return &result 87 | } 88 | 89 | // Run runs the provided test suite using the provided run configuration. 90 | func Run(suite interface{}, runConf *RunConf) *Result { 91 | runner := newSuiteRunner(suite, runConf) 92 | return runner.run() 93 | } 94 | 95 | // ListAll returns the names of all the test functions registered with the 96 | // Suite function that will be run with the provided run configuration. 97 | func ListAll(runConf *RunConf) []string { 98 | var names []string 99 | for _, suite := range allSuites { 100 | names = append(names, List(suite, runConf)...) 101 | } 102 | return names 103 | } 104 | 105 | // List returns the names of the test functions in the given 106 | // suite that will be run with the provided run configuration. 107 | func List(suite interface{}, runConf *RunConf) []string { 108 | var names []string 109 | runner := newSuiteRunner(suite, runConf) 110 | for _, t := range runner.tests { 111 | names = append(names, t.String()) 112 | } 113 | return names 114 | } 115 | 116 | // ----------------------------------------------------------------------- 117 | // Result methods. 118 | 119 | func (r *Result) Add(other *Result) { 120 | r.Succeeded += other.Succeeded 121 | r.Skipped += other.Skipped 122 | r.Failed += other.Failed 123 | r.Panicked += other.Panicked 124 | r.FixturePanicked += other.FixturePanicked 125 | r.ExpectedFailures += other.ExpectedFailures 126 | r.Missed += other.Missed 127 | if r.WorkDir != "" && other.WorkDir != "" { 128 | r.WorkDir += ":" + other.WorkDir 129 | } else if other.WorkDir != "" { 130 | r.WorkDir = other.WorkDir 131 | } 132 | } 133 | 134 | func (r *Result) Passed() bool { 135 | return (r.Failed == 0 && r.Panicked == 0 && 136 | r.FixturePanicked == 0 && r.Missed == 0 && 137 | r.RunError == nil) 138 | } 139 | 140 | func (r *Result) String() string { 141 | if r.RunError != nil { 142 | return "ERROR: " + r.RunError.Error() 143 | } 144 | 145 | var value string 146 | if r.Failed == 0 && r.Panicked == 0 && r.FixturePanicked == 0 && 147 | r.Missed == 0 { 148 | value = "OK: " 149 | } else { 150 | value = "OOPS: " 151 | } 152 | value += fmt.Sprintf("%d passed", r.Succeeded) 153 | if r.Skipped != 0 { 154 | value += fmt.Sprintf(", %d skipped", r.Skipped) 155 | } 156 | if r.ExpectedFailures != 0 { 157 | value += fmt.Sprintf(", %d expected failures", r.ExpectedFailures) 158 | } 159 | if r.Failed != 0 { 160 | value += fmt.Sprintf(", %d FAILED", r.Failed) 161 | } 162 | if r.Panicked != 0 { 163 | value += fmt.Sprintf(", %d PANICKED", r.Panicked) 164 | } 165 | if r.FixturePanicked != 0 { 166 | value += fmt.Sprintf(", %d FIXTURE-PANICKED", r.FixturePanicked) 167 | } 168 | if r.Missed != 0 { 169 | value += fmt.Sprintf(", %d MISSED", r.Missed) 170 | } 171 | if r.WorkDir != "" { 172 | value += "\nWORK=" + r.WorkDir 173 | } 174 | return value 175 | } 176 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | objconv [![CircleCI](https://circleci.com/gh/segmentio/objconv.svg?style=shield)](https://circleci.com/gh/segmentio/objconv) [![Go Report Card](https://goreportcard.com/badge/github.com/segmentio/objconv)](https://goreportcard.com/report/github.com/segmentio/objconv) [![GoDoc](https://godoc.org/github.com/segmentio/objconv?status.svg)](https://godoc.org/github.com/segmentio/objconv) 2 | ======= 3 | 4 | This Go package provides the implementation of high performance encoder and 5 | decoders for JSON-like object representations. 6 | 7 | The top-level package exposes the generic types and algorithms for encoding and 8 | decoding values, while each sub-package implements the parser and emitters for 9 | specific types. 10 | 11 | ### Breaking changes introduced in [#18](https://github.com/segmentio/objconv/pull/18) 12 | 13 | The `Encoder` type used to have methods exposed to encode specific types for 14 | optimization purposes. The generic `Encode` method has been optimized to make 15 | those other methods obsolete and they were therefore removed. 16 | 17 | Compatibility with the standard library 18 | --------------------------------------- 19 | 20 | The sub-packages providing implementation for specific formats also expose APIs 21 | that mirror those of the standard library to make it easy to integrate with the 22 | objconv package. However there are a couple of differences that need to be taken 23 | in consideration: 24 | 25 | - Encoder and Decoder types are not exposed in the objconv sub-packages, instead 26 | the types from the top-level package are used. For example, variables declared 27 | with the `json.Encoder` type would have to be replaced with `objconv.Encoder`. 28 | 29 | - Interfaces like `json.Marshaler` or `json.Unmarshaler` are not supported. 30 | However the `encoding.TextMarshaler` and `encoding.TextUnmarshaler` interfaces 31 | are. 32 | 33 | Encoder 34 | ------- 35 | 36 | The package exposes a generic encoder API that let's the program serialize 37 | native values into various formats. 38 | 39 | Here's an example of how to serialize a structure to JSON: 40 | ```go 41 | package main 42 | 43 | import ( 44 | "os" 45 | 46 | "github.com/segmentio/objconv/json" 47 | ) 48 | 49 | func main() { 50 | e := json.NewEncoder(os.Stdout) 51 | e.Encode(struct{ Hello string }{"World"}) 52 | } 53 | ``` 54 | ``` 55 | $ go run ./example.go 56 | {"Hello":"World"} 57 | ``` 58 | 59 | Note that this code is fully compatible with the standard `encoding/json` 60 | package. 61 | 62 | Decoder 63 | ------- 64 | 65 | Here's an example of how to use a JSON decoder: 66 | ```go 67 | package main 68 | 69 | import ( 70 | "fmt" 71 | "os" 72 | 73 | "github.com/segmentio/objconv/json" 74 | ) 75 | 76 | func main() { 77 | v := struct{ Message string }{} 78 | 79 | d := json.NewDecoder(os.Stdin) 80 | d.Decode(&v) 81 | 82 | fmt.Println(v.Message) 83 | } 84 | ``` 85 | ``` 86 | $ echo '{ "Message": "Hello World!" }' | go run ./example.go 87 | Hello World! 88 | ``` 89 | 90 | Streaming 91 | --------- 92 | 93 | One of the interesting features of the `objconv` package is the ability to read 94 | and write streams of data. This has several advantages in terms of memory usage 95 | and latency when passing data from service to service. 96 | The package exposes the `StreamEncoder` and `StreamDecoder` types for this 97 | purpose. 98 | 99 | For example the JSON stream encoder and decoder can produce a JSON array as a 100 | stream where data are produced and consumed on the fly as they become available, 101 | here's an example: 102 | ```go 103 | package main 104 | 105 | import ( 106 | "io" 107 | 108 | "github.com/segmentio/objconv/json" 109 | ) 110 | 111 | func main() { 112 | r, w := io.Pipe() 113 | 114 | go func() { 115 | defer w.Close() 116 | 117 | e := json.NewStreamEncoder(w) 118 | defer e.Close() 119 | 120 | // Produce values to the JSON stream. 121 | for i := 0; i != 1000; i++ { 122 | e.Encode(i) 123 | } 124 | }() 125 | 126 | d := json.NewStreamDecoder(r) 127 | 128 | // Consume values from the JSON stream. 129 | var v int 130 | 131 | for d.Decode(&v) == nil { 132 | // v => {0..999} 133 | // ... 134 | } 135 | } 136 | ``` 137 | 138 | Stream decoders are capable of reading values from either arrays or single 139 | values, this is very convenient when an program cannot predict the structure of 140 | the stream. If the actual data representation is not an array the stream decoder 141 | will simply behave like a normal decoder and produce a single value. 142 | 143 | Encoding and decoding custom types 144 | ---------------------------------- 145 | 146 | To override the default encoder and decoder behaviors a type may implement the 147 | `ValueEncoder` or `ValueDecoder` interface. The method on these interfaces are 148 | called to customize the default behavior. 149 | 150 | This can prove very useful to represent slice of pairs as maps for example: 151 | ```go 152 | type KV struct { 153 | K string 154 | V interface{} 155 | } 156 | 157 | type M []KV 158 | 159 | // Implement the ValueEncoder interface to provide a custom encoding. 160 | func (m M) EncodeValue(e objconv.Encoder) error { 161 | i := 0 162 | return e.EncodeMap(len(m), func(k objconv.Encoder, v objconv.Encoder) (err error) { 163 | if err = k.Encode(m[i].K); err != nil { 164 | return 165 | } 166 | if err = v.Encode(m[i].V); err != nil { 167 | return 168 | } 169 | i++ 170 | return 171 | }) 172 | } 173 | ``` 174 | 175 | Mime Types 176 | ---------- 177 | 178 | The `objconv` package exposes APIs for registering codecs for specific mime 179 | types. When an objconv package for a specific format is imported 180 | it registers itself on the global registry to be later referred by name. 181 | 182 | ```go 183 | import ( 184 | "bytes" 185 | 186 | "github.com/segmentio/objconv" 187 | _ "github.com/segmentio/objconv/json" // registers the JSON codec 188 | ) 189 | 190 | func main() { 191 | // Lookup the JSON codec. 192 | jsonCodec, ok := objconv.Lookup("application/json") 193 | 194 | if !ok { 195 | panic("unreachable") 196 | } 197 | 198 | // Create a new encoder from the codec. 199 | b := &bytes.Buffer{} 200 | e := jsonCodec.NewEncoder(b) 201 | 202 | // ... 203 | } 204 | ``` 205 | -------------------------------------------------------------------------------- /yaml/parse.go: -------------------------------------------------------------------------------- 1 | package yaml 2 | 3 | import ( 4 | "bytes" 5 | "encoding/base64" 6 | "fmt" 7 | "io" 8 | "io/ioutil" 9 | "time" 10 | 11 | yaml "gopkg.in/yaml.v2" 12 | 13 | "github.com/segmentio/objconv" 14 | ) 15 | 16 | type Parser struct { 17 | r io.Reader // reader to load bytes from 18 | s []byte // string buffer 19 | // This stack is used to iterate over the arrays and maps that get loaded in 20 | // the value field. 21 | stack []parser 22 | } 23 | 24 | func NewParser(r io.Reader) *Parser { 25 | return &Parser{r: r} 26 | } 27 | 28 | func (p *Parser) Reset(r io.Reader) { 29 | p.r = r 30 | p.s = nil 31 | p.stack = nil 32 | } 33 | 34 | func (p *Parser) Buffered() io.Reader { 35 | return bytes.NewReader(nil) 36 | } 37 | 38 | func (p *Parser) ParseType() (typ objconv.Type, err error) { 39 | if p.stack == nil { 40 | var b []byte 41 | var v interface{} 42 | 43 | if b, err = ioutil.ReadAll(p.r); err != nil { 44 | return 45 | } 46 | if err = yaml.Unmarshal(b, &v); err != nil { 47 | return 48 | } 49 | p.push(newParser(v)) 50 | } 51 | 52 | switch v := p.value(); v.(type) { 53 | case nil: 54 | typ = objconv.Nil 55 | 56 | case bool: 57 | typ = objconv.Bool 58 | 59 | case int, int64: 60 | typ = objconv.Int 61 | 62 | case uint64: 63 | typ = objconv.Uint 64 | 65 | case float64: 66 | typ = objconv.Float 67 | 68 | case string: 69 | typ = objconv.String 70 | 71 | case yaml.MapSlice: 72 | typ = objconv.Map 73 | 74 | case []interface{}: 75 | typ = objconv.Array 76 | 77 | case eof: 78 | err = io.EOF 79 | 80 | default: 81 | err = fmt.Errorf("objconv/yaml: gopkg.in/yaml.v2 generated an unsupported value of type %T", v) 82 | } 83 | 84 | return 85 | } 86 | 87 | func (p *Parser) ParseNil() (err error) { 88 | p.pop() 89 | return 90 | } 91 | 92 | func (p *Parser) ParseBool() (v bool, err error) { 93 | v = p.pop().value().(bool) 94 | return 95 | } 96 | 97 | func (p *Parser) ParseInt() (v int64, err error) { 98 | switch x := p.pop().value().(type) { 99 | case int: 100 | v = int64(x) 101 | default: 102 | v = x.(int64) 103 | } 104 | return 105 | } 106 | 107 | func (p *Parser) ParseUint() (v uint64, err error) { 108 | v = p.pop().value().(uint64) 109 | return 110 | } 111 | 112 | func (p *Parser) ParseFloat() (v float64, err error) { 113 | v = p.pop().value().(float64) 114 | return 115 | } 116 | 117 | func (p *Parser) ParseString() (v []byte, err error) { 118 | s := p.pop().value().(string) 119 | n := len(s) 120 | 121 | if cap(p.s) < n { 122 | p.s = make([]byte, 0, ((n/1024)+1)*1024) 123 | } 124 | 125 | v = p.s[:n] 126 | copy(v, s) 127 | return 128 | } 129 | 130 | func (p *Parser) ParseBytes() (v []byte, err error) { 131 | panic("objconv/yaml: ParseBytes should never be called because YAML has no bytes type, this is likely a bug in the decoder code") 132 | } 133 | 134 | func (p *Parser) ParseTime() (v time.Time, err error) { 135 | panic("objconv/yaml: ParseBytes should never be called because YAML has no time type, this is likely a bug in the decoder code") 136 | } 137 | 138 | func (p *Parser) ParseDuration() (v time.Duration, err error) { 139 | panic("objconv/yaml: ParseDuration should never be called because YAML has no duration type, this is likely a bug in the decoder code") 140 | } 141 | 142 | func (p *Parser) ParseError() (v error, err error) { 143 | panic("objconv/yaml: ParseError should never be called because YAML has no error type, this is likely a bug in the decoder code") 144 | } 145 | 146 | func (p *Parser) ParseArrayBegin() (n int, err error) { 147 | if n = p.top().len(); n != 0 { 148 | p.push(newParser(p.top().next())) 149 | } 150 | return 151 | } 152 | 153 | func (p *Parser) ParseArrayEnd(n int) (err error) { 154 | p.pop() 155 | return 156 | } 157 | 158 | func (p *Parser) ParseArrayNext(n int) (err error) { 159 | p.push(newParser(p.top().next())) 160 | return 161 | } 162 | 163 | func (p *Parser) ParseMapBegin() (n int, err error) { 164 | if n = p.top().len(); n != 0 { 165 | p.push(newParser(p.top().next())) 166 | } 167 | return 168 | } 169 | 170 | func (p *Parser) ParseMapEnd(n int) (err error) { 171 | p.pop() 172 | return 173 | } 174 | 175 | func (p *Parser) ParseMapValue(n int) (err error) { 176 | p.push(newParser(p.top().next())) 177 | return 178 | } 179 | 180 | func (p *Parser) ParseMapNext(n int) (err error) { 181 | p.push(newParser(p.top().next())) 182 | return 183 | } 184 | 185 | func (p *Parser) TextParser() bool { 186 | return true 187 | } 188 | 189 | func (p *Parser) DecodeBytes(b []byte) (v []byte, err error) { 190 | var n int 191 | if n, err = base64.StdEncoding.Decode(b, b); err != nil { 192 | return 193 | } 194 | v = b[:n] 195 | return 196 | } 197 | 198 | func (p *Parser) push(v parser) { 199 | p.stack = append(p.stack, v) 200 | } 201 | 202 | func (p *Parser) pop() parser { 203 | i := len(p.stack) - 1 204 | v := p.stack[i] 205 | p.stack = p.stack[:i] 206 | return v 207 | } 208 | 209 | func (p *Parser) top() parser { 210 | return p.stack[len(p.stack)-1] 211 | } 212 | 213 | func (p *Parser) value() interface{} { 214 | n := len(p.stack) 215 | if n == 0 { 216 | return eof{} 217 | } 218 | return p.stack[n-1].value() 219 | } 220 | 221 | type parser interface { 222 | value() interface{} 223 | next() interface{} 224 | len() int 225 | } 226 | 227 | type valueParser struct { 228 | self interface{} 229 | } 230 | 231 | func (p *valueParser) value() interface{} { 232 | return p.self 233 | } 234 | 235 | func (p *valueParser) next() interface{} { 236 | panic("objconv/yaml: invalid call of next method on simple value parser") 237 | } 238 | 239 | func (p *valueParser) len() int { 240 | panic("objconv/yaml: invalid call of len method on simple value parser") 241 | } 242 | 243 | type arrayParser struct { 244 | self []interface{} 245 | off int 246 | } 247 | 248 | func (p *arrayParser) value() interface{} { 249 | return p.self 250 | } 251 | 252 | func (p *arrayParser) next() interface{} { 253 | v := p.self[p.off] 254 | p.off++ 255 | return v 256 | } 257 | 258 | func (p *arrayParser) len() int { 259 | return len(p.self) 260 | } 261 | 262 | type mapParser struct { 263 | self yaml.MapSlice 264 | off int 265 | val bool 266 | } 267 | 268 | func (p *mapParser) value() interface{} { 269 | return p.self 270 | } 271 | 272 | func (p *mapParser) next() (v interface{}) { 273 | if p.val { 274 | v = p.self[p.off].Value 275 | p.val = false 276 | p.off++ 277 | } else { 278 | v = p.self[p.off].Key 279 | p.val = true 280 | } 281 | return 282 | } 283 | 284 | func (p *mapParser) len() int { 285 | return len(p.self) 286 | } 287 | 288 | func newParser(v interface{}) parser { 289 | switch x := v.(type) { 290 | case map[interface{}]interface{}: 291 | return &mapParser{self: makeMapSlice(x)} 292 | 293 | case []interface{}: 294 | return &arrayParser{self: x} 295 | 296 | default: 297 | return &valueParser{self: x} 298 | } 299 | } 300 | 301 | func makeMapSlice(m map[interface{}]interface{}) yaml.MapSlice { 302 | s := make(yaml.MapSlice, 0, len(m)) 303 | 304 | for k, v := range m { 305 | s = append(s, yaml.MapItem{ 306 | Key: k, 307 | Value: v, 308 | }) 309 | } 310 | 311 | return s 312 | } 313 | 314 | // eof values are returned by the top method to indicate that all values have 315 | // already been consumed. 316 | type eof struct{} 317 | -------------------------------------------------------------------------------- /encode_test.go: -------------------------------------------------------------------------------- 1 | package objconv 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "reflect" 7 | "testing" 8 | "time" 9 | ) 10 | 11 | // Used for testing that the encoder does the right thing with type aliases. 12 | type TBool bool 13 | type TInt int 14 | type TInt8 int8 15 | type TInt16 int16 16 | type TInt32 int32 17 | type TInt64 int64 18 | type TUint uint 19 | type TUint8 uint8 20 | type TUint16 uint16 21 | type TUint32 uint32 22 | type TUint64 uint64 23 | type TUintptr uintptr 24 | type TFloat32 float32 25 | type TFloat64 float64 26 | type TString string 27 | type TBytes []byte 28 | 29 | func TestEncoder(t *testing.T) { 30 | now := time.Now() 31 | err := errors.New("error") 32 | 33 | tests := [...]struct { 34 | in interface{} 35 | out interface{} 36 | }{ 37 | // nil 38 | {nil, nil}, 39 | 40 | // booleans 41 | {true, true}, 42 | {false, false}, 43 | {TBool(true), true}, 44 | {TBool(false), false}, 45 | 46 | // int 47 | {int(1), int64(1)}, 48 | {int8(1), int64(1)}, 49 | {int16(1), int64(1)}, 50 | {int32(1), int64(1)}, 51 | {int64(1), int64(1)}, 52 | {TInt(1), int64(1)}, 53 | {TInt8(1), int64(1)}, 54 | {TInt16(1), int64(1)}, 55 | {TInt32(1), int64(1)}, 56 | {TInt64(1), int64(1)}, 57 | 58 | // uint 59 | {uint(1), uint64(1)}, 60 | {uint8(1), uint64(1)}, 61 | {uint16(1), uint64(1)}, 62 | {uint32(1), uint64(1)}, 63 | {uint64(1), uint64(1)}, 64 | {uintptr(1), uint64(1)}, 65 | {TUint(1), uint64(1)}, 66 | {TUint8(1), uint64(1)}, 67 | {TUint16(1), uint64(1)}, 68 | {TUint32(1), uint64(1)}, 69 | {TUint64(1), uint64(1)}, 70 | {TUintptr(1), uint64(1)}, 71 | 72 | // float 73 | {float32(1), float64(1)}, 74 | {float64(1), float64(1)}, 75 | {TFloat32(1), float64(1)}, 76 | {TFloat64(1), float64(1)}, 77 | 78 | // string 79 | {"Hello World!", "Hello World!"}, 80 | {TString("Hello World!"), "Hello World!"}, 81 | 82 | // bytes 83 | {[]byte("123"), []byte("123")}, 84 | {TBytes("123"), []byte("123")}, 85 | 86 | // time 87 | {now, now}, 88 | 89 | // duration 90 | {time.Second, time.Second}, 91 | 92 | // error 93 | {err, err}, 94 | 95 | // array 96 | {[...]int{1, 2, 3}, []interface{}{int64(1), int64(2), int64(3)}}, 97 | {[]int{1, 2, 3}, []interface{}{int64(1), int64(2), int64(3)}}, 98 | {[]int{}, []interface{}{}}, 99 | 100 | // map 101 | {map[int]int{1: 21, 2: 42}, map[interface{}]interface{}{ 102 | int64(1): int64(21), 103 | int64(2): int64(42), 104 | }}, 105 | {map[string]interface{}{"hello": "world"}, map[interface{}]interface{}{ 106 | "hello": "world", 107 | }}, 108 | 109 | // struct 110 | {struct{}{}, map[interface{}]interface{}{}}, 111 | {struct{ A int }{42}, map[interface{}]interface{}{"A": int64(42)}}, 112 | 113 | // struct tags 114 | { 115 | in: &struct { 116 | A bool `objconv:"a"` 117 | B bool `objconv:"b,omitempty"` 118 | C bool `objconv:"c,omitzero"` 119 | }{true, false, false}, 120 | out: map[interface{}]interface{}{ 121 | "a": true, 122 | }, 123 | }, 124 | 125 | // struct tags (json) 126 | { 127 | in: &struct { 128 | A bool `json:"a"` 129 | B bool `json:"b,omitempty"` 130 | C bool `json:"c,omitzero"` 131 | }{true, false, false}, 132 | out: map[interface{}]interface{}{ 133 | "a": true, 134 | "c": false, 135 | }, 136 | }, 137 | 138 | // list of complex data structures 139 | { 140 | in: []map[string]string{ 141 | {"A": "hello", "B": "world"}, 142 | {}, 143 | {"A": "1"}, 144 | }, 145 | out: []interface{}{ 146 | map[interface{}]interface{}{"A": "hello", "B": "world"}, 147 | map[interface{}]interface{}{}, 148 | map[interface{}]interface{}{"A": "1"}, 149 | }, 150 | }, 151 | 152 | // nested structs and maps 153 | { 154 | in: map[string]struct{ M map[int][]int }{ 155 | "answer": {map[int][]int{1: {1, 2, 3}, 2: nil}}, 156 | }, 157 | out: map[interface{}]interface{}{ 158 | "answer": map[interface{}]interface{}{ 159 | "M": map[interface{}]interface{}{ 160 | int64(1): []interface{}{int64(1), int64(2), int64(3)}, 161 | int64(2): []interface{}{}, 162 | }, 163 | }, 164 | }, 165 | }, 166 | } 167 | 168 | for _, test := range tests { 169 | t.Run(fmt.Sprintf("%T", test.in), func(t *testing.T) { 170 | emt := &ValueEmitter{} 171 | enc := NewEncoder(emt) 172 | 173 | if err := enc.Encode(test.in); err != nil { 174 | t.Error(err) 175 | } 176 | 177 | if val := emt.Value(); !reflect.DeepEqual(val, test.out) { 178 | t.Errorf("%T => %#v", val, val) 179 | } 180 | }) 181 | } 182 | } 183 | 184 | func BenchmarkEncoder(b *testing.B) { 185 | tests := [...]interface{}{ 186 | // nil 187 | nil, 188 | 189 | // bool 190 | false, 191 | TBool(false), 192 | 193 | // int 194 | int(0), 195 | int8(0), 196 | int16(0), 197 | int32(0), 198 | int64(0), 199 | TInt(0), 200 | TInt8(0), 201 | TInt16(0), 202 | TInt32(0), 203 | TInt64(0), 204 | 205 | // uint 206 | uint(0), 207 | uint8(0), 208 | uint16(0), 209 | uint32(0), 210 | uint64(0), 211 | uintptr(0), 212 | TUint(0), 213 | TUint8(0), 214 | TUint16(0), 215 | TUint32(0), 216 | TUint64(0), 217 | TUintptr(0), 218 | 219 | // float 220 | float32(0), 221 | float64(0), 222 | TFloat32(0), 223 | TFloat64(0), 224 | 225 | // string 226 | "", 227 | TString(""), 228 | 229 | // bytes 230 | []byte(nil), 231 | TBytes(nil), 232 | 233 | // time 234 | time.Now(), 235 | 236 | // duration 237 | time.Second, 238 | 239 | // error 240 | errors.New("error"), 241 | 242 | // array 243 | []int(nil), 244 | [0]int{}, 245 | 246 | // map 247 | (map[int]int)(nil), 248 | (map[string]string)(nil), 249 | 250 | // struct 251 | struct{}{}, 252 | struct{ A int }{}, 253 | } 254 | 255 | enc := NewEncoder(Discard) 256 | 257 | for _, test := range tests { 258 | b.Run(fmt.Sprintf("%T", test), func(b *testing.B) { 259 | for i := 0; i != b.N; i++ { 260 | enc.Encode(test) 261 | } 262 | }) 263 | } 264 | } 265 | 266 | func TestStreamEncoderFix(t *testing.T) { 267 | val := &ValueEmitter{} 268 | enc := NewStreamEncoder(val) 269 | 270 | if err := enc.Open(10); err != nil { 271 | t.Error(err) 272 | } 273 | 274 | for i := 0; i != 10; i++ { 275 | if err := enc.Encode(i); err != nil { 276 | t.Error(err) 277 | } 278 | } 279 | 280 | x1 := []interface{}{ 281 | int64(0), 282 | int64(1), 283 | int64(2), 284 | int64(3), 285 | int64(4), 286 | int64(5), 287 | int64(6), 288 | int64(7), 289 | int64(8), 290 | int64(9), 291 | } 292 | 293 | x2 := val.Value() 294 | 295 | if !reflect.DeepEqual(x1, x2) { 296 | t.Error(x1, "!=", x2) 297 | } 298 | } 299 | 300 | func TestStreamEncoderVar(t *testing.T) { 301 | val := &ValueEmitter{} 302 | enc := NewStreamEncoder(val) 303 | 304 | for i := 0; i != 10; i++ { 305 | if err := enc.Encode(i); err != nil { 306 | t.Error(err) 307 | } 308 | } 309 | 310 | if err := enc.Close(); err != nil { 311 | t.Error(err) 312 | } 313 | 314 | x1 := []interface{}{ 315 | int64(0), 316 | int64(1), 317 | int64(2), 318 | int64(3), 319 | int64(4), 320 | int64(5), 321 | int64(6), 322 | int64(7), 323 | int64(8), 324 | int64(9), 325 | } 326 | 327 | x2 := val.Value() 328 | 329 | if !reflect.DeepEqual(x1, x2) { 330 | t.Error(x1, "!=", x2) 331 | } 332 | } 333 | -------------------------------------------------------------------------------- /json/emit.go: -------------------------------------------------------------------------------- 1 | package json 2 | 3 | import ( 4 | "encoding/base64" 5 | "errors" 6 | "io" 7 | "math" 8 | "strconv" 9 | "time" 10 | 11 | "github.com/segmentio/objconv" 12 | "github.com/segmentio/objconv/objutil" 13 | ) 14 | 15 | var ( 16 | nullBytes = [...]byte{'n', 'u', 'l', 'l'} 17 | trueBytes = [...]byte{'t', 'r', 'u', 'e'} 18 | falseBytes = [...]byte{'f', 'a', 'l', 's', 'e'} 19 | 20 | arrayOpen = [...]byte{'['} 21 | arrayClose = [...]byte{']'} 22 | 23 | mapOpen = [...]byte{'{'} 24 | mapClose = [...]byte{'}'} 25 | 26 | comma = [...]byte{','} 27 | column = [...]byte{':'} 28 | 29 | newline = [...]byte{'\n'} 30 | spaces = [...]byte{' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '} 31 | ) 32 | 33 | // Emitter implements a JSON emitter that satisfies the objconv.Emitter 34 | // interface. 35 | type Emitter struct { 36 | w io.Writer 37 | s []byte 38 | a [128]byte 39 | } 40 | 41 | func NewEmitter(w io.Writer) *Emitter { 42 | e := &Emitter{w: w} 43 | e.s = e.a[:0] 44 | return e 45 | } 46 | 47 | func (e *Emitter) Reset(w io.Writer) { 48 | e.w = w 49 | } 50 | 51 | func (e *Emitter) EmitNil() (err error) { 52 | _, err = e.w.Write(nullBytes[:]) 53 | return 54 | } 55 | 56 | func (e *Emitter) EmitBool(v bool) (err error) { 57 | if v { 58 | _, err = e.w.Write(trueBytes[:]) 59 | } else { 60 | _, err = e.w.Write(falseBytes[:]) 61 | } 62 | return 63 | } 64 | 65 | func (e *Emitter) EmitInt(v int64, _ int) (err error) { 66 | _, err = e.w.Write(strconv.AppendInt(e.s[:0], v, 10)) 67 | return 68 | } 69 | 70 | func (e *Emitter) EmitUint(v uint64, _ int) (err error) { 71 | _, err = e.w.Write(strconv.AppendUint(e.s[:0], v, 10)) 72 | return 73 | } 74 | 75 | func (e *Emitter) EmitFloat(v float64, bitSize int) (err error) { 76 | switch { 77 | case math.IsNaN(v): 78 | err = errors.New("NaN has no json representation") 79 | 80 | case math.IsInf(v, +1): 81 | err = errors.New("+Inf has no json representation") 82 | 83 | case math.IsInf(v, -1): 84 | err = errors.New("-Inf has no json representation") 85 | 86 | default: 87 | _, err = e.w.Write(strconv.AppendFloat(e.s[:0], v, 'g', -1, bitSize)) 88 | } 89 | return 90 | } 91 | 92 | func (e *Emitter) EmitString(v string) (err error) { 93 | i := 0 94 | j := 0 95 | n := len(v) 96 | s := append(e.s[:0], '"') 97 | 98 | for j != n { 99 | b := v[j] 100 | j++ 101 | 102 | switch b { 103 | case '"', '\\': 104 | // b = b 105 | 106 | case '\b': 107 | b = 'b' 108 | 109 | case '\f': 110 | b = 'f' 111 | 112 | case '\n': 113 | b = 'n' 114 | 115 | case '\r': 116 | b = 'r' 117 | 118 | case '\t': 119 | b = 't' 120 | 121 | default: 122 | continue 123 | } 124 | 125 | s = append(s, v[i:j-1]...) 126 | s = append(s, '\\', b) 127 | i = j 128 | } 129 | 130 | s = append(s, v[i:j]...) 131 | s = append(s, '"') 132 | e.s = s[:0] // in case the buffer was reallocated 133 | 134 | _, err = e.w.Write(s) 135 | return 136 | } 137 | 138 | func (e *Emitter) EmitBytes(v []byte) (err error) { 139 | s := e.s[:0] 140 | n := base64.StdEncoding.EncodedLen(len(v)) + 2 141 | 142 | if cap(s) < n { 143 | s = make([]byte, 0, align(n, 1024)) 144 | e.s = s 145 | } 146 | 147 | s = s[:n] 148 | s[0] = '"' 149 | base64.StdEncoding.Encode(s[1:], v) 150 | s[n-1] = '"' 151 | 152 | _, err = e.w.Write(s) 153 | return 154 | } 155 | 156 | func (e *Emitter) EmitTime(v time.Time) (err error) { 157 | s := e.s[:0] 158 | 159 | s = append(s, '"') 160 | s = v.AppendFormat(s, time.RFC3339Nano) 161 | s = append(s, '"') 162 | 163 | e.s = s[:0] 164 | _, err = e.w.Write(s) 165 | return 166 | } 167 | 168 | func (e *Emitter) EmitDuration(v time.Duration) (err error) { 169 | s := e.s[:0] 170 | 171 | s = append(s, '"') 172 | s = objutil.AppendDuration(s, v) 173 | s = append(s, '"') 174 | 175 | e.s = s[:0] 176 | _, err = e.w.Write(s) 177 | return 178 | } 179 | 180 | func (e *Emitter) EmitError(v error) (err error) { 181 | return e.EmitString(v.Error()) 182 | } 183 | 184 | func (e *Emitter) EmitArrayBegin(_ int) (err error) { 185 | _, err = e.w.Write(arrayOpen[:]) 186 | return 187 | } 188 | 189 | func (e *Emitter) EmitArrayEnd() (err error) { 190 | _, err = e.w.Write(arrayClose[:]) 191 | return 192 | } 193 | 194 | func (e *Emitter) EmitArrayNext() (err error) { 195 | _, err = e.w.Write(comma[:]) 196 | return 197 | } 198 | 199 | func (e *Emitter) EmitMapBegin(_ int) (err error) { 200 | _, err = e.w.Write(mapOpen[:]) 201 | return 202 | } 203 | 204 | func (e *Emitter) EmitMapEnd() (err error) { 205 | _, err = e.w.Write(mapClose[:]) 206 | return 207 | } 208 | 209 | func (e *Emitter) EmitMapValue() (err error) { 210 | _, err = e.w.Write(column[:]) 211 | return 212 | } 213 | 214 | func (e *Emitter) EmitMapNext() (err error) { 215 | _, err = e.w.Write(comma[:]) 216 | return 217 | } 218 | 219 | func (e *Emitter) TextEmitter() bool { 220 | return true 221 | } 222 | 223 | func (e *Emitter) PrettyEmitter() objconv.Emitter { 224 | return NewPrettyEmitter(e.w) 225 | } 226 | 227 | func align(n int, a int) int { 228 | if (n % a) == 0 { 229 | return n 230 | } 231 | return ((n / a) + 1) * a 232 | } 233 | 234 | type PrettyEmitter struct { 235 | Emitter 236 | i int 237 | s []int 238 | a [8]int 239 | } 240 | 241 | func NewPrettyEmitter(w io.Writer) *PrettyEmitter { 242 | e := &PrettyEmitter{ 243 | Emitter: *NewEmitter(w), 244 | } 245 | e.s = e.a[:0] 246 | return e 247 | } 248 | 249 | func (e *PrettyEmitter) Reset(w io.Writer) { 250 | e.Emitter.Reset(w) 251 | e.i = 0 252 | e.s = e.s[:0] 253 | } 254 | 255 | func (e *PrettyEmitter) EmitArrayBegin(n int) (err error) { 256 | if err = e.Emitter.EmitArrayBegin(n); err != nil { 257 | return 258 | } 259 | if e.push(n) != 0 { 260 | err = e.indent() 261 | } 262 | return 263 | } 264 | 265 | func (e *PrettyEmitter) EmitArrayEnd() (err error) { 266 | if e.pop() != 0 { 267 | if err = e.indent(); err != nil { 268 | return 269 | } 270 | } 271 | return e.Emitter.EmitArrayEnd() 272 | } 273 | 274 | func (e *PrettyEmitter) EmitArrayNext() (err error) { 275 | if err = e.Emitter.EmitArrayNext(); err != nil { 276 | return 277 | } 278 | return e.indent() 279 | } 280 | 281 | func (e *PrettyEmitter) EmitMapBegin(n int) (err error) { 282 | if err = e.Emitter.EmitMapBegin(n); err != nil { 283 | return 284 | } 285 | if e.push(n) != 0 { 286 | err = e.indent() 287 | } 288 | return 289 | } 290 | 291 | func (e *PrettyEmitter) EmitMapEnd() (err error) { 292 | if e.pop() != 0 { 293 | if err = e.indent(); err != nil { 294 | return 295 | } 296 | } 297 | return e.Emitter.EmitMapEnd() 298 | } 299 | 300 | func (e *PrettyEmitter) EmitMapValue() (err error) { 301 | if err = e.Emitter.EmitMapValue(); err != nil { 302 | return 303 | } 304 | _, err = e.w.Write(spaces[:1]) 305 | return 306 | } 307 | 308 | func (e *PrettyEmitter) EmitMapNext() (err error) { 309 | if err = e.Emitter.EmitMapNext(); err != nil { 310 | return 311 | } 312 | return e.indent() 313 | } 314 | 315 | func (e *PrettyEmitter) TextEmitter() bool { 316 | return true 317 | } 318 | 319 | func (e *PrettyEmitter) indent() (err error) { 320 | if _, err = e.w.Write(newline[:]); err != nil { 321 | return 322 | } 323 | 324 | for n := 2 * e.i; n != 0; { 325 | n1 := n 326 | n2 := len(spaces) 327 | 328 | if n1 > n2 { 329 | n1 = n2 330 | } 331 | 332 | if _, err = e.w.Write(spaces[:n1]); err != nil { 333 | return 334 | } 335 | 336 | n -= n1 337 | } 338 | 339 | return 340 | } 341 | 342 | func (e *PrettyEmitter) push(n int) int { 343 | if n != 0 { 344 | e.i++ 345 | } 346 | e.s = append(e.s, n) 347 | return n 348 | } 349 | 350 | func (e *PrettyEmitter) pop() int { 351 | i := len(e.s) - 1 352 | n := e.s[i] 353 | e.s = e.s[:i] 354 | if n != 0 { 355 | e.i-- 356 | } 357 | return n 358 | } 359 | -------------------------------------------------------------------------------- /yaml/vendor/gopkg.in/check.v1/helpers.go: -------------------------------------------------------------------------------- 1 | package check 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | "time" 7 | ) 8 | 9 | // TestName returns the current test name in the form "SuiteName.TestName" 10 | func (c *C) TestName() string { 11 | return c.testName 12 | } 13 | 14 | // ----------------------------------------------------------------------- 15 | // Basic succeeding/failing logic. 16 | 17 | // Failed returns whether the currently running test has already failed. 18 | func (c *C) Failed() bool { 19 | return c.status() == failedSt 20 | } 21 | 22 | // Fail marks the currently running test as failed. 23 | // 24 | // Something ought to have been previously logged so the developer can tell 25 | // what went wrong. The higher level helper functions will fail the test 26 | // and do the logging properly. 27 | func (c *C) Fail() { 28 | c.setStatus(failedSt) 29 | } 30 | 31 | // FailNow marks the currently running test as failed and stops running it. 32 | // Something ought to have been previously logged so the developer can tell 33 | // what went wrong. The higher level helper functions will fail the test 34 | // and do the logging properly. 35 | func (c *C) FailNow() { 36 | c.Fail() 37 | c.stopNow() 38 | } 39 | 40 | // Succeed marks the currently running test as succeeded, undoing any 41 | // previous failures. 42 | func (c *C) Succeed() { 43 | c.setStatus(succeededSt) 44 | } 45 | 46 | // SucceedNow marks the currently running test as succeeded, undoing any 47 | // previous failures, and stops running the test. 48 | func (c *C) SucceedNow() { 49 | c.Succeed() 50 | c.stopNow() 51 | } 52 | 53 | // ExpectFailure informs that the running test is knowingly broken for 54 | // the provided reason. If the test does not fail, an error will be reported 55 | // to raise attention to this fact. This method is useful to temporarily 56 | // disable tests which cover well known problems until a better time to 57 | // fix the problem is found, without forgetting about the fact that a 58 | // failure still exists. 59 | func (c *C) ExpectFailure(reason string) { 60 | if reason == "" { 61 | panic("Missing reason why the test is expected to fail") 62 | } 63 | c.mustFail = true 64 | c.reason = reason 65 | } 66 | 67 | // Skip skips the running test for the provided reason. If run from within 68 | // SetUpTest, the individual test being set up will be skipped, and if run 69 | // from within SetUpSuite, the whole suite is skipped. 70 | func (c *C) Skip(reason string) { 71 | if reason == "" { 72 | panic("Missing reason why the test is being skipped") 73 | } 74 | c.reason = reason 75 | c.setStatus(skippedSt) 76 | c.stopNow() 77 | } 78 | 79 | // ----------------------------------------------------------------------- 80 | // Basic logging. 81 | 82 | // GetTestLog returns the current test error output. 83 | func (c *C) GetTestLog() string { 84 | return c.logb.String() 85 | } 86 | 87 | // Log logs some information into the test error output. 88 | // The provided arguments are assembled together into a string with fmt.Sprint. 89 | func (c *C) Log(args ...interface{}) { 90 | c.log(args...) 91 | } 92 | 93 | // Log logs some information into the test error output. 94 | // The provided arguments are assembled together into a string with fmt.Sprintf. 95 | func (c *C) Logf(format string, args ...interface{}) { 96 | c.logf(format, args...) 97 | } 98 | 99 | // Output enables *C to be used as a logger in functions that require only 100 | // the minimum interface of *log.Logger. 101 | func (c *C) Output(calldepth int, s string) error { 102 | d := time.Now().Sub(c.startTime) 103 | msec := d / time.Millisecond 104 | sec := d / time.Second 105 | min := d / time.Minute 106 | 107 | c.Logf("[LOG] %d:%02d.%03d %s", min, sec%60, msec%1000, s) 108 | return nil 109 | } 110 | 111 | // Error logs an error into the test error output and marks the test as failed. 112 | // The provided arguments are assembled together into a string with fmt.Sprint. 113 | func (c *C) Error(args ...interface{}) { 114 | c.logCaller(1) 115 | c.logString(fmt.Sprint("Error: ", fmt.Sprint(args...))) 116 | c.logNewLine() 117 | c.Fail() 118 | } 119 | 120 | // Errorf logs an error into the test error output and marks the test as failed. 121 | // The provided arguments are assembled together into a string with fmt.Sprintf. 122 | func (c *C) Errorf(format string, args ...interface{}) { 123 | c.logCaller(1) 124 | c.logString(fmt.Sprintf("Error: "+format, args...)) 125 | c.logNewLine() 126 | c.Fail() 127 | } 128 | 129 | // Fatal logs an error into the test error output, marks the test as failed, and 130 | // stops the test execution. The provided arguments are assembled together into 131 | // a string with fmt.Sprint. 132 | func (c *C) Fatal(args ...interface{}) { 133 | c.logCaller(1) 134 | c.logString(fmt.Sprint("Error: ", fmt.Sprint(args...))) 135 | c.logNewLine() 136 | c.FailNow() 137 | } 138 | 139 | // Fatlaf logs an error into the test error output, marks the test as failed, and 140 | // stops the test execution. The provided arguments are assembled together into 141 | // a string with fmt.Sprintf. 142 | func (c *C) Fatalf(format string, args ...interface{}) { 143 | c.logCaller(1) 144 | c.logString(fmt.Sprint("Error: ", fmt.Sprintf(format, args...))) 145 | c.logNewLine() 146 | c.FailNow() 147 | } 148 | 149 | // ----------------------------------------------------------------------- 150 | // Generic checks and assertions based on checkers. 151 | 152 | // Check verifies if the first value matches the expected value according 153 | // to the provided checker. If they do not match, an error is logged, the 154 | // test is marked as failed, and the test execution continues. 155 | // 156 | // Some checkers may not need the expected argument (e.g. IsNil). 157 | // 158 | // Extra arguments provided to the function are logged next to the reported 159 | // problem when the matching fails. 160 | func (c *C) Check(obtained interface{}, checker Checker, args ...interface{}) bool { 161 | return c.internalCheck("Check", obtained, checker, args...) 162 | } 163 | 164 | // Assert ensures that the first value matches the expected value according 165 | // to the provided checker. If they do not match, an error is logged, the 166 | // test is marked as failed, and the test execution stops. 167 | // 168 | // Some checkers may not need the expected argument (e.g. IsNil). 169 | // 170 | // Extra arguments provided to the function are logged next to the reported 171 | // problem when the matching fails. 172 | func (c *C) Assert(obtained interface{}, checker Checker, args ...interface{}) { 173 | if !c.internalCheck("Assert", obtained, checker, args...) { 174 | c.stopNow() 175 | } 176 | } 177 | 178 | func (c *C) internalCheck(funcName string, obtained interface{}, checker Checker, args ...interface{}) bool { 179 | if checker == nil { 180 | c.logCaller(2) 181 | c.logString(fmt.Sprintf("%s(obtained, nil!?, ...):", funcName)) 182 | c.logString("Oops.. you've provided a nil checker!") 183 | c.logNewLine() 184 | c.Fail() 185 | return false 186 | } 187 | 188 | // If the last argument is a bug info, extract it out. 189 | var comment CommentInterface 190 | if len(args) > 0 { 191 | if c, ok := args[len(args)-1].(CommentInterface); ok { 192 | comment = c 193 | args = args[:len(args)-1] 194 | } 195 | } 196 | 197 | params := append([]interface{}{obtained}, args...) 198 | info := checker.Info() 199 | 200 | if len(params) != len(info.Params) { 201 | names := append([]string{info.Params[0], info.Name}, info.Params[1:]...) 202 | c.logCaller(2) 203 | c.logString(fmt.Sprintf("%s(%s):", funcName, strings.Join(names, ", "))) 204 | c.logString(fmt.Sprintf("Wrong number of parameters for %s: want %d, got %d", info.Name, len(names), len(params)+1)) 205 | c.logNewLine() 206 | c.Fail() 207 | return false 208 | } 209 | 210 | // Copy since it may be mutated by Check. 211 | names := append([]string{}, info.Params...) 212 | 213 | // Do the actual check. 214 | result, error := checker.Check(params, names) 215 | if !result || error != "" { 216 | c.logCaller(2) 217 | for i := 0; i != len(params); i++ { 218 | c.logValue(names[i], params[i]) 219 | } 220 | if comment != nil { 221 | c.logString(comment.CheckCommentString()) 222 | } 223 | if error != "" { 224 | c.logString(error) 225 | } 226 | c.logNewLine() 227 | c.Fail() 228 | return false 229 | } 230 | return true 231 | } 232 | -------------------------------------------------------------------------------- /msgpack/emit.go: -------------------------------------------------------------------------------- 1 | package msgpack 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "io" 7 | "math" 8 | "sync" 9 | "time" 10 | 11 | "github.com/segmentio/objconv/objutil" 12 | ) 13 | 14 | // Emitter implements a MessagePack emitter that satisfies the objconv.Emitter 15 | // interface. 16 | type Emitter struct { 17 | w io.Writer 18 | b [240]byte 19 | 20 | // This stack is used to cache arrays that are emitted in streaming mode, 21 | // where the length of the array is not known before outputing all the 22 | // elements. 23 | stack []*context 24 | 25 | // sback is used as the initial backing array for the stack slice to avoid 26 | // dynamic memory allocations for the most common use cases. 27 | sback [8]*context 28 | } 29 | 30 | type context struct { 31 | b bytes.Buffer // buffer where the array elements are cached 32 | w io.Writer // the previous writer where b will be flushed 33 | n int // the number of elements written to the array 34 | } 35 | 36 | func NewEmitter(w io.Writer) *Emitter { 37 | e := &Emitter{w: w} 38 | e.stack = e.sback[:0] 39 | return e 40 | } 41 | 42 | func (e *Emitter) Reset(w io.Writer) { 43 | e.w = w 44 | e.stack = e.stack[:0] 45 | } 46 | 47 | func (e *Emitter) EmitNil() (err error) { 48 | e.b[0] = Nil 49 | _, err = e.w.Write(e.b[:1]) 50 | return 51 | } 52 | 53 | func (e *Emitter) EmitBool(v bool) (err error) { 54 | if v { 55 | e.b[0] = True 56 | } else { 57 | e.b[0] = False 58 | } 59 | _, err = e.w.Write(e.b[:1]) 60 | return 61 | } 62 | 63 | func (e *Emitter) EmitInt(v int64, _ int) (err error) { 64 | n := 0 65 | 66 | if v >= 0 { 67 | switch { 68 | case v <= objutil.Int8Max: 69 | e.b[0] = byte(v) | PositiveFixintTag 70 | n = 1 71 | 72 | case v <= objutil.Int16Max: 73 | e.b[0] = Int16 74 | putUint16(e.b[1:], uint16(v)) 75 | n = 3 76 | 77 | case v <= objutil.Int32Max: 78 | e.b[0] = Int32 79 | putUint32(e.b[1:], uint32(v)) 80 | n = 5 81 | 82 | default: 83 | e.b[0] = Int64 84 | putUint64(e.b[1:], uint64(v)) 85 | n = 9 86 | } 87 | 88 | } else { 89 | switch { 90 | case v >= -31: 91 | e.b[0] = byte(v) | NegativeFixintTag 92 | n = 1 93 | 94 | case v >= objutil.Int8Min: 95 | e.b[0] = Int8 96 | e.b[1] = byte(v) 97 | n = 2 98 | 99 | case v >= objutil.Int16Min: 100 | e.b[0] = Int16 101 | putUint16(e.b[1:], uint16(v)) 102 | n = 3 103 | 104 | case v >= objutil.Int32Min: 105 | e.b[0] = Int32 106 | putUint32(e.b[1:], uint32(v)) 107 | n = 5 108 | 109 | default: 110 | e.b[0] = Int64 111 | putUint64(e.b[1:], uint64(v)) 112 | n = 9 113 | } 114 | } 115 | 116 | _, err = e.w.Write(e.b[:n]) 117 | return 118 | } 119 | 120 | func (e *Emitter) EmitUint(v uint64, _ int) (err error) { 121 | n := 0 122 | 123 | switch { 124 | case v <= objutil.Uint8Max: 125 | e.b[0] = Uint8 126 | e.b[1] = byte(v) 127 | n = 2 128 | 129 | case v <= objutil.Uint16Max: 130 | e.b[0] = Uint16 131 | putUint16(e.b[1:], uint16(v)) 132 | n = 3 133 | 134 | case v <= objutil.Uint32Max: 135 | e.b[0] = Uint32 136 | putUint32(e.b[1:], uint32(v)) 137 | n = 5 138 | 139 | default: 140 | e.b[0] = Uint64 141 | putUint64(e.b[1:], v) 142 | n = 9 143 | } 144 | 145 | _, err = e.w.Write(e.b[:n]) 146 | return 147 | } 148 | 149 | func (e *Emitter) EmitFloat(v float64, bitSize int) (err error) { 150 | switch bitSize { 151 | case 32: 152 | e.b[0] = Float32 153 | putUint32(e.b[1:], math.Float32bits(float32(v))) 154 | _, err = e.w.Write(e.b[:5]) 155 | default: 156 | e.b[0] = Float64 157 | putUint64(e.b[1:], math.Float64bits(v)) 158 | _, err = e.w.Write(e.b[:9]) 159 | } 160 | return 161 | } 162 | 163 | func (e *Emitter) EmitString(v string) (err error) { 164 | n := len(v) 165 | 166 | switch { 167 | case n <= 31: 168 | e.b[0] = byte(n) | FixstrTag 169 | n = 1 170 | 171 | case n <= objutil.Uint8Max: 172 | e.b[0] = Str8 173 | e.b[1] = byte(n) 174 | n = 2 175 | 176 | case n <= objutil.Uint16Max: 177 | e.b[0] = Str16 178 | putUint16(e.b[1:], uint16(n)) 179 | n = 3 180 | 181 | case n <= objutil.Uint32Max: 182 | e.b[0] = Str32 183 | putUint32(e.b[1:], uint32(n)) 184 | n = 5 185 | 186 | default: 187 | err = fmt.Errorf("objconv/msgpack: string of length %d is too long to be encoded", n) 188 | return 189 | } 190 | 191 | for { 192 | n1 := len(v) 193 | n2 := len(e.b[n:]) 194 | 195 | if n1 > n2 { 196 | n1 = n2 197 | } 198 | 199 | copy(e.b[n:], v[:n1]) 200 | 201 | if _, err = e.w.Write(e.b[:n+n1]); err != nil { 202 | return 203 | } 204 | 205 | v = v[n1:] 206 | n = 0 207 | 208 | if len(v) == 0 { 209 | return 210 | } 211 | } 212 | } 213 | 214 | func (e *Emitter) EmitBytes(v []byte) (err error) { 215 | n := len(v) 216 | 217 | switch { 218 | case n <= objutil.Uint8Max: 219 | e.b[0] = Bin8 220 | e.b[1] = byte(n) 221 | n = 2 222 | 223 | case n <= objutil.Uint16Max: 224 | e.b[0] = Bin16 225 | putUint16(e.b[1:], uint16(n)) 226 | n = 3 227 | 228 | case n <= objutil.Uint32Max: 229 | e.b[0] = Bin32 230 | putUint32(e.b[1:], uint32(n)) 231 | n = 5 232 | 233 | default: 234 | err = fmt.Errorf("objconv/msgpack: byte slice of length %d is too long to be encoded", n) 235 | return 236 | } 237 | 238 | if _, err = e.w.Write(e.b[:n]); err != nil { 239 | return 240 | } 241 | 242 | _, err = e.w.Write(v) 243 | return 244 | } 245 | 246 | func (e *Emitter) EmitTime(v time.Time) (err error) { 247 | const int34Max = 17179869183 248 | 249 | x := ExtTime 250 | n := 0 251 | s := v.Unix() 252 | ns := v.Nanosecond() 253 | 254 | if ns == 0 && s >= 0 && s <= objutil.Uint32Max { 255 | e.b[0] = Fixext4 256 | e.b[1] = byte(x) 257 | putUint32(e.b[2:], uint32(s)) 258 | n = 6 259 | } else if s >= 0 && s <= int34Max { 260 | e.b[0] = Fixext8 261 | e.b[1] = byte(x) 262 | putUint64(e.b[2:], uint64(s)|(uint64(ns)<<34)) 263 | n = 10 264 | } else { 265 | e.b[0] = Ext8 266 | e.b[1] = 12 267 | e.b[2] = byte(x) 268 | putUint32(e.b[3:], uint32(ns)) 269 | putUint64(e.b[7:], uint64(s)) 270 | n = 15 271 | } 272 | 273 | _, err = e.w.Write(e.b[:n]) 274 | return 275 | } 276 | 277 | func (e *Emitter) EmitDuration(v time.Duration) (err error) { 278 | return e.EmitString(string(objutil.AppendDuration(e.b[:0], v))) 279 | } 280 | 281 | func (e *Emitter) EmitError(v error) (err error) { 282 | return e.EmitString(v.Error()) 283 | } 284 | 285 | func (e *Emitter) EmitArrayBegin(n int) (err error) { 286 | var c *context 287 | 288 | if n < 0 { 289 | c = contextPool.Get().(*context) 290 | c.b.Truncate(0) 291 | c.n = 0 292 | c.w = e.w 293 | e.w = &c.b 294 | } else { 295 | err = e.emitArray(n) 296 | } 297 | 298 | e.stack = append(e.stack, c) 299 | return 300 | } 301 | 302 | func (e *Emitter) EmitArrayEnd() (err error) { 303 | i := len(e.stack) - 1 304 | c := e.stack[i] 305 | e.stack = e.stack[:i] 306 | 307 | if c != nil { 308 | e.w = c.w 309 | 310 | if c.b.Len() != 0 { 311 | c.n++ 312 | } 313 | 314 | if err = e.emitArray(c.n); err == nil { 315 | _, err = c.b.WriteTo(c.w) 316 | } 317 | 318 | contextPool.Put(c) 319 | } 320 | 321 | return 322 | } 323 | 324 | func (e *Emitter) EmitArrayNext() (err error) { 325 | if c := e.stack[len(e.stack)-1]; c != nil { 326 | c.n++ 327 | } 328 | return 329 | } 330 | 331 | func (e *Emitter) EmitMapBegin(n int) (err error) { 332 | if n < 0 { 333 | err = fmt.Errorf("objconv/msgpack: encoding maps of unknown length is not supported (n = %d)", n) 334 | return 335 | } 336 | 337 | switch { 338 | case n <= 15: 339 | e.b[0] = byte(n) | FixmapTag 340 | n = 1 341 | 342 | case n <= objutil.Uint16Max: 343 | e.b[0] = Map16 344 | putUint16(e.b[1:], uint16(n)) 345 | n = 3 346 | 347 | case n <= objutil.Uint32Max: 348 | e.b[0] = Map32 349 | putUint32(e.b[1:], uint32(n)) 350 | n = 5 351 | 352 | default: 353 | err = fmt.Errorf("objconv/msgpack: map of length %d is too long to be encoded", n) 354 | return 355 | } 356 | 357 | _, err = e.w.Write(e.b[:n]) 358 | return 359 | } 360 | 361 | func (e *Emitter) EmitMapEnd() (err error) { 362 | return 363 | } 364 | 365 | func (e *Emitter) EmitMapValue() (err error) { 366 | return 367 | } 368 | 369 | func (e *Emitter) EmitMapNext() (err error) { 370 | return 371 | } 372 | 373 | func (e *Emitter) emitArray(n int) (err error) { 374 | switch { 375 | case n <= 15: 376 | e.b[0] = byte(n) | FixarrayTag 377 | n = 1 378 | 379 | case n <= objutil.Uint16Max: 380 | e.b[0] = Array16 381 | putUint16(e.b[1:], uint16(n)) 382 | n = 3 383 | 384 | case n <= objutil.Uint32Max: 385 | e.b[0] = Array32 386 | putUint32(e.b[1:], uint32(n)) 387 | n = 5 388 | 389 | default: 390 | err = fmt.Errorf("objconv/msgpack: array of length %d is too long to be encoded", n) 391 | return 392 | } 393 | 394 | _, err = e.w.Write(e.b[:n]) 395 | return 396 | } 397 | 398 | var contextPool = sync.Pool{ 399 | New: func() interface{} { return &context{} }, 400 | } 401 | --------------------------------------------------------------------------------