├── bench └── go.mod ├── go.mod ├── .github └── workflows │ ├── lint.yml │ └── ci.yml ├── internal ├── util │ ├── strings.go │ └── file.go └── cmd │ ├── gencontainer │ └── gencontainer.go │ ├── genencoder │ └── genencoder.go │ └── gendecoder │ └── gendecoder.go ├── errors.go ├── .gitignore ├── .golangci.yml ├── ext.go ├── msgpack.go ├── roundtrip_test.go ├── code.go ├── array_builder.go ├── map_builder.go ├── reader.go ├── encoder_numeric_gen.go ├── encoder_locking_gen.go ├── decoder_locking_gen.go ├── writer.go ├── code_string.go ├── msgpack_example_test.go ├── encoder_container_gen.go ├── interface.go ├── decoder_numeric_gen.go ├── decoder_test.go ├── encoder.go ├── README.md ├── encoder_test.go └── decoder.go /bench/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/lestrrat-go/msgpack/bench 2 | 3 | go 1.16 4 | 5 | require ( 6 | github.com/lestrrat-go/msgpack v0.0.0-20191118094803-f1541f70f50e 7 | github.com/vmihailenco/msgpack/v4 v4.3.12 8 | gopkg.in/vmihailenco/msgpack.v2 v2.9.1 // indirect 9 | ) 10 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/lestrrat-go/msgpack 2 | 3 | go 1.12 4 | 5 | require ( 6 | github.com/davecgh/go-spew v1.1.1 // indirect 7 | github.com/lestrrat-go/bufferpool v0.0.0-20180220091733-e7784e1b3e37 8 | github.com/pkg/errors v0.8.1 9 | github.com/stretchr/testify v1.3.0 10 | ) 11 | -------------------------------------------------------------------------------- /.github/workflows/lint.yml: -------------------------------------------------------------------------------- 1 | name: lint 2 | on: [push, pull_request] 3 | jobs: 4 | golangci: 5 | name: lint 6 | runs-on: ubuntu-latest 7 | steps: 8 | - uses: actions/checkout@v2 9 | - uses: golangci/golangci-lint-action@v2 10 | with: 11 | version: v1.34.1 12 | -------------------------------------------------------------------------------- /internal/util/strings.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import "unicode" 4 | 5 | func Ucfirst(s string) string { 6 | res := make([]rune, len(s)) 7 | for i, r := range s { 8 | if i == 0 { 9 | res[i] = unicode.ToUpper(r) 10 | } else { 11 | res[i] = r 12 | } 13 | } 14 | return string(res) 15 | } 16 | -------------------------------------------------------------------------------- /errors.go: -------------------------------------------------------------------------------- 1 | package msgpack 2 | 3 | import "reflect" 4 | 5 | func (e *InvalidDecodeError) Error() string { 6 | if e.Type == nil { 7 | return "msgpack: Decode(nil)" 8 | } 9 | 10 | if e.Type.Kind() != reflect.Ptr { 11 | return "msgpack: Decode(non-pointer " + e.Type.String() + ")" 12 | } 13 | return "msgpack: Decode(nil " + e.Type.String() + ")" 14 | } 15 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /internal/util/file.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import ( 4 | "fmt" 5 | "go/format" 6 | "os" 7 | 8 | "github.com/pkg/errors" 9 | ) 10 | 11 | func WriteFormattedFile(fn string, src []byte) error { 12 | formatted, err := format.Source(src) 13 | if err != nil { 14 | fmt.Println(string(src)) 15 | return err 16 | } 17 | 18 | dst, err := os.OpenFile(fn, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644) 19 | if err != nil { 20 | return errors.Wrap(err, `failed to open file`) 21 | } 22 | defer dst.Close() 23 | 24 | dst.Write(formatted) 25 | return nil 26 | } 27 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: [push, pull_request] 3 | 4 | jobs: 5 | build: 6 | runs-on: ubuntu-latest 7 | strategy: 8 | matrix: 9 | go: [ '1.15', '1.14' ] 10 | name: Go ${{ matrix.go }} test 11 | steps: 12 | - name: Checkout repository 13 | uses: actions/checkout@v2 14 | - name: Install Go stable version 15 | if: matrix.go != 'tip' 16 | uses: actions/setup-go@v2 17 | with: 18 | go-version: ${{ matrix.go }} 19 | - name: Install Go tip 20 | if: matrix.go == 'tip' 21 | run: | 22 | git clone --depth=1 https://go.googlesource.com/go $HOME/gotip 23 | cd $HOME/gotip/src 24 | ./make.bash 25 | echo "::set-env name=GOROOT::$HOME/gotip" 26 | echo "::add-path::$HOME/gotip/bin" 27 | echo "::add-path::$(go env GOPATH)/bin" 28 | - name: Test 29 | run: go test -v -race ./... 30 | - name: Upload code coverage to codecov 31 | if: matrix.go == '1.15' 32 | uses: codecov/codecov-action@v1 33 | with: 34 | file: ./coverage.out 35 | 36 | -------------------------------------------------------------------------------- /.golangci.yml: -------------------------------------------------------------------------------- 1 | run: 2 | skip-dirs: internal 3 | 4 | linters-settings: 5 | govet: 6 | enable-all: true 7 | disable: 8 | - shadow 9 | 10 | linters: 11 | enable-all: true 12 | disable: 13 | - dupl 14 | - exhaustive 15 | - exhaustivestruct 16 | - errorlint 17 | - funlen 18 | - gci 19 | - gochecknoglobals 20 | - gochecknoinits 21 | - gocognit 22 | - gocritic 23 | - gocyclo 24 | - godot 25 | - godox 26 | - goerr113 27 | - gofumpt 28 | - gomnd 29 | - gosec 30 | - lll 31 | - makezero 32 | - nakedret 33 | - nestif 34 | - nlreturn 35 | - paralleltest 36 | - testpackage 37 | - thelper 38 | - unconvert 39 | - wrapcheck 40 | - wsl 41 | 42 | issues: 43 | exclude-rules: 44 | - path: /*_test.go 45 | linters: 46 | - errcheck 47 | - path: /*_example_test.go 48 | linters: 49 | - forbidigo 50 | 51 | # Maximum issues count per one linter. Set to 0 to disable. Default is 50. 52 | max-issues-per-linter: 0 53 | 54 | # Maximum count of issues with the same text. Set to 0 to disable. Default is 3. 55 | max-same-issues: 0 56 | 57 | -------------------------------------------------------------------------------- /ext.go: -------------------------------------------------------------------------------- 1 | package msgpack 2 | 3 | import ( 4 | "reflect" 5 | "sync" 6 | 7 | "github.com/pkg/errors" 8 | ) 9 | 10 | var muExtDecode sync.RWMutex 11 | var muExtEncode sync.RWMutex 12 | var extDecodeRegistry = make(map[int]reflect.Type) 13 | var extEncodeRegistry = make(map[reflect.Type]int) 14 | 15 | var decodeMsgpackerType = reflect.TypeOf((*DecodeMsgpacker)(nil)).Elem() 16 | var encodeMsgpackerType = reflect.TypeOf((*EncodeMsgpacker)(nil)).Elem() 17 | 18 | func RegisterExt(typ int, v interface{}) error { 19 | rt := reflect.TypeOf(v) 20 | 21 | var decodeType = rt 22 | var encodeType = rt 23 | if decodeType.Implements(decodeMsgpackerType) { 24 | if decodeType.Kind() == reflect.Ptr { 25 | decodeType = decodeType.Elem() 26 | } 27 | } else { 28 | if ptrT := reflect.PtrTo(decodeType); !ptrT.Implements(decodeMsgpackerType) { 29 | return errors.Errorf(`msgpack: invalid type %s: only DecodeMsgpackers can be registered`, decodeType) 30 | } 31 | } 32 | 33 | if !encodeType.Implements(encodeMsgpackerType) { 34 | if encodeType.Kind() == reflect.Ptr && encodeType.Elem().Implements(encodeMsgpackerType) { 35 | encodeType = encodeType.Elem() 36 | } else { 37 | return errors.Errorf(`msgpack: invalid type %s: only EncodeMsgpackers can be registered`, encodeType) 38 | } 39 | } 40 | 41 | muExtDecode.Lock() 42 | extDecodeRegistry[typ] = decodeType 43 | muExtDecode.Unlock() 44 | 45 | muExtEncode.Lock() 46 | extEncodeRegistry[encodeType] = typ 47 | muExtEncode.Unlock() 48 | 49 | return nil 50 | } 51 | -------------------------------------------------------------------------------- /msgpack.go: -------------------------------------------------------------------------------- 1 | //go:generate stringer -type Code 2 | //go:generate go run internal/cmd/gencontainer/gencontainer.go - encoder_container_gen.go 3 | //go:generate go run internal/cmd/gendecoder/gendecoder.go 4 | //go:generate go run internal/cmd/genencoder/genencoder.go 5 | 6 | package msgpack 7 | 8 | import ( 9 | "bytes" 10 | "sync" 11 | 12 | "github.com/pkg/errors" 13 | ) 14 | 15 | var appendingWriterPool = sync.Pool{ 16 | New: allocAppendingWriter, 17 | } 18 | 19 | func allocAppendingWriter() interface{} { 20 | return newAppendingWriter(9) 21 | } 22 | 23 | func releaseAppendingWriter(w *appendingWriter) { 24 | w.buf = w.buf[0:0] 25 | appendingWriterPool.Put(w) 26 | } 27 | 28 | var encoderPool = sync.Pool{ 29 | New: func() interface{} { return NewEncoder(nil) }, 30 | } 31 | 32 | // Marshal takes a Go value and serializes it in msgpack format. 33 | func Marshal(v interface{}) ([]byte, error) { 34 | var buf = appendingWriterPool.Get().(*appendingWriter) 35 | defer releaseAppendingWriter(buf) 36 | 37 | var enc = encoderPool.Get().(Encoder) 38 | enc.SetDestination(buf) 39 | if err := enc.Encode(v); err != nil { 40 | return nil, errors.Wrap(err, `failed to marshal`) 41 | } 42 | raw := buf.Bytes() 43 | ret := make([]byte, len(raw)) 44 | copy(ret, raw) 45 | return ret, nil 46 | } 47 | 48 | // Unmarshal takes a byte slice and a pointer to a Go value and 49 | // deserializes the Go value from the data in msgpack format. 50 | func Unmarshal(data []byte, v interface{}) error { 51 | buf := bytes.NewBuffer(data) 52 | if err := NewDecoder(buf).Decode(v); err != nil { 53 | return errors.Wrap(err, `failed to unmarshal`) 54 | } 55 | return nil 56 | } 57 | -------------------------------------------------------------------------------- /roundtrip_test.go: -------------------------------------------------------------------------------- 1 | package msgpack_test 2 | 3 | import ( 4 | "math" 5 | "reflect" 6 | "testing" 7 | "time" 8 | 9 | msgpack "github.com/lestrrat-go/msgpack" 10 | "github.com/stretchr/testify/assert" 11 | ) 12 | 13 | type stringList []string 14 | type dummyStruct struct { 15 | Message string 16 | } 17 | type dummyStructList []*dummyStruct 18 | 19 | func TestRoundTrip(t *testing.T) { 20 | t.Parallel() 21 | 22 | a := 1 23 | b := 2 24 | c := 3 25 | var list = []interface{}{ 26 | int8(-31), 27 | int8(127), 28 | int8(math.MaxInt8), 29 | int16(math.MaxInt16), 30 | int32(math.MaxInt32), 31 | int64(math.MaxInt64), 32 | uint8(math.MaxUint8), 33 | uint16(math.MaxUint16), 34 | uint32(math.MaxUint32), 35 | uint64(math.MaxUint64), 36 | float32(math.MaxFloat32), 37 | float64(math.MaxFloat64), 38 | "Hello, World!", 39 | []byte("Hello, World!"), 40 | []string{"uno", "dos", "tres"}, 41 | stringList{"uno", "dos", "tres"}, 42 | dummyStructList{ 43 | {Message: "uno"}, 44 | {Message: "dos"}, 45 | {Message: "tres"}, 46 | }, 47 | []*int{&a, &b, &c}, 48 | time.Now().Round(0), 49 | dummyStruct{Message: "Hello World!"}, 50 | } 51 | 52 | for _, data := range list { 53 | data := data 54 | t.Run(reflect.TypeOf(data).String(), func(t *testing.T) { 55 | t.Parallel() 56 | b, err := msgpack.Marshal(data) 57 | if !assert.NoError(t, err, "Marshal should succeed") { 58 | return 59 | } 60 | 61 | var v interface{} = reflect.New(reflect.TypeOf(data)).Interface() 62 | if !assert.NoError(t, msgpack.Unmarshal(b, v), "Unmarshal should succeed") { 63 | return 64 | } 65 | 66 | if !assert.Equal(t, data, reflect.ValueOf(v).Elem().Interface(), "RoundTrip should succeed") { 67 | return 68 | } 69 | }) 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /code.go: -------------------------------------------------------------------------------- 1 | package msgpack 2 | 3 | // Byte returns the byte representation of the Code 4 | func (t Code) Byte() byte { 5 | return byte(t) 6 | } 7 | 8 | // IsMapFamily returns true if the given code is equivalent to 9 | // one of the `map` family in msgpack 10 | func IsMapFamily(c Code) bool { 11 | b := c.Byte() 12 | return (b >= FixMap0.Byte() && b <= FixMap15.Byte()) || 13 | b == Map16.Byte() || 14 | b == Map32.Byte() 15 | } 16 | 17 | // IsArrayFamily returns true if the given code is equivalent 18 | // to one of the `array` family in msgpack 19 | func IsArrayFamily(c Code) bool { 20 | b := c.Byte() 21 | return (b >= FixArray0.Byte() && b <= FixArray15.Byte()) || 22 | b == Array16.Byte() || 23 | b == Array32.Byte() 24 | } 25 | 26 | // IsStrFamily returns true if the given code is equivalent 27 | // to one of the `str` family in msgpack 28 | func IsStrFamily(c Code) bool { 29 | b := c.Byte() 30 | return (b >= FixStr0.Byte() && b <= FixStr31.Byte()) || 31 | b == Str8.Byte() || 32 | b == Str16.Byte() || 33 | b == Str32.Byte() 34 | } 35 | 36 | // IsBinFamily returns true if the given code is equivalent 37 | // to one of the `bin` family in msgpack 38 | func IsBinFamily(c Code) bool { 39 | b := c.Byte() 40 | return b == Bin8.Byte() || b == Bin16.Byte() || b == Bin32.Byte() 41 | } 42 | 43 | // IsExtFamily returns true if the given code is equivalent 44 | // to one of the `ext` family in msgpack 45 | func IsExtFamily(c Code) bool { 46 | b := c.Byte() 47 | return b == Ext8.Byte() || b == Ext16.Byte() || b == Ext32.Byte() || 48 | b == FixExt1.Byte() || b == FixExt2.Byte() || b == FixExt4.Byte() || b == FixExt8.Byte() || b == FixExt16.Byte() 49 | } 50 | 51 | // IsFixNumFamily returns true if the given code is equivalent 52 | // to one of the fixed num family 53 | func IsFixNumFamily(c Code) bool { 54 | return IsPositiveFixNum(c) || IsNegativeFixNum(c) 55 | } 56 | 57 | func IsPositiveFixNum(c Code) bool { 58 | b := c.Byte() 59 | return b>>7 == 0 60 | } 61 | 62 | const negativeFixNumPrefix = 0xe0 63 | 64 | func IsNegativeFixNum(c Code) bool { 65 | b := c.Byte() 66 | return b&0xe0 == negativeFixNumPrefix 67 | } 68 | -------------------------------------------------------------------------------- /array_builder.go: -------------------------------------------------------------------------------- 1 | package msgpack 2 | 3 | import ( 4 | "bytes" 5 | "io" 6 | "math" 7 | "reflect" 8 | 9 | "github.com/pkg/errors" 10 | ) 11 | 12 | type arrayBuilder struct { 13 | buffer []interface{} 14 | } 15 | 16 | func NewArrayBuilder() ArrayBuilder { 17 | return &arrayBuilder{} 18 | } 19 | 20 | func (e *arrayBuilder) Add(v interface{}) { 21 | e.buffer = append(e.buffer, v) 22 | } 23 | 24 | func WriteArrayHeader(dst io.Writer, c int) error { 25 | var w Writer 26 | var ok bool 27 | if w, ok = dst.(Writer); !ok { 28 | w = NewWriter(dst) 29 | } 30 | 31 | switch { 32 | case c < 16: 33 | if err := w.WriteByte(FixArray0.Byte() + byte(c)); err != nil { 34 | return errors.Wrap(err, `msgpack: failed to write fixed array header`) 35 | } 36 | case c < math.MaxUint16: 37 | if err := w.WriteByte(Array16.Byte()); err != nil { 38 | return errors.Wrap(err, `msgpack: failed to write 16-bit array header prefix`) 39 | } 40 | if err := w.WriteUint16(uint16(c)); err != nil { 41 | return errors.Wrap(err, `msgpack: failed to write 16-bit array header`) 42 | } 43 | case c < math.MaxUint32: 44 | if err := w.WriteByte(Array32.Byte()); err != nil { 45 | return errors.Wrap(err, `msgpack: failed to write 32-bit array header prefix`) 46 | } 47 | if err := w.WriteUint32(uint32(c)); err != nil { 48 | return errors.Wrap(err, `msgpack: failed to write 32-bit array header`) 49 | } 50 | default: 51 | return errors.Errorf(`msgpack: array element count out of range (%d)`, c) 52 | } 53 | return nil 54 | } 55 | 56 | func (e arrayBuilder) Encode(dst io.Writer) error { 57 | if err := WriteArrayHeader(dst, e.Count()); err != nil { 58 | return errors.Wrap(err, `msgpack: failed to write array header`) 59 | } 60 | 61 | enc := NewEncoder(dst) 62 | for _, v := range e.buffer { 63 | if err := enc.Encode(v); err != nil { 64 | return errors.Wrapf(err, `msgpack: failed to encode array element %s`, reflect.TypeOf(v)) 65 | } 66 | } 67 | return nil 68 | } 69 | 70 | func (e arrayBuilder) Bytes() ([]byte, error) { 71 | var buf bytes.Buffer 72 | if err := e.Encode(&buf); err != nil { 73 | return nil, errors.Wrap(err, `msgpack: failed to encode array`) 74 | } 75 | return buf.Bytes(), nil 76 | } 77 | 78 | func (e arrayBuilder) Count() int { 79 | return len(e.buffer) 80 | } 81 | 82 | func (e *arrayBuilder) Reset() { 83 | e.buffer = e.buffer[:0] 84 | } 85 | -------------------------------------------------------------------------------- /map_builder.go: -------------------------------------------------------------------------------- 1 | package msgpack 2 | 3 | import ( 4 | "bytes" 5 | "io" 6 | "math" 7 | 8 | "github.com/pkg/errors" 9 | ) 10 | 11 | type mapBuilder struct { 12 | buffer []interface{} 13 | } 14 | 15 | func NewMapBuilder() MapBuilder { 16 | return &mapBuilder{} 17 | } 18 | 19 | func (b *mapBuilder) Reset() { 20 | b.buffer = b.buffer[:0] 21 | } 22 | 23 | func (b *mapBuilder) Add(key string, value interface{}) { 24 | b.buffer = append(b.buffer, key, value) 25 | } 26 | 27 | func (b *mapBuilder) Count() int { 28 | return len(b.buffer) / 2 29 | } 30 | 31 | func WriteMapHeader(dst io.Writer, c int) error { 32 | var w Writer 33 | var ok bool 34 | if w, ok = dst.(Writer); !ok { 35 | w = NewWriter(dst) 36 | } 37 | 38 | switch { 39 | case c < 16: 40 | if err := w.WriteByte(FixMap0.Byte() + byte(c)); err != nil { 41 | return errors.Wrap(err, `failed to write element size prefix`) 42 | } 43 | case c < math.MaxUint16: 44 | if err := w.WriteByte(Map16.Byte()); err != nil { 45 | return errors.Wrap(err, `failed to write 16-bit element size prefix`) 46 | } 47 | if err := w.WriteUint16(uint16(c)); err != nil { 48 | return errors.Wrap(err, `failed to write 16-bit element size`) 49 | } 50 | case c < math.MaxUint32: 51 | if err := w.WriteByte(Map32.Byte()); err != nil { 52 | return errors.Wrap(err, `failed to write 32-bit element size prefix`) 53 | } 54 | 55 | if err := w.WriteUint32(uint32(c)); err != nil { 56 | return errors.Wrap(err, `failed to write 32-bit element size`) 57 | } 58 | default: 59 | return errors.Errorf(`map builder: map element count out of range (%d)`, c) 60 | } 61 | return nil 62 | } 63 | 64 | func (b *mapBuilder) Encode(dst io.Writer) error { 65 | if err := WriteMapHeader(dst, b.Count()); err != nil { 66 | return errors.Wrap(err, `failed to write map header`) 67 | } 68 | 69 | e := NewEncoder(dst) 70 | for i := 0; i < b.Count(); i++ { 71 | if err := e.Encode(b.buffer[i*2]); err != nil { 72 | return errors.Wrapf(err, `map builder: failed to encode map key %s`, b.buffer[i]) 73 | } 74 | if err := e.Encode(b.buffer[i*2+1]); err != nil { 75 | return errors.Wrapf(err, `map builder: failed to encode map element for %s`, b.buffer[i]) 76 | } 77 | } 78 | return nil 79 | } 80 | 81 | func (b *mapBuilder) Bytes() ([]byte, error) { 82 | var buf bytes.Buffer 83 | if err := b.Encode(&buf); err != nil { 84 | return nil, errors.Wrap(err, `map builder: failed to write map`) 85 | } 86 | 87 | return buf.Bytes(), nil 88 | } 89 | -------------------------------------------------------------------------------- /internal/cmd/gencontainer/gencontainer.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "go/format" 7 | "log" 8 | "os" 9 | "reflect" 10 | "unicode" 11 | 12 | "github.com/pkg/errors" 13 | ) 14 | 15 | // This utility generates the various encodeArrayXXX and encodeMapXXX 16 | // methods, which uses raw []XXX and map[string]XXX types instead of 17 | // reflect for maximum efficiency, respectively 18 | func main() { 19 | if err := _main(); err != nil { 20 | log.Printf("%s", err) 21 | os.Exit(1) 22 | } 23 | } 24 | 25 | func ucfirst(s string) string { 26 | res := make([]rune, len(s)) 27 | for i, r := range s { 28 | if i == 0 { 29 | res[i] = unicode.ToUpper(r) 30 | } else { 31 | res[i] = r 32 | } 33 | } 34 | return string(res) 35 | } 36 | 37 | func _main() error { 38 | types := []reflect.Kind{ 39 | reflect.Bool, 40 | reflect.Int, 41 | reflect.Int8, 42 | reflect.Int16, 43 | reflect.Int32, 44 | reflect.Int64, 45 | reflect.Uint, 46 | reflect.Uint8, 47 | reflect.Uint16, 48 | reflect.Uint32, 49 | reflect.Uint64, 50 | reflect.Float32, 51 | reflect.Float64, 52 | reflect.String, 53 | } 54 | 55 | var buf bytes.Buffer 56 | buf.WriteString("package msgpack") 57 | buf.WriteString("\n\n// Auto-generated by internal/cmd/gencontainer/gencontainer.go. DO NOT EDIT!") 58 | buf.WriteString("\n\nimport \"github.com/pkg/errors\"") 59 | for _, typ := range types { 60 | fmt.Fprintf(&buf, "\n\nfunc (enl *encoderNL) encodeMap%s(in interface{}) error {", ucfirst(typ.String())) 61 | fmt.Fprintf(&buf, "\nfor k, v := range in.(map[string]%s) {", typ) 62 | buf.WriteString("\nif err := enl.EncodeString(k); err != nil {") 63 | buf.WriteString("\nreturn errors.Wrap(err, `failed to encode key`)") 64 | buf.WriteString("\n}") 65 | buf.WriteString("\nif err := enl.Encode(v); err != nil {") 66 | buf.WriteString("\nreturn errors.Wrapf(err, `failed to encode value for %s`, k)") 67 | buf.WriteString("\n}") 68 | buf.WriteString("\n}") 69 | buf.WriteString("\nreturn nil") 70 | buf.WriteString("\n}") 71 | } 72 | for _, typ := range types { 73 | fmt.Fprintf(&buf, "\n\nfunc (enl *encoderNL) encodeArray%s(in interface{}) error {", ucfirst(typ.String())) 74 | fmt.Fprintf(&buf, "\nfor k, v := range in.([]%s) {", typ) 75 | buf.WriteString("\nif err := enl.Encode(v); err != nil {") 76 | buf.WriteString("\nreturn errors.Wrapf(err, `failed to encode value for element %d`, k)") 77 | buf.WriteString("\n}") 78 | buf.WriteString("\n}") 79 | buf.WriteString("\nreturn nil") 80 | buf.WriteString("\n}") 81 | } 82 | 83 | formatted, err := format.Source(buf.Bytes()) 84 | if err != nil { 85 | fmt.Println(buf.String()) 86 | return errors.Wrap(err, `failed to format`) 87 | } 88 | 89 | var fn string 90 | for i := 1; i < len(os.Args); i++ { 91 | if os.Args[i] != "-" { 92 | fn = os.Args[i] 93 | break 94 | } 95 | } 96 | 97 | dst, err := os.OpenFile(fn, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644) 98 | if err != nil { 99 | return errors.Wrap(err, `failed to open file`) 100 | } 101 | defer dst.Close() 102 | 103 | dst.Write(formatted) 104 | return nil 105 | } 106 | -------------------------------------------------------------------------------- /reader.go: -------------------------------------------------------------------------------- 1 | package msgpack 2 | 3 | import ( 4 | "encoding/binary" 5 | "io" 6 | 7 | "github.com/pkg/errors" 8 | ) 9 | 10 | type reader struct { 11 | src io.Reader 12 | // Note: accessing buf concurrently is a mistake. But you DO NOT 13 | // write to a writer concurrently, or otherwise you can't guarantee 14 | // the correct memory layout. We assume that the caller doesn't do 15 | // anything silly. 16 | buf []byte 17 | } 18 | 19 | func NewReader(r io.Reader) Reader { 20 | return &reader{ 21 | src: r, 22 | buf: make([]byte, 9), 23 | } 24 | } 25 | 26 | func (r *reader) Read(buf []byte) (int, error) { 27 | return io.ReadFull(r.src, buf) 28 | } 29 | 30 | func (r *reader) ReadByte() (byte, error) { 31 | b := r.buf[:1] 32 | n, err := r.Read(b) 33 | if n != 1 { 34 | return byte(0), errors.Wrap(err, `reader: failed to read byte`) 35 | } 36 | return b[0], nil 37 | } 38 | 39 | func (r *reader) ReadUint8() (uint8, error) { 40 | b, err := r.ReadByte() 41 | if err != nil { 42 | return uint8(0), errors.Wrap(err, `reader: failed to read uint8`) 43 | } 44 | return uint8(b), nil 45 | } 46 | 47 | func (r *reader) ReadUint16() (uint16, error) { 48 | b := r.buf[:2] 49 | if _, err := r.Read(b); err != nil { 50 | return uint16(0), errors.Wrap(err, `reader: failed to read uint16`) 51 | } 52 | return uint16(b[1]) | uint16(b[0])<<8, nil 53 | } 54 | 55 | func (r *reader) ReadUint32() (uint32, error) { 56 | b := r.buf[:4] 57 | if _, err := r.Read(b); err != nil { 58 | return uint32(0), errors.Wrap(err, `reader: failed to read uint32`) 59 | } 60 | return uint32(b[3]) | uint32(b[2])<<8 | uint32(b[1])<<16 | uint32(b[0])<<24, nil 61 | } 62 | 63 | func (r *reader) ReadUint64() (uint64, error) { 64 | b := r.buf[:8] 65 | if _, err := r.Read(b); err != nil { 66 | return uint64(0), errors.Wrap(err, `reader: failed to read uint64`) 67 | } 68 | return uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 | 69 | uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56, nil 70 | } 71 | 72 | func (r *reader) readbuf(size int) error { 73 | b := r.buf[:size] 74 | for len(b) > 0 { 75 | n, err := r.Read(b) 76 | b = b[n:] 77 | if err != nil { 78 | return errors.Wrapf(err, `reader: failed to read %d bytes`, size) 79 | } 80 | } 81 | return nil 82 | } 83 | 84 | func (r *reader) ReadByteUint8() (byte, uint8, error) { 85 | const size = 2 86 | if err := r.readbuf(size); err != nil { 87 | return 0, 0, err 88 | } 89 | return r.buf[0], uint8(r.buf[1]), nil 90 | } 91 | 92 | func (r *reader) ReadByteUint16() (byte, uint16, error) { 93 | const size = 3 94 | if err := r.readbuf(size); err != nil { 95 | return 0, 0, err 96 | } 97 | return r.buf[0], binary.BigEndian.Uint16(r.buf[1:]), nil 98 | } 99 | 100 | func (r *reader) ReadByteUint32() (byte, uint32, error) { 101 | const size = 5 102 | if err := r.readbuf(size); err != nil { 103 | return 0, 0, err 104 | } 105 | return r.buf[0], binary.BigEndian.Uint32(r.buf[1:]), nil 106 | } 107 | 108 | func (r *reader) ReadByteUint64() (byte, uint64, error) { 109 | const size = 9 110 | if err := r.readbuf(size); err != nil { 111 | return 0, 0, err 112 | } 113 | return r.buf[0], binary.BigEndian.Uint64(r.buf[1:]), nil 114 | } 115 | -------------------------------------------------------------------------------- /encoder_numeric_gen.go: -------------------------------------------------------------------------------- 1 | package msgpack 2 | 3 | // Auto-generated by internal/cmd/genencoder/genencoder.go. DO NOT EDIT! 4 | 5 | import ( 6 | "math" 7 | 8 | "github.com/pkg/errors" 9 | ) 10 | 11 | func (enl *encoderNL) EncodeInt(v int) error { 12 | if inNegativeFixNumRange(int64(v)) { 13 | return enl.encodeNegativeFixNum(int8(byte(0xff & v))) 14 | } 15 | 16 | if err := enl.dst.WriteByteUint64(Int64.Byte(), uint64(v)); err != nil { 17 | return errors.Wrap(err, `msgpack: failed to write Int64`) 18 | } 19 | return nil 20 | } 21 | 22 | func (enl *encoderNL) EncodeInt8(v int8) error { 23 | if inNegativeFixNumRange(int64(v)) { 24 | return enl.encodeNegativeFixNum(v) 25 | } 26 | 27 | if err := enl.dst.WriteByteUint8(Int8.Byte(), uint8(v)); err != nil { 28 | return errors.Wrap(err, `msgpack: failed to write Int8`) 29 | } 30 | return nil 31 | } 32 | 33 | func (enl *encoderNL) EncodeInt16(v int16) error { 34 | if inNegativeFixNumRange(int64(v)) { 35 | return enl.encodeNegativeFixNum(int8(byte(0xff & v))) 36 | } 37 | 38 | if err := enl.dst.WriteByteUint16(Int16.Byte(), uint16(v)); err != nil { 39 | return errors.Wrap(err, `msgpack: failed to write Int16`) 40 | } 41 | return nil 42 | } 43 | 44 | func (enl *encoderNL) EncodeInt32(v int32) error { 45 | if inNegativeFixNumRange(int64(v)) { 46 | return enl.encodeNegativeFixNum(int8(byte(0xff & v))) 47 | } 48 | 49 | if err := enl.dst.WriteByteUint32(Int32.Byte(), uint32(v)); err != nil { 50 | return errors.Wrap(err, `msgpack: failed to write Int32`) 51 | } 52 | return nil 53 | } 54 | 55 | func (enl *encoderNL) EncodeInt64(v int64) error { 56 | if inNegativeFixNumRange(int64(v)) { 57 | return enl.encodeNegativeFixNum(int8(byte(0xff & v))) 58 | } 59 | 60 | if err := enl.dst.WriteByteUint64(Int64.Byte(), uint64(v)); err != nil { 61 | return errors.Wrap(err, `msgpack: failed to write Int64`) 62 | } 63 | return nil 64 | } 65 | 66 | func (enl *encoderNL) EncodeUint(v uint) error { 67 | if inPositiveFixNumRange(int64(v)) { 68 | return enl.encodePositiveFixNum(uint8(0xff & v)) 69 | } 70 | 71 | if err := enl.dst.WriteByteUint64(Uint64.Byte(), uint64(v)); err != nil { 72 | return errors.Wrap(err, `msgpack: failed to write Uint64`) 73 | } 74 | return nil 75 | } 76 | 77 | func (enl *encoderNL) EncodeUint8(v uint8) error { 78 | if inPositiveFixNumRange(int64(v)) { 79 | return enl.encodePositiveFixNum(uint8(0xff & v)) 80 | } 81 | 82 | if err := enl.dst.WriteByteUint8(Uint8.Byte(), v); err != nil { 83 | return errors.Wrap(err, `msgpack: failed to write Uint8`) 84 | } 85 | return nil 86 | } 87 | 88 | func (enl *encoderNL) EncodeUint16(v uint16) error { 89 | if inPositiveFixNumRange(int64(v)) { 90 | return enl.encodePositiveFixNum(uint8(0xff & v)) 91 | } 92 | 93 | if err := enl.dst.WriteByteUint16(Uint16.Byte(), v); err != nil { 94 | return errors.Wrap(err, `msgpack: failed to write Uint16`) 95 | } 96 | return nil 97 | } 98 | 99 | func (enl *encoderNL) EncodeUint32(v uint32) error { 100 | if inPositiveFixNumRange(int64(v)) { 101 | return enl.encodePositiveFixNum(uint8(0xff & v)) 102 | } 103 | 104 | if err := enl.dst.WriteByteUint32(Uint32.Byte(), v); err != nil { 105 | return errors.Wrap(err, `msgpack: failed to write Uint32`) 106 | } 107 | return nil 108 | } 109 | 110 | func (enl *encoderNL) EncodeUint64(v uint64) error { 111 | if inPositiveFixNumRange(int64(v)) { 112 | return enl.encodePositiveFixNum(uint8(0xff & v)) 113 | } 114 | 115 | if err := enl.dst.WriteByteUint64(Uint64.Byte(), v); err != nil { 116 | return errors.Wrap(err, `msgpack: failed to write Uint64`) 117 | } 118 | return nil 119 | } 120 | 121 | func (enl *encoderNL) EncodeFloat32(f float32) error { 122 | if err := enl.dst.WriteByteUint32(Float.Byte(), math.Float32bits(f)); err != nil { 123 | return errors.Wrap(err, `msgpack: failed to write Float`) 124 | } 125 | return nil 126 | } 127 | 128 | func (enl *encoderNL) EncodeFloat64(f float64) error { 129 | if err := enl.dst.WriteByteUint64(Double.Byte(), math.Float64bits(f)); err != nil { 130 | return errors.Wrap(err, `msgpack: failed to write Double`) 131 | } 132 | return nil 133 | } 134 | -------------------------------------------------------------------------------- /encoder_locking_gen.go: -------------------------------------------------------------------------------- 1 | package msgpack 2 | 3 | // Auto-generated by internal/cmd/genencoder/genencoder.go. DO NOT EDIT! 4 | 5 | import ( 6 | "time" 7 | ) 8 | 9 | func (d *encoder) Encode(v interface{}) error { 10 | d.mu.RLock() 11 | defer d.mu.RUnlock() 12 | return d.nl.Encode(v) 13 | } 14 | 15 | func (d *encoder) EncodeArray(v interface{}) error { 16 | d.mu.RLock() 17 | defer d.mu.RUnlock() 18 | return d.nl.EncodeArray(v) 19 | } 20 | 21 | func (d *encoder) EncodeArrayHeader(v int) error { 22 | d.mu.RLock() 23 | defer d.mu.RUnlock() 24 | return d.nl.EncodeArrayHeader(v) 25 | } 26 | 27 | func (d *encoder) EncodeBool(v bool) error { 28 | d.mu.RLock() 29 | defer d.mu.RUnlock() 30 | return d.nl.EncodeBool(v) 31 | } 32 | 33 | func (d *encoder) EncodeBytes(v []byte) error { 34 | d.mu.RLock() 35 | defer d.mu.RUnlock() 36 | return d.nl.EncodeBytes(v) 37 | } 38 | 39 | func (d *encoder) EncodeExt(v EncodeMsgpacker) error { 40 | d.mu.RLock() 41 | defer d.mu.RUnlock() 42 | return d.nl.EncodeExt(v) 43 | } 44 | 45 | func (d *encoder) EncodeExtHeader(v int) error { 46 | d.mu.RLock() 47 | defer d.mu.RUnlock() 48 | return d.nl.EncodeExtHeader(v) 49 | } 50 | 51 | func (d *encoder) EncodeExtType(v EncodeMsgpacker) error { 52 | d.mu.RLock() 53 | defer d.mu.RUnlock() 54 | return d.nl.EncodeExtType(v) 55 | } 56 | 57 | func (d *encoder) EncodeMap(v interface{}) error { 58 | d.mu.RLock() 59 | defer d.mu.RUnlock() 60 | return d.nl.EncodeMap(v) 61 | } 62 | 63 | func (d *encoder) EncodeNegativeFixNum(v int8) error { 64 | d.mu.RLock() 65 | defer d.mu.RUnlock() 66 | return d.nl.EncodeNegativeFixNum(v) 67 | } 68 | 69 | func (d *encoder) EncodeNil() error { 70 | d.mu.RLock() 71 | defer d.mu.RUnlock() 72 | return d.nl.EncodeNil() 73 | } 74 | 75 | func (d *encoder) EncodePositiveFixNum(v uint8) error { 76 | d.mu.RLock() 77 | defer d.mu.RUnlock() 78 | return d.nl.EncodePositiveFixNum(v) 79 | } 80 | 81 | func (d *encoder) EncodeString(v string) error { 82 | d.mu.RLock() 83 | defer d.mu.RUnlock() 84 | return d.nl.EncodeString(v) 85 | } 86 | 87 | func (d *encoder) EncodeStruct(v interface{}) error { 88 | d.mu.RLock() 89 | defer d.mu.RUnlock() 90 | return d.nl.EncodeStruct(v) 91 | } 92 | 93 | func (d *encoder) EncodeTime(v time.Time) error { 94 | d.mu.RLock() 95 | defer d.mu.RUnlock() 96 | return d.nl.EncodeTime(v) 97 | } 98 | 99 | func (d *encoder) Writer() Writer { 100 | d.mu.RLock() 101 | defer d.mu.RUnlock() 102 | return d.nl.Writer() 103 | } 104 | 105 | func (d *encoder) EncodeInt(v int) error { 106 | d.mu.RLock() 107 | defer d.mu.RUnlock() 108 | return d.nl.EncodeInt(v) 109 | } 110 | 111 | func (d *encoder) EncodeInt8(v int8) error { 112 | d.mu.RLock() 113 | defer d.mu.RUnlock() 114 | return d.nl.EncodeInt8(v) 115 | } 116 | 117 | func (d *encoder) EncodeInt16(v int16) error { 118 | d.mu.RLock() 119 | defer d.mu.RUnlock() 120 | return d.nl.EncodeInt16(v) 121 | } 122 | 123 | func (d *encoder) EncodeInt32(v int32) error { 124 | d.mu.RLock() 125 | defer d.mu.RUnlock() 126 | return d.nl.EncodeInt32(v) 127 | } 128 | 129 | func (d *encoder) EncodeInt64(v int64) error { 130 | d.mu.RLock() 131 | defer d.mu.RUnlock() 132 | return d.nl.EncodeInt64(v) 133 | } 134 | 135 | func (d *encoder) EncodeUint(v uint) error { 136 | d.mu.RLock() 137 | defer d.mu.RUnlock() 138 | return d.nl.EncodeUint(v) 139 | } 140 | 141 | func (d *encoder) EncodeUint8(v uint8) error { 142 | d.mu.RLock() 143 | defer d.mu.RUnlock() 144 | return d.nl.EncodeUint8(v) 145 | } 146 | 147 | func (d *encoder) EncodeUint16(v uint16) error { 148 | d.mu.RLock() 149 | defer d.mu.RUnlock() 150 | return d.nl.EncodeUint16(v) 151 | } 152 | 153 | func (d *encoder) EncodeUint32(v uint32) error { 154 | d.mu.RLock() 155 | defer d.mu.RUnlock() 156 | return d.nl.EncodeUint32(v) 157 | } 158 | 159 | func (d *encoder) EncodeUint64(v uint64) error { 160 | d.mu.RLock() 161 | defer d.mu.RUnlock() 162 | return d.nl.EncodeUint64(v) 163 | } 164 | 165 | func (d *encoder) EncodeFloat32(v float32) error { 166 | d.mu.RLock() 167 | defer d.mu.RUnlock() 168 | return d.nl.EncodeFloat32(v) 169 | } 170 | 171 | func (d *encoder) EncodeFloat64(v float64) error { 172 | d.mu.RLock() 173 | defer d.mu.RUnlock() 174 | return d.nl.EncodeFloat64(v) 175 | } 176 | -------------------------------------------------------------------------------- /decoder_locking_gen.go: -------------------------------------------------------------------------------- 1 | package msgpack 2 | 3 | // Auto-generated by internal/cmd/gendecoder/gendecoder.go. DO NOT EDIT! 4 | 5 | import ( 6 | "reflect" 7 | "time" 8 | ) 9 | 10 | func (d *decoder) Decode(v interface{}) error { 11 | d.mu.RLock() 12 | defer d.mu.RUnlock() 13 | return d.nl.Decode(v) 14 | } 15 | 16 | func (d *decoder) DecodeArray(v interface{}) error { 17 | d.mu.RLock() 18 | defer d.mu.RUnlock() 19 | return d.nl.DecodeArray(v) 20 | } 21 | 22 | func (d *decoder) DecodeArrayLength(v *int) error { 23 | d.mu.RLock() 24 | defer d.mu.RUnlock() 25 | return d.nl.DecodeArrayLength(v) 26 | } 27 | 28 | func (d *decoder) DecodeBool(v *bool) error { 29 | d.mu.RLock() 30 | defer d.mu.RUnlock() 31 | return d.nl.DecodeBool(v) 32 | } 33 | 34 | func (d *decoder) DecodeBytes(v *[]byte) error { 35 | d.mu.RLock() 36 | defer d.mu.RUnlock() 37 | return d.nl.DecodeBytes(v) 38 | } 39 | 40 | func (d *decoder) DecodeExt(v DecodeMsgpacker) error { 41 | d.mu.RLock() 42 | defer d.mu.RUnlock() 43 | return d.nl.DecodeExt(v) 44 | } 45 | 46 | func (d *decoder) DecodeExtLength(v *int) error { 47 | d.mu.RLock() 48 | defer d.mu.RUnlock() 49 | return d.nl.DecodeExtLength(v) 50 | } 51 | 52 | func (d *decoder) DecodeExtType(v *reflect.Type) error { 53 | d.mu.RLock() 54 | defer d.mu.RUnlock() 55 | return d.nl.DecodeExtType(v) 56 | } 57 | 58 | func (d *decoder) DecodeMap(v *map[string]interface{}) error { 59 | d.mu.RLock() 60 | defer d.mu.RUnlock() 61 | return d.nl.DecodeMap(v) 62 | } 63 | 64 | func (d *decoder) DecodeMapLength(v *int) error { 65 | d.mu.RLock() 66 | defer d.mu.RUnlock() 67 | return d.nl.DecodeMapLength(v) 68 | } 69 | 70 | func (d *decoder) DecodeNil(v *interface{}) error { 71 | d.mu.RLock() 72 | defer d.mu.RUnlock() 73 | return d.nl.DecodeNil(v) 74 | } 75 | 76 | func (d *decoder) DecodeString(v *string) error { 77 | d.mu.RLock() 78 | defer d.mu.RUnlock() 79 | return d.nl.DecodeString(v) 80 | } 81 | 82 | func (d *decoder) DecodeStruct(v interface{}) error { 83 | d.mu.RLock() 84 | defer d.mu.RUnlock() 85 | return d.nl.DecodeStruct(v) 86 | } 87 | 88 | func (d *decoder) DecodeTime(v *time.Time) error { 89 | d.mu.RLock() 90 | defer d.mu.RUnlock() 91 | return d.nl.DecodeTime(v) 92 | } 93 | 94 | func (d *decoder) PeekCode() (Code, error) { 95 | d.mu.RLock() 96 | defer d.mu.RUnlock() 97 | return d.nl.PeekCode() 98 | } 99 | 100 | func (d *decoder) ReadCode() (Code, error) { 101 | d.mu.RLock() 102 | defer d.mu.RUnlock() 103 | return d.nl.ReadCode() 104 | } 105 | 106 | func (d *decoder) Reader() Reader { 107 | d.mu.RLock() 108 | defer d.mu.RUnlock() 109 | return d.nl.Reader() 110 | } 111 | 112 | func (d *decoder) DecodeInt(v *int) error { 113 | d.mu.RLock() 114 | defer d.mu.RUnlock() 115 | return d.nl.DecodeInt(v) 116 | } 117 | 118 | func (d *decoder) DecodeInt8(v *int8) error { 119 | d.mu.RLock() 120 | defer d.mu.RUnlock() 121 | return d.nl.DecodeInt8(v) 122 | } 123 | 124 | func (d *decoder) DecodeInt16(v *int16) error { 125 | d.mu.RLock() 126 | defer d.mu.RUnlock() 127 | return d.nl.DecodeInt16(v) 128 | } 129 | 130 | func (d *decoder) DecodeInt32(v *int32) error { 131 | d.mu.RLock() 132 | defer d.mu.RUnlock() 133 | return d.nl.DecodeInt32(v) 134 | } 135 | 136 | func (d *decoder) DecodeInt64(v *int64) error { 137 | d.mu.RLock() 138 | defer d.mu.RUnlock() 139 | return d.nl.DecodeInt64(v) 140 | } 141 | 142 | func (d *decoder) DecodeUint(v *uint) error { 143 | d.mu.RLock() 144 | defer d.mu.RUnlock() 145 | return d.nl.DecodeUint(v) 146 | } 147 | 148 | func (d *decoder) DecodeUint8(v *uint8) error { 149 | d.mu.RLock() 150 | defer d.mu.RUnlock() 151 | return d.nl.DecodeUint8(v) 152 | } 153 | 154 | func (d *decoder) DecodeUint16(v *uint16) error { 155 | d.mu.RLock() 156 | defer d.mu.RUnlock() 157 | return d.nl.DecodeUint16(v) 158 | } 159 | 160 | func (d *decoder) DecodeUint32(v *uint32) error { 161 | d.mu.RLock() 162 | defer d.mu.RUnlock() 163 | return d.nl.DecodeUint32(v) 164 | } 165 | 166 | func (d *decoder) DecodeUint64(v *uint64) error { 167 | d.mu.RLock() 168 | defer d.mu.RUnlock() 169 | return d.nl.DecodeUint64(v) 170 | } 171 | 172 | func (d *decoder) DecodeFloat32(v *float32) error { 173 | d.mu.RLock() 174 | defer d.mu.RUnlock() 175 | return d.nl.DecodeFloat32(v) 176 | } 177 | 178 | func (d *decoder) DecodeFloat64(v *float64) error { 179 | d.mu.RLock() 180 | defer d.mu.RUnlock() 181 | return d.nl.DecodeFloat64(v) 182 | } 183 | -------------------------------------------------------------------------------- /writer.go: -------------------------------------------------------------------------------- 1 | package msgpack 2 | 3 | import ( 4 | "encoding/binary" 5 | "io" 6 | ) 7 | 8 | type writer struct { 9 | dst io.Writer 10 | // Note: accessing buf concurrently is a mistake. But you DO NOT 11 | // write to a writer concurrently, or otherwise you can't guarantee 12 | // the correct memory layout. We assume that the caller doesn't do 13 | // anything silly. 14 | buf []byte 15 | } 16 | 17 | func NewWriter(w io.Writer) Writer { 18 | return &writer{ 19 | dst: w, 20 | buf: make([]byte, 9), 21 | } 22 | } 23 | 24 | func (w writer) Write(buf []byte) (int, error) { 25 | return w.dst.Write(buf) 26 | } 27 | 28 | func (w writer) WriteString(s string) (int, error) { 29 | return w.Write([]byte(s)) 30 | } 31 | 32 | func (w writer) WriteByte(v byte) error { 33 | b := w.buf[:1] 34 | b[0] = v 35 | _, err := w.Write(b) 36 | return err 37 | } 38 | 39 | func (w writer) WriteUint8(v uint8) error { 40 | return w.WriteByte(byte(v)) 41 | } 42 | 43 | func (w writer) WriteUint16(v uint16) error { 44 | b := w.buf[:2] 45 | binary.BigEndian.PutUint16(b, v) 46 | _, err := w.Write(b) 47 | return err 48 | } 49 | 50 | func (w writer) WriteUint32(v uint32) error { 51 | b := w.buf[:4] 52 | binary.BigEndian.PutUint32(b, v) 53 | _, err := w.Write(b) 54 | return err 55 | } 56 | 57 | func (w writer) WriteUint64(v uint64) error { 58 | b := w.buf[:8] 59 | binary.BigEndian.PutUint64(b, v) 60 | _, err := w.Write(b) 61 | return err 62 | } 63 | 64 | func (w writer) WriteByteUint8(b byte, v uint8) error { 65 | buf := w.buf[:2] 66 | buf[0] = b 67 | buf[1] = byte(v) 68 | _, err := w.Write(buf) 69 | return err 70 | } 71 | 72 | func (w writer) WriteByteUint16(b byte, v uint16) error { 73 | buf := w.buf[:3] 74 | buf[0] = b 75 | binary.BigEndian.PutUint16(buf[1:], v) 76 | _, err := w.Write(buf) 77 | return err 78 | } 79 | 80 | func (w writer) WriteByteUint32(b byte, v uint32) error { 81 | buf := w.buf[:5] 82 | buf[0] = b 83 | binary.BigEndian.PutUint32(buf[1:], v) 84 | _, err := w.Write(buf) 85 | return err 86 | } 87 | 88 | func (w writer) WriteByteUint64(b byte, v uint64) error { 89 | buf := w.buf[:9] 90 | buf[0] = b 91 | binary.BigEndian.PutUint64(buf[1:], v) 92 | _, err := w.Write(buf) 93 | return err 94 | } 95 | 96 | type appendingWriter struct { 97 | buf []byte 98 | } 99 | 100 | var _ Writer = &appendingWriter{} 101 | 102 | func newAppendingWriter(size int) *appendingWriter { 103 | return &appendingWriter{ 104 | buf: make([]byte, 0, size), 105 | } 106 | } 107 | 108 | func (w *appendingWriter) Write(buf []byte) (int, error) { 109 | w.buf = append(w.buf, buf...) 110 | return len(buf), nil 111 | } 112 | 113 | func (w *appendingWriter) WriteString(s string) (int, error) { 114 | w.buf = append(w.buf, s...) 115 | return len(s), nil 116 | } 117 | 118 | func (w *appendingWriter) WriteByte(v byte) error { 119 | w.buf = append(w.buf, v) 120 | return nil 121 | } 122 | 123 | func (w *appendingWriter) WriteUint8(v uint8) error { 124 | return w.WriteByte(byte(v)) 125 | } 126 | 127 | func (w *appendingWriter) WriteUint16(v uint16) error { 128 | const size = 2 129 | for i := 0; i < size; i++ { 130 | w.buf = append(w.buf, 0) 131 | } 132 | binary.BigEndian.PutUint16(w.buf[len(w.buf)-size:], v) 133 | return nil 134 | } 135 | 136 | func (w *appendingWriter) WriteUint32(v uint32) error { 137 | const size = 4 138 | for i := 0; i < size; i++ { 139 | w.buf = append(w.buf, 0) 140 | } 141 | binary.BigEndian.PutUint32(w.buf[len(w.buf)-size:], v) 142 | return nil 143 | } 144 | 145 | func (w *appendingWriter) WriteUint64(v uint64) error { 146 | const size = 8 147 | for i := 0; i < size; i++ { 148 | w.buf = append(w.buf, 0) 149 | } 150 | binary.BigEndian.PutUint64(w.buf[len(w.buf)-size:], v) 151 | return nil 152 | } 153 | 154 | func (w *appendingWriter) WriteByteUint8(b byte, v uint8) error { 155 | w.buf = append(w.buf, b, byte(v)) 156 | return nil 157 | } 158 | 159 | func (w *appendingWriter) WriteByteUint16(b byte, v uint16) error { 160 | w.buf = append(w.buf, b) 161 | return w.WriteUint16(v) 162 | } 163 | 164 | func (w *appendingWriter) WriteByteUint32(b byte, v uint32) error { 165 | w.buf = append(w.buf, b) 166 | return w.WriteUint32(v) 167 | } 168 | 169 | func (w *appendingWriter) WriteByteUint64(b byte, v uint64) error { 170 | w.buf = append(w.buf, b) 171 | return w.WriteUint64(v) 172 | } 173 | 174 | func (w appendingWriter) Bytes() []byte { 175 | return w.buf 176 | } 177 | -------------------------------------------------------------------------------- /code_string.go: -------------------------------------------------------------------------------- 1 | // Code generated by "stringer -type Code"; DO NOT EDIT. 2 | 3 | package msgpack 4 | 5 | import "strconv" 6 | 7 | func _() { 8 | // An "invalid array index" compiler error signifies that the constant values have changed. 9 | // Re-run the stringer command to generate them again. 10 | var x [1]struct{} 11 | _ = x[InvalidCode-0] 12 | _ = x[FixMap0-128] 13 | _ = x[FixMap1-129] 14 | _ = x[FixMap2-130] 15 | _ = x[FixMap3-131] 16 | _ = x[FixMap4-132] 17 | _ = x[FixMap5-133] 18 | _ = x[FixMap6-134] 19 | _ = x[FixMap7-135] 20 | _ = x[FixMap8-136] 21 | _ = x[FixMap9-137] 22 | _ = x[FixMap10-138] 23 | _ = x[FixMap11-139] 24 | _ = x[FixMap12-140] 25 | _ = x[FixMap13-141] 26 | _ = x[FixMap14-142] 27 | _ = x[FixMap15-143] 28 | _ = x[FixArray0-144] 29 | _ = x[FixArray1-145] 30 | _ = x[FixArray2-146] 31 | _ = x[FixArray3-147] 32 | _ = x[FixArray4-148] 33 | _ = x[FixArray5-149] 34 | _ = x[FixArray6-150] 35 | _ = x[FixArray7-151] 36 | _ = x[FixArray8-152] 37 | _ = x[FixArray9-153] 38 | _ = x[FixArray10-154] 39 | _ = x[FixArray11-155] 40 | _ = x[FixArray12-156] 41 | _ = x[FixArray13-157] 42 | _ = x[FixArray14-158] 43 | _ = x[FixArray15-159] 44 | _ = x[NegFixedNumLow-224] 45 | _ = x[FixStr0-160] 46 | _ = x[FixStr1-161] 47 | _ = x[FixStr2-162] 48 | _ = x[FixStr3-163] 49 | _ = x[FixStr4-164] 50 | _ = x[FixStr5-165] 51 | _ = x[FixStr6-166] 52 | _ = x[FixStr7-167] 53 | _ = x[FixStr8-168] 54 | _ = x[FixStr9-169] 55 | _ = x[FixStr10-170] 56 | _ = x[FixStr11-171] 57 | _ = x[FixStr12-172] 58 | _ = x[FixStr13-173] 59 | _ = x[FixStr14-174] 60 | _ = x[FixStr15-175] 61 | _ = x[FixStr16-176] 62 | _ = x[FixStr17-177] 63 | _ = x[FixStr18-178] 64 | _ = x[FixStr19-179] 65 | _ = x[FixStr20-180] 66 | _ = x[FixStr21-181] 67 | _ = x[FixStr22-182] 68 | _ = x[FixStr23-183] 69 | _ = x[FixStr24-184] 70 | _ = x[FixStr25-185] 71 | _ = x[FixStr26-186] 72 | _ = x[FixStr27-187] 73 | _ = x[FixStr28-188] 74 | _ = x[FixStr29-189] 75 | _ = x[FixStr30-190] 76 | _ = x[FixStr31-191] 77 | _ = x[Nil-192] 78 | _ = x[False-194] 79 | _ = x[True-195] 80 | _ = x[Bin8-196] 81 | _ = x[Bin16-197] 82 | _ = x[Bin32-198] 83 | _ = x[Ext8-199] 84 | _ = x[Ext16-200] 85 | _ = x[Ext32-201] 86 | _ = x[Float-202] 87 | _ = x[Double-203] 88 | _ = x[Uint8-204] 89 | _ = x[Uint16-205] 90 | _ = x[Uint32-206] 91 | _ = x[Uint64-207] 92 | _ = x[Int8-208] 93 | _ = x[Int16-209] 94 | _ = x[Int32-210] 95 | _ = x[Int64-211] 96 | _ = x[FixExt1-212] 97 | _ = x[FixExt2-213] 98 | _ = x[FixExt4-214] 99 | _ = x[FixExt8-215] 100 | _ = x[FixExt16-216] 101 | _ = x[Str8-217] 102 | _ = x[Str16-218] 103 | _ = x[Str32-219] 104 | _ = x[Array16-220] 105 | _ = x[Array32-221] 106 | _ = x[Map16-222] 107 | _ = x[Map32-223] 108 | _ = x[FixedArrayMask-15] 109 | } 110 | 111 | const ( 112 | _Code_name_0 = "InvalidCode" 113 | _Code_name_1 = "FixedArrayMask" 114 | _Code_name_2 = "FixMap0FixMap1FixMap2FixMap3FixMap4FixMap5FixMap6FixMap7FixMap8FixMap9FixMap10FixMap11FixMap12FixMap13FixMap14FixMap15FixArray0FixArray1FixArray2FixArray3FixArray4FixArray5FixArray6FixArray7FixArray8FixArray9FixArray10FixArray11FixArray12FixArray13FixArray14FixArray15FixStr0FixStr1FixStr2FixStr3FixStr4FixStr5FixStr6FixStr7FixStr8FixStr9FixStr10FixStr11FixStr12FixStr13FixStr14FixStr15FixStr16FixStr17FixStr18FixStr19FixStr20FixStr21FixStr22FixStr23FixStr24FixStr25FixStr26FixStr27FixStr28FixStr29FixStr30FixStr31Nil" 115 | _Code_name_3 = "FalseTrueBin8Bin16Bin32Ext8Ext16Ext32FloatDoubleUint8Uint16Uint32Uint64Int8Int16Int32Int64FixExt1FixExt2FixExt4FixExt8FixExt16Str8Str16Str32Array16Array32Map16Map32NegFixedNumLow" 116 | ) 117 | 118 | var ( 119 | _Code_index_2 = [...]uint16{0, 7, 14, 21, 28, 35, 42, 49, 56, 63, 70, 78, 86, 94, 102, 110, 118, 127, 136, 145, 154, 163, 172, 181, 190, 199, 208, 218, 228, 238, 248, 258, 268, 275, 282, 289, 296, 303, 310, 317, 324, 331, 338, 346, 354, 362, 370, 378, 386, 394, 402, 410, 418, 426, 434, 442, 450, 458, 466, 474, 482, 490, 498, 506, 514, 517} 120 | _Code_index_3 = [...]uint8{0, 5, 9, 13, 18, 23, 27, 32, 37, 42, 48, 53, 59, 65, 71, 75, 80, 85, 90, 97, 104, 111, 118, 126, 130, 135, 140, 147, 154, 159, 164, 178} 121 | ) 122 | 123 | func (i Code) String() string { 124 | switch { 125 | case i == 0: 126 | return _Code_name_0 127 | case i == 15: 128 | return _Code_name_1 129 | case 128 <= i && i <= 192: 130 | i -= 128 131 | return _Code_name_2[_Code_index_2[i]:_Code_index_2[i+1]] 132 | case 194 <= i && i <= 224: 133 | i -= 194 134 | return _Code_name_3[_Code_index_3[i]:_Code_index_3[i+1]] 135 | default: 136 | return "Code(" + strconv.FormatInt(int64(i), 10) + ")" 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /msgpack_example_test.go: -------------------------------------------------------------------------------- 1 | package msgpack_test 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | 7 | msgpack "github.com/lestrrat-go/msgpack" 8 | "github.com/pkg/errors" 9 | ) 10 | 11 | type EventTime struct { 12 | time.Time 13 | } 14 | 15 | func init() { 16 | if err := msgpack.RegisterExt(0, EventTime{}); err != nil { 17 | panic(err) 18 | } 19 | } 20 | 21 | func (t *EventTime) DecodeMsgpack(d msgpack.Decoder) error { 22 | r := d.Reader() 23 | sec, err := r.ReadUint32() 24 | if err != nil { 25 | return errors.Wrap(err, `failed to read uint32 from first 4 bytes`) 26 | } 27 | 28 | nsec, err := r.ReadUint32() 29 | if err != nil { 30 | return errors.Wrap(err, `failed to read uint32 from second 4 bytes`) 31 | } 32 | 33 | t.Time = time.Unix(int64(sec), int64(nsec)).UTC() 34 | return nil 35 | } 36 | 37 | func (t EventTime) EncodeMsgpack(e msgpack.Encoder) error { 38 | w := e.Writer() 39 | if err := w.WriteUint32(uint32(t.Unix())); err != nil { 40 | return errors.Wrap(err, `failed to write EventTime seconds payload`) 41 | } 42 | 43 | if err := w.WriteUint32(uint32(t.Nanosecond())); err != nil { 44 | return errors.Wrap(err, `failed to write EventTime nanoseconds payload`) 45 | } 46 | 47 | return nil 48 | } 49 | 50 | type FluentdMessage struct { 51 | Tag string 52 | Time EventTime 53 | Record map[string]interface{} 54 | Option map[string]interface{} 55 | } 56 | 57 | func (m FluentdMessage) EncodeMsgpack(e msgpack.Encoder) error { 58 | if err := e.EncodeArrayHeader(4); err != nil { 59 | return errors.Wrap(err, `failed to encode array header`) 60 | } 61 | if err := e.EncodeString(m.Tag); err != nil { 62 | return errors.Wrap(err, `failed to encode tag`) 63 | } 64 | if err := e.EncodeStruct(m.Time); err != nil { 65 | return errors.Wrap(err, `failed to encode time`) 66 | } 67 | if err := e.EncodeMap(m.Record); err != nil { 68 | return errors.Wrap(err, `failed to encode record`) 69 | } 70 | if err := e.EncodeMap(m.Option); err != nil { 71 | return errors.Wrap(err, `failed to encode option`) 72 | } 73 | return nil 74 | } 75 | 76 | func (m *FluentdMessage) DecodeMsgpack(e msgpack.Decoder) error { 77 | var l int 78 | if err := e.DecodeArrayLength(&l); err != nil { 79 | return errors.Wrap(err, `failed to decode msgpack array length`) 80 | } 81 | 82 | if l != 4 { 83 | return errors.Errorf(`invalid array length %d (expected 4)`, l) 84 | } 85 | 86 | if err := e.DecodeString(&m.Tag); err != nil { 87 | return errors.Wrap(err, `failed to decode fluentd message tag`) 88 | } 89 | 90 | if err := e.DecodeStruct(&m.Time); err != nil { 91 | return errors.Wrap(err, `failed to decode fluentd time`) 92 | } 93 | 94 | if err := e.DecodeMap(&m.Record); err != nil { 95 | return errors.Wrap(err, `failed to decode fluentd record`) 96 | } 97 | 98 | if err := e.DecodeMap(&m.Option); err != nil { 99 | return errors.Wrap(err, `failed to decode fluentd option`) 100 | } 101 | 102 | return nil 103 | } 104 | 105 | func ExampleFluentdMessage() { 106 | var f1 = FluentdMessage{ 107 | Tag: "foo", 108 | Time: EventTime{Time: time.Unix(1234567890, 123).UTC()}, 109 | Record: map[string]interface{}{ 110 | "count": 1000, 111 | }, 112 | } 113 | 114 | b, err := msgpack.Marshal(f1) 115 | if err != nil { 116 | fmt.Printf("%s\n", err) 117 | return 118 | } 119 | 120 | var f2 FluentdMessage 121 | if err := msgpack.Unmarshal(b, &f2); err != nil { 122 | fmt.Printf("%s\n", err) 123 | return 124 | } 125 | 126 | fmt.Printf("%s %s %v %v\n", f2.Tag, f2.Time, f2.Record, f2.Option) 127 | // OUTPUT: 128 | // foo 2009-02-13 23:31:30.000000123 +0000 UTC map[count:1000] map[] 129 | } 130 | 131 | func ExampleEventTime() { 132 | var e1 = EventTime{Time: time.Unix(1234567890, 123).UTC()} 133 | 134 | b, err := msgpack.Marshal(e1) 135 | if err != nil { 136 | fmt.Printf("%s\n", err) 137 | return 138 | } 139 | 140 | var e2 interface{} 141 | if err := msgpack.Unmarshal(b, &e2); err != nil { 142 | fmt.Printf("%s\n", err) 143 | return 144 | } 145 | // OUTPUT: 146 | } 147 | 148 | func ExampleStructTag() { 149 | var v struct { 150 | Foo string `msgpack:"foo"` 151 | Bar string `msgpack:"bar,omitempty"` 152 | } 153 | 154 | b, err := msgpack.Marshal(v) 155 | if err != nil { 156 | fmt.Printf("%s\n", err) 157 | return 158 | } 159 | 160 | var m map[string]interface{} 161 | if err := msgpack.Unmarshal(b, &m); err != nil { 162 | fmt.Printf("%s\n", err) 163 | return 164 | } 165 | 166 | if _, ok := m["foo"]; !ok { 167 | fmt.Printf(`payload should have contained "foo"`) 168 | return 169 | } 170 | 171 | if _, ok := m["bar"]; ok { 172 | fmt.Printf(`payload should NOT contain "bar"`) 173 | return 174 | } 175 | 176 | v.Bar = "bar" 177 | 178 | b, err = msgpack.Marshal(v) 179 | if err != nil { 180 | fmt.Printf("%s\n", err) 181 | return 182 | } 183 | 184 | m = map[string]interface{}{} // reinitialize 185 | if err := msgpack.Unmarshal(b, &m); err != nil { 186 | fmt.Printf("%s\n", err) 187 | return 188 | } 189 | 190 | if _, ok := m["foo"]; !ok { 191 | fmt.Printf(`payload should have contained "foo"`) 192 | return 193 | } 194 | 195 | if _, ok := m["bar"]; !ok { 196 | fmt.Printf(`payload should have contained "bar"`) 197 | return 198 | } 199 | 200 | // OUTPUT: 201 | } 202 | -------------------------------------------------------------------------------- /encoder_container_gen.go: -------------------------------------------------------------------------------- 1 | package msgpack 2 | 3 | // Auto-generated by internal/cmd/gencontainer/gencontainer.go. DO NOT EDIT! 4 | 5 | import "github.com/pkg/errors" 6 | 7 | func (enl *encoderNL) encodeMapBool(in interface{}) error { 8 | for k, v := range in.(map[string]bool) { 9 | if err := enl.EncodeString(k); err != nil { 10 | return errors.Wrap(err, `failed to encode key`) 11 | } 12 | if err := enl.Encode(v); err != nil { 13 | return errors.Wrapf(err, `failed to encode value for %s`, k) 14 | } 15 | } 16 | return nil 17 | } 18 | 19 | func (enl *encoderNL) encodeMapInt(in interface{}) error { 20 | for k, v := range in.(map[string]int) { 21 | if err := enl.EncodeString(k); err != nil { 22 | return errors.Wrap(err, `failed to encode key`) 23 | } 24 | if err := enl.Encode(v); err != nil { 25 | return errors.Wrapf(err, `failed to encode value for %s`, k) 26 | } 27 | } 28 | return nil 29 | } 30 | 31 | func (enl *encoderNL) encodeMapInt8(in interface{}) error { 32 | for k, v := range in.(map[string]int8) { 33 | if err := enl.EncodeString(k); err != nil { 34 | return errors.Wrap(err, `failed to encode key`) 35 | } 36 | if err := enl.Encode(v); err != nil { 37 | return errors.Wrapf(err, `failed to encode value for %s`, k) 38 | } 39 | } 40 | return nil 41 | } 42 | 43 | func (enl *encoderNL) encodeMapInt16(in interface{}) error { 44 | for k, v := range in.(map[string]int16) { 45 | if err := enl.EncodeString(k); err != nil { 46 | return errors.Wrap(err, `failed to encode key`) 47 | } 48 | if err := enl.Encode(v); err != nil { 49 | return errors.Wrapf(err, `failed to encode value for %s`, k) 50 | } 51 | } 52 | return nil 53 | } 54 | 55 | func (enl *encoderNL) encodeMapInt32(in interface{}) error { 56 | for k, v := range in.(map[string]int32) { 57 | if err := enl.EncodeString(k); err != nil { 58 | return errors.Wrap(err, `failed to encode key`) 59 | } 60 | if err := enl.Encode(v); err != nil { 61 | return errors.Wrapf(err, `failed to encode value for %s`, k) 62 | } 63 | } 64 | return nil 65 | } 66 | 67 | func (enl *encoderNL) encodeMapInt64(in interface{}) error { 68 | for k, v := range in.(map[string]int64) { 69 | if err := enl.EncodeString(k); err != nil { 70 | return errors.Wrap(err, `failed to encode key`) 71 | } 72 | if err := enl.Encode(v); err != nil { 73 | return errors.Wrapf(err, `failed to encode value for %s`, k) 74 | } 75 | } 76 | return nil 77 | } 78 | 79 | func (enl *encoderNL) encodeMapUint(in interface{}) error { 80 | for k, v := range in.(map[string]uint) { 81 | if err := enl.EncodeString(k); err != nil { 82 | return errors.Wrap(err, `failed to encode key`) 83 | } 84 | if err := enl.Encode(v); err != nil { 85 | return errors.Wrapf(err, `failed to encode value for %s`, k) 86 | } 87 | } 88 | return nil 89 | } 90 | 91 | func (enl *encoderNL) encodeMapUint8(in interface{}) error { 92 | for k, v := range in.(map[string]uint8) { 93 | if err := enl.EncodeString(k); err != nil { 94 | return errors.Wrap(err, `failed to encode key`) 95 | } 96 | if err := enl.Encode(v); err != nil { 97 | return errors.Wrapf(err, `failed to encode value for %s`, k) 98 | } 99 | } 100 | return nil 101 | } 102 | 103 | func (enl *encoderNL) encodeMapUint16(in interface{}) error { 104 | for k, v := range in.(map[string]uint16) { 105 | if err := enl.EncodeString(k); err != nil { 106 | return errors.Wrap(err, `failed to encode key`) 107 | } 108 | if err := enl.Encode(v); err != nil { 109 | return errors.Wrapf(err, `failed to encode value for %s`, k) 110 | } 111 | } 112 | return nil 113 | } 114 | 115 | func (enl *encoderNL) encodeMapUint32(in interface{}) error { 116 | for k, v := range in.(map[string]uint32) { 117 | if err := enl.EncodeString(k); err != nil { 118 | return errors.Wrap(err, `failed to encode key`) 119 | } 120 | if err := enl.Encode(v); err != nil { 121 | return errors.Wrapf(err, `failed to encode value for %s`, k) 122 | } 123 | } 124 | return nil 125 | } 126 | 127 | func (enl *encoderNL) encodeMapUint64(in interface{}) error { 128 | for k, v := range in.(map[string]uint64) { 129 | if err := enl.EncodeString(k); err != nil { 130 | return errors.Wrap(err, `failed to encode key`) 131 | } 132 | if err := enl.Encode(v); err != nil { 133 | return errors.Wrapf(err, `failed to encode value for %s`, k) 134 | } 135 | } 136 | return nil 137 | } 138 | 139 | func (enl *encoderNL) encodeMapFloat32(in interface{}) error { 140 | for k, v := range in.(map[string]float32) { 141 | if err := enl.EncodeString(k); err != nil { 142 | return errors.Wrap(err, `failed to encode key`) 143 | } 144 | if err := enl.Encode(v); err != nil { 145 | return errors.Wrapf(err, `failed to encode value for %s`, k) 146 | } 147 | } 148 | return nil 149 | } 150 | 151 | func (enl *encoderNL) encodeMapFloat64(in interface{}) error { 152 | for k, v := range in.(map[string]float64) { 153 | if err := enl.EncodeString(k); err != nil { 154 | return errors.Wrap(err, `failed to encode key`) 155 | } 156 | if err := enl.Encode(v); err != nil { 157 | return errors.Wrapf(err, `failed to encode value for %s`, k) 158 | } 159 | } 160 | return nil 161 | } 162 | 163 | func (enl *encoderNL) encodeMapString(in interface{}) error { 164 | for k, v := range in.(map[string]string) { 165 | if err := enl.EncodeString(k); err != nil { 166 | return errors.Wrap(err, `failed to encode key`) 167 | } 168 | if err := enl.Encode(v); err != nil { 169 | return errors.Wrapf(err, `failed to encode value for %s`, k) 170 | } 171 | } 172 | return nil 173 | } 174 | 175 | func (enl *encoderNL) encodeArrayBool(in interface{}) error { 176 | for k, v := range in.([]bool) { 177 | if err := enl.Encode(v); err != nil { 178 | return errors.Wrapf(err, `failed to encode value for element %d`, k) 179 | } 180 | } 181 | return nil 182 | } 183 | 184 | func (enl *encoderNL) encodeArrayInt(in interface{}) error { 185 | for k, v := range in.([]int) { 186 | if err := enl.Encode(v); err != nil { 187 | return errors.Wrapf(err, `failed to encode value for element %d`, k) 188 | } 189 | } 190 | return nil 191 | } 192 | 193 | func (enl *encoderNL) encodeArrayInt8(in interface{}) error { 194 | for k, v := range in.([]int8) { 195 | if err := enl.Encode(v); err != nil { 196 | return errors.Wrapf(err, `failed to encode value for element %d`, k) 197 | } 198 | } 199 | return nil 200 | } 201 | 202 | func (enl *encoderNL) encodeArrayInt16(in interface{}) error { 203 | for k, v := range in.([]int16) { 204 | if err := enl.Encode(v); err != nil { 205 | return errors.Wrapf(err, `failed to encode value for element %d`, k) 206 | } 207 | } 208 | return nil 209 | } 210 | 211 | func (enl *encoderNL) encodeArrayInt32(in interface{}) error { 212 | for k, v := range in.([]int32) { 213 | if err := enl.Encode(v); err != nil { 214 | return errors.Wrapf(err, `failed to encode value for element %d`, k) 215 | } 216 | } 217 | return nil 218 | } 219 | 220 | func (enl *encoderNL) encodeArrayInt64(in interface{}) error { 221 | for k, v := range in.([]int64) { 222 | if err := enl.Encode(v); err != nil { 223 | return errors.Wrapf(err, `failed to encode value for element %d`, k) 224 | } 225 | } 226 | return nil 227 | } 228 | 229 | func (enl *encoderNL) encodeArrayUint(in interface{}) error { 230 | for k, v := range in.([]uint) { 231 | if err := enl.Encode(v); err != nil { 232 | return errors.Wrapf(err, `failed to encode value for element %d`, k) 233 | } 234 | } 235 | return nil 236 | } 237 | 238 | func (enl *encoderNL) encodeArrayUint8(in interface{}) error { 239 | for k, v := range in.([]uint8) { 240 | if err := enl.Encode(v); err != nil { 241 | return errors.Wrapf(err, `failed to encode value for element %d`, k) 242 | } 243 | } 244 | return nil 245 | } 246 | 247 | func (enl *encoderNL) encodeArrayUint16(in interface{}) error { 248 | for k, v := range in.([]uint16) { 249 | if err := enl.Encode(v); err != nil { 250 | return errors.Wrapf(err, `failed to encode value for element %d`, k) 251 | } 252 | } 253 | return nil 254 | } 255 | 256 | func (enl *encoderNL) encodeArrayUint32(in interface{}) error { 257 | for k, v := range in.([]uint32) { 258 | if err := enl.Encode(v); err != nil { 259 | return errors.Wrapf(err, `failed to encode value for element %d`, k) 260 | } 261 | } 262 | return nil 263 | } 264 | 265 | func (enl *encoderNL) encodeArrayUint64(in interface{}) error { 266 | for k, v := range in.([]uint64) { 267 | if err := enl.Encode(v); err != nil { 268 | return errors.Wrapf(err, `failed to encode value for element %d`, k) 269 | } 270 | } 271 | return nil 272 | } 273 | 274 | func (enl *encoderNL) encodeArrayFloat32(in interface{}) error { 275 | for k, v := range in.([]float32) { 276 | if err := enl.Encode(v); err != nil { 277 | return errors.Wrapf(err, `failed to encode value for element %d`, k) 278 | } 279 | } 280 | return nil 281 | } 282 | 283 | func (enl *encoderNL) encodeArrayFloat64(in interface{}) error { 284 | for k, v := range in.([]float64) { 285 | if err := enl.Encode(v); err != nil { 286 | return errors.Wrapf(err, `failed to encode value for element %d`, k) 287 | } 288 | } 289 | return nil 290 | } 291 | 292 | func (enl *encoderNL) encodeArrayString(in interface{}) error { 293 | for k, v := range in.([]string) { 294 | if err := enl.Encode(v); err != nil { 295 | return errors.Wrapf(err, `failed to encode value for element %d`, k) 296 | } 297 | } 298 | return nil 299 | } 300 | -------------------------------------------------------------------------------- /internal/cmd/genencoder/genencoder.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "io" 7 | "log" 8 | "os" 9 | "reflect" 10 | "sort" 11 | 12 | "github.com/lestrrat-go/msgpack/internal/util" 13 | "github.com/pkg/errors" 14 | ) 15 | 16 | type argument struct { 17 | name string 18 | typ string 19 | } 20 | 21 | type numericType struct { 22 | Code string 23 | Bits int 24 | } 25 | 26 | var floatTypes = map[reflect.Kind]numericType{ 27 | reflect.Float32: {Code: "Float", Bits: 32}, 28 | reflect.Float64: {Code: "Double", Bits: 64}, 29 | } 30 | 31 | var integerTypes = map[reflect.Kind]numericType{ 32 | reflect.Int: {Code: "Int64", Bits: 64}, 33 | reflect.Int8: {Code: "Int8", Bits: 8}, 34 | reflect.Int16: {Code: "Int16", Bits: 16}, 35 | reflect.Int32: {Code: "Int32", Bits: 32}, 36 | reflect.Int64: {Code: "Int64", Bits: 64}, 37 | reflect.Uint: {Code: "Uint64", Bits: 64}, 38 | reflect.Uint8: {Code: "Uint8", Bits: 8}, 39 | reflect.Uint16: {Code: "Uint16", Bits: 16}, 40 | reflect.Uint32: {Code: "Uint32", Bits: 32}, 41 | reflect.Uint64: {Code: "Uint64", Bits: 64}, 42 | } 43 | 44 | func main() { 45 | if err := _main(); err != nil { 46 | log.Printf("%s", err) 47 | os.Exit(1) 48 | } 49 | } 50 | 51 | func _main() error { 52 | if err := generateNumericEncoders(); err != nil { 53 | return errors.Wrap(err, `failed to generate numeric encoders`) 54 | } 55 | if err := generateLockingWrappers(); err != nil { 56 | return errors.Wrap(err, `failed to generate locking wrappers`) 57 | } 58 | return nil 59 | } 60 | 61 | func writeLockingWrapper(dst io.Writer, methodName string, args []argument, rets []string) error { 62 | fmt.Fprintf(dst, "\n\nfunc (d *encoder) %s(", methodName) 63 | for i, arg := range args { 64 | fmt.Fprintf(dst, "%s %s", arg.name, arg.typ) 65 | if i != len(args)-1 { 66 | fmt.Fprint(dst, ", ") 67 | } 68 | } 69 | fmt.Fprint(dst, ") ") 70 | 71 | if len(rets) > 1 { 72 | fmt.Fprint(dst, "(") 73 | } 74 | for i, ret := range rets { 75 | fmt.Fprint(dst, ret) 76 | if i != len(rets)-1 { 77 | fmt.Fprint(dst, ", ") 78 | } 79 | } 80 | if len(rets) > 1 { 81 | fmt.Fprint(dst, ")") 82 | } 83 | fmt.Fprint(dst, " {") 84 | fmt.Fprintf(dst, "\nd.mu.RLock()") 85 | fmt.Fprintf(dst, "\ndefer d.mu.RUnlock()") 86 | fmt.Fprintf(dst, "\nreturn d.nl.%s(", methodName) 87 | for i, arg := range args { 88 | fmt.Fprint(dst, arg.name) 89 | if i != len(args)-1 { 90 | fmt.Fprint(dst, ", ") 91 | } 92 | } 93 | fmt.Fprint(dst, ")") 94 | 95 | fmt.Fprintf(dst, "\n}") 96 | return nil 97 | } 98 | 99 | func generateLockingWrappers() error { 100 | var dst = &bytes.Buffer{} 101 | 102 | dst.WriteString("package msgpack") 103 | dst.WriteString("\n\n// Auto-generated by internal/cmd/genencoder/genencoder.go. DO NOT EDIT!") 104 | dst.WriteString("\n\nimport (") 105 | // dst.WriteString("\n\"reflect\"") 106 | dst.WriteString("\n\"time\"") 107 | dst.WriteString("\n)") 108 | 109 | wrappers := []struct { 110 | name string 111 | args []argument 112 | rets []string 113 | }{ 114 | { 115 | name: "Encode", 116 | args: []argument{ 117 | {name: "v", typ: "interface{}"}, 118 | }, 119 | rets: []string{"error"}, 120 | }, 121 | { 122 | name: "EncodeArray", 123 | args: []argument{ 124 | {name: "v", typ: "interface{}"}, 125 | }, 126 | rets: []string{"error"}, 127 | }, 128 | { 129 | name: "EncodeArrayHeader", 130 | args: []argument{ 131 | {name: "v", typ: "int"}, 132 | }, 133 | rets: []string{"error"}, 134 | }, 135 | { 136 | name: "EncodeBool", 137 | args: []argument{ 138 | {name: "v", typ: "bool"}, 139 | }, 140 | rets: []string{"error"}, 141 | }, 142 | { 143 | name: "EncodeBytes", 144 | args: []argument{ 145 | {name: "v", typ: "[]byte"}, 146 | }, 147 | rets: []string{"error"}, 148 | }, 149 | { 150 | name: "EncodeExt", 151 | args: []argument{ 152 | {name: "v", typ: "EncodeMsgpacker"}, 153 | }, 154 | rets: []string{"error"}, 155 | }, 156 | { 157 | name: "EncodeExtHeader", 158 | args: []argument{ 159 | {name: "v", typ: "int"}, 160 | }, 161 | rets: []string{"error"}, 162 | }, 163 | { 164 | name: "EncodeExtType", 165 | args: []argument{ 166 | {name: "v", typ: "EncodeMsgpacker"}, 167 | }, 168 | rets: []string{"error"}, 169 | }, 170 | { 171 | name: "EncodeMap", 172 | args: []argument{ 173 | {name: "v", typ: "interface{}"}, 174 | }, 175 | rets: []string{"error"}, 176 | }, 177 | { 178 | name: "EncodeNegativeFixNum", 179 | args: []argument{ 180 | {name: "v", typ: "int8"}, 181 | }, 182 | rets: []string{"error"}, 183 | }, 184 | { 185 | name: "EncodeNil", 186 | rets: []string{"error"}, 187 | }, 188 | { 189 | name: "EncodePositiveFixNum", 190 | args: []argument{ 191 | {name: "v", typ: "uint8"}, 192 | }, 193 | rets: []string{"error"}, 194 | }, 195 | { 196 | name: "EncodeString", 197 | args: []argument{ 198 | {name: "v", typ: "string"}, 199 | }, 200 | rets: []string{"error"}, 201 | }, 202 | { 203 | name: "EncodeStruct", 204 | args: []argument{ 205 | {name: "v", typ: "interface{}"}, 206 | }, 207 | rets: []string{"error"}, 208 | }, 209 | { 210 | name: "EncodeTime", 211 | args: []argument{ 212 | {name: "v", typ: "time.Time"}, 213 | }, 214 | rets: []string{"error"}, 215 | }, 216 | { 217 | name: "Writer", 218 | rets: []string{"Writer"}, 219 | }, 220 | } 221 | 222 | for _, w := range wrappers { 223 | writeLockingWrapper(dst, w.name, w.args, w.rets) 224 | } 225 | 226 | // numeric stuff 227 | keys := make([]reflect.Kind, 0, len(integerTypes)+len(floatTypes)) 228 | for k := range integerTypes { 229 | keys = append(keys, k) 230 | } 231 | for k := range floatTypes { 232 | keys = append(keys, k) 233 | } 234 | 235 | sort.Slice(keys, func(i, j int) bool { 236 | return uint(keys[i]) < uint(keys[j]) 237 | }) 238 | 239 | for _, typ := range keys { 240 | writeLockingWrapper( 241 | dst, 242 | fmt.Sprintf("Encode%s", util.Ucfirst(typ.String())), 243 | []argument{ 244 | {name: "v", typ: typ.String()}, 245 | }, 246 | []string{"error"}, 247 | ) 248 | } 249 | 250 | if err := util.WriteFormattedFile("encoder_locking_gen.go", dst.Bytes()); err != nil { 251 | return errors.Wrap(err, `failed to write to file`) 252 | } 253 | return nil 254 | } 255 | 256 | func generateNumericEncoders() error { 257 | var buf bytes.Buffer 258 | 259 | buf.WriteString("package msgpack") 260 | buf.WriteString("\n\n// Auto-generated by internal/cmd/genencoder/genencoder.go. DO NOT EDIT!") 261 | buf.WriteString("\n\nimport (") 262 | buf.WriteString("\n\"math\"") 263 | buf.WriteString("\n\n\"github.com/pkg/errors\"") 264 | buf.WriteString("\n)") 265 | 266 | if err := generateIntegerTypes(&buf); err != nil { 267 | return errors.Wrap(err, `failed to generate integer encoders`) 268 | } 269 | 270 | if err := generateFloatTypes(&buf); err != nil { 271 | return errors.Wrap(err, `failed to generate float encoders`) 272 | } 273 | 274 | if err := util.WriteFormattedFile("encoder_numeric_gen.go", buf.Bytes()); err != nil { 275 | return errors.Wrap(err, `failed to write to file`) 276 | } 277 | return nil 278 | } 279 | 280 | func generateIntegerTypes(dst io.Writer) error { 281 | types := integerTypes 282 | 283 | keys := make([]reflect.Kind, 0, len(types)) 284 | for k := range types { 285 | keys = append(keys, k) 286 | } 287 | sort.Slice(keys, func(i, j int) bool { 288 | return uint(keys[i]) < uint(keys[j]) 289 | }) 290 | for _, typ := range keys { 291 | data := types[typ] 292 | fmt.Fprintf(dst, "\n\nfunc (enl *encoderNL) Encode%s(v %s) error {", util.Ucfirst(typ.String()), typ) 293 | switch typ { 294 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: 295 | fmt.Fprintf(dst, "\nif inPositiveFixNumRange(int64(v)) {") 296 | fmt.Fprintf(dst, "\nreturn enl.encodePositiveFixNum(uint8(0xff & v))") 297 | fmt.Fprintf(dst, "\n}") 298 | case reflect.Int8: 299 | fmt.Fprintf(dst, "\nif inNegativeFixNumRange(int64(v)) {") 300 | fmt.Fprintf(dst, "\nreturn enl.encodeNegativeFixNum(v)") 301 | fmt.Fprintf(dst, "\n}") 302 | default: 303 | fmt.Fprintf(dst, "\nif inNegativeFixNumRange(int64(v)) {") 304 | fmt.Fprintf(dst, "\nreturn enl.encodeNegativeFixNum(int8(byte(0xff &v)))") 305 | fmt.Fprintf(dst, "\n}") 306 | } 307 | 308 | fmt.Fprintf(dst, "\n\nif err := enl.dst.WriteByteUint%d(%s.Byte(), ", data.Bits, data.Code) 309 | switch typ { 310 | case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: 311 | fmt.Fprintf(dst, "v") 312 | default: 313 | fmt.Fprintf(dst, "uint%d(v)", data.Bits) 314 | } 315 | fmt.Fprintf(dst, "); err != nil {") 316 | fmt.Fprintf(dst, "\nreturn errors.Wrap(err, `msgpack: failed to write %s`)", data.Code) 317 | fmt.Fprintf(dst, "\n}") 318 | fmt.Fprintf(dst, "\nreturn nil") 319 | fmt.Fprintf(dst, "\n}") 320 | } 321 | return nil 322 | } 323 | 324 | func generateFloatTypes(dst io.Writer) error { 325 | types := floatTypes 326 | keys := make([]reflect.Kind, 0, len(types)) 327 | for k := range types { 328 | keys = append(keys, k) 329 | } 330 | sort.Slice(keys, func(i, j int) bool { 331 | return uint(keys[i]) < uint(keys[j]) 332 | }) 333 | for _, typ := range keys { 334 | data := types[typ] 335 | fmt.Fprintf(dst, "\n\nfunc (enl *encoderNL) EncodeFloat%d(f float%d) error {", data.Bits, data.Bits) 336 | fmt.Fprintf(dst, "\nif err := enl.dst.WriteByteUint%d(%s.Byte(), math.Float%dbits(f)); err != nil {", data.Bits, data.Code, data.Bits) 337 | fmt.Fprintf(dst, "\nreturn errors.Wrap(err, `msgpack: failed to write %s`)", data.Code) 338 | fmt.Fprintf(dst, "\n}") 339 | fmt.Fprintf(dst, "\nreturn nil") 340 | fmt.Fprintf(dst, "\n}") 341 | } 342 | return nil 343 | } 344 | -------------------------------------------------------------------------------- /interface.go: -------------------------------------------------------------------------------- 1 | package msgpack 2 | 3 | import ( 4 | "bufio" 5 | "io" 6 | "reflect" 7 | "sync" 8 | "time" 9 | ) 10 | 11 | const MaxPositiveFixNum = byte(0x7f) 12 | const MinNegativeFixNum = byte(0xe0) 13 | 14 | // Code represents the first by in a msgpack element. It tell us 15 | // the data layout that follows it 16 | type Code byte 17 | 18 | const ( 19 | InvalidCode Code = 0 20 | FixMap0 Code = 0x80 21 | FixMap1 Code = 0x81 22 | FixMap2 Code = 0x82 23 | FixMap3 Code = 0x83 24 | FixMap4 Code = 0x84 25 | FixMap5 Code = 0x85 26 | FixMap6 Code = 0x86 27 | FixMap7 Code = 0x87 28 | FixMap8 Code = 0x88 29 | FixMap9 Code = 0x89 30 | FixMap10 Code = 0x8a 31 | FixMap11 Code = 0x8b 32 | FixMap12 Code = 0x8c 33 | FixMap13 Code = 0x8d 34 | FixMap14 Code = 0x8e 35 | FixMap15 Code = 0x8f 36 | FixArray0 Code = 0x90 37 | FixArray1 Code = 0x91 38 | FixArray2 Code = 0x92 39 | FixArray3 Code = 0x93 40 | FixArray4 Code = 0x94 41 | FixArray5 Code = 0x95 42 | FixArray6 Code = 0x96 43 | FixArray7 Code = 0x97 44 | FixArray8 Code = 0x98 45 | FixArray9 Code = 0x99 46 | FixArray10 Code = 0x9a 47 | FixArray11 Code = 0x9b 48 | FixArray12 Code = 0x9c 49 | FixArray13 Code = 0x9d 50 | FixArray14 Code = 0x9e 51 | FixArray15 Code = 0x9f 52 | NegFixedNumLow Code = 0xe0 53 | FixStr0 Code = 0xa0 54 | FixStr1 Code = 0xa1 55 | FixStr2 Code = 0xa2 56 | FixStr3 Code = 0xa3 57 | FixStr4 Code = 0xa4 58 | FixStr5 Code = 0xa5 59 | FixStr6 Code = 0xa6 60 | FixStr7 Code = 0xa7 61 | FixStr8 Code = 0xa8 62 | FixStr9 Code = 0xa9 63 | FixStr10 Code = 0xaa 64 | FixStr11 Code = 0xab 65 | FixStr12 Code = 0xac 66 | FixStr13 Code = 0xad 67 | FixStr14 Code = 0xae 68 | FixStr15 Code = 0xaf 69 | FixStr16 Code = 0xb0 70 | FixStr17 Code = 0xb1 71 | FixStr18 Code = 0xb2 72 | FixStr19 Code = 0xb3 73 | FixStr20 Code = 0xb4 74 | FixStr21 Code = 0xb5 75 | FixStr22 Code = 0xb6 76 | FixStr23 Code = 0xb7 77 | FixStr24 Code = 0xb8 78 | FixStr25 Code = 0xb9 79 | FixStr26 Code = 0xba 80 | FixStr27 Code = 0xbb 81 | FixStr28 Code = 0xbc 82 | FixStr29 Code = 0xbd 83 | FixStr30 Code = 0xbe 84 | FixStr31 Code = 0xbf 85 | Nil Code = 0xc0 86 | False Code = 0xc2 87 | True Code = 0xc3 88 | Bin8 Code = 0xc4 89 | Bin16 Code = 0xc5 90 | Bin32 Code = 0xc6 91 | Ext8 Code = 0xc7 92 | Ext16 Code = 0xc8 93 | Ext32 Code = 0xc9 94 | Float Code = 0xca 95 | Double Code = 0xcb 96 | Uint8 Code = 0xcc 97 | Uint16 Code = 0xcd 98 | Uint32 Code = 0xce 99 | Uint64 Code = 0xcf 100 | Int8 Code = 0xd0 101 | Int16 Code = 0xd1 102 | Int32 Code = 0xd2 103 | Int64 Code = 0xd3 104 | FixExt1 Code = 0xd4 105 | FixExt2 Code = 0xd5 106 | FixExt4 Code = 0xd6 107 | FixExt8 Code = 0xd7 108 | FixExt16 Code = 0xd8 109 | Str8 Code = 0xd9 110 | Str16 Code = 0xda 111 | Str32 Code = 0xdb 112 | Array16 Code = 0xdc 113 | Array32 Code = 0xdd 114 | Map16 Code = 0xde 115 | Map32 Code = 0xdf 116 | FixedArrayMask Code = 0xf 117 | ) 118 | 119 | type InvalidDecodeError struct { 120 | Type reflect.Type 121 | } 122 | 123 | // EncodeMsgpacker is an interface for those objects that provide 124 | // their own serialization. The objects are responsible for providing 125 | // the complete msgpack payload, including the code, payload length 126 | // (if applicable), and payload (if applicable) 127 | // 128 | // The Encoder instance that is passed is NOT safe to be used 129 | // concurrently with other goroutines. DO NOT share it between multiple 130 | // goroutines, and DO NOT attempt to use it once you return from 131 | // your DecodeMsgpack method. 132 | type EncodeMsgpacker interface { 133 | EncodeMsgpack(Encoder) error 134 | } 135 | 136 | // DecodeMsgpacker is an interface for those objects that provide 137 | // their own deserialization. The objects are responsible for handling 138 | // the code, payload length (if applicable), and payload (if applicable) 139 | // 140 | // The Decoder instance that is passed is NOT safe to be used 141 | // concurrently with other goroutines. DO NOT share it between multiple 142 | // goroutines, and DO NOT attempt to use it once you return from 143 | // your DecodeMsgpack method. 144 | type DecodeMsgpacker interface { 145 | DecodeMsgpack(Decoder) error 146 | } 147 | 148 | // ArrayBuilder is used to build a msgpack array 149 | type ArrayBuilder interface { 150 | Add(interface{}) 151 | Bytes() ([]byte, error) 152 | Count() int 153 | Encode(io.Writer) error 154 | Reset() 155 | } 156 | 157 | // MapBuilder is used to build a msgpack map 158 | type MapBuilder interface { 159 | Add(string, interface{}) 160 | Bytes() ([]byte, error) 161 | Count() int 162 | Encode(io.Writer) error 163 | Reset() 164 | } 165 | 166 | // Writer handles low-level writing to an io.Writer. 167 | // Note that Writers are NEVER meant to be shared concurrently 168 | // between goroutines. You DO NOT write serialized data concurrently 169 | // to the same destination. 170 | type Writer interface { 171 | io.Writer 172 | WriteByte(byte) error 173 | WriteByteUint8(byte, uint8) error 174 | WriteByteUint16(byte, uint16) error 175 | WriteByteUint32(byte, uint32) error 176 | WriteByteUint64(byte, uint64) error 177 | WriteString(string) (int, error) 178 | WriteUint8(uint8) error 179 | WriteUint16(uint16) error 180 | WriteUint32(uint32) error 181 | WriteUint64(uint64) error 182 | } 183 | 184 | // Reader handles low-level reading from an io.Reader. 185 | // Note that Readers are NEVER meant to be shared concurrently 186 | // between goroutines. You DO NOT read data concurrently 187 | // from the same serialized source. 188 | type Reader interface { 189 | io.Reader 190 | ReadByte() (byte, error) 191 | ReadUint8() (uint8, error) 192 | ReadUint16() (uint16, error) 193 | ReadUint32() (uint32, error) 194 | ReadUint64() (uint64, error) 195 | ReadByteUint8() (byte, uint8, error) 196 | ReadByteUint16() (byte, uint16, error) 197 | ReadByteUint32() (byte, uint32, error) 198 | ReadByteUint64() (byte, uint64, error) 199 | } 200 | 201 | // Encoder writes serialized data to a destination pointed to by 202 | // an io.Writer 203 | type Encoder interface { 204 | Encode(interface{}) error 205 | EncodeArrayHeader(int) error 206 | EncodeArray(interface{}) error 207 | EncodeBool(bool) error 208 | EncodeBytes([]byte) error 209 | EncodeExt(EncodeMsgpacker) error 210 | EncodeExtHeader(int) error 211 | EncodeExtType(EncodeMsgpacker) error 212 | EncodeMap(interface{}) error 213 | EncodeNegativeFixNum(int8) error 214 | EncodeNil() error 215 | EncodePositiveFixNum(uint8) error 216 | EncodeInt(int) error 217 | EncodeInt8(int8) error 218 | EncodeInt16(int16) error 219 | EncodeInt32(int32) error 220 | EncodeInt64(int64) error 221 | EncodeUint(uint) error 222 | EncodeUint8(uint8) error 223 | EncodeUint16(uint16) error 224 | EncodeUint32(uint32) error 225 | EncodeUint64(uint64) error 226 | EncodeFloat32(float32) error 227 | EncodeFloat64(float64) error 228 | EncodeString(string) error 229 | EncodeStruct(interface{}) error 230 | EncodeTime(time.Time) error 231 | Writer() Writer 232 | 233 | // SetDestination is a utility tool that allows the user to swap out the 234 | // reader object the Encoder is writing to, there by saving the 235 | // extra cost of re-instantiaion. 236 | SetDestination(io.Writer) 237 | } 238 | 239 | type encoder struct { 240 | nl *encoderNL 241 | mu sync.RWMutex 242 | } 243 | 244 | type encoderNL struct { 245 | dst Writer 246 | } 247 | 248 | // Decoder reads serialized data from a source pointed to by 249 | // an io.Reader, and meterializes the data structure 250 | type Decoder interface { 251 | // Decode takes a pointer to a variable, and populates it with the value 252 | // that was unmarshaled from the stream. 253 | // 254 | // If the variable is a non-pointer or nil, an error is returned. 255 | Decode(interface{}) error 256 | DecodeArray(interface{}) error 257 | DecodeArrayLength(*int) error 258 | DecodeBool(b *bool) error 259 | DecodeBytes(*[]byte) error 260 | DecodeExt(DecodeMsgpacker) error 261 | DecodeExtLength(*int) error 262 | DecodeExtType(*reflect.Type) error 263 | DecodeFloat32(*float32) error 264 | DecodeFloat64(*float64) error 265 | DecodeInt(*int) error 266 | DecodeInt8(*int8) error 267 | DecodeInt16(*int16) error 268 | DecodeInt32(*int32) error 269 | DecodeInt64(*int64) error 270 | DecodeMap(*map[string]interface{}) error 271 | DecodeMapLength(*int) error 272 | DecodeNil(*interface{}) error 273 | DecodeString(*string) error 274 | DecodeStruct(interface{}) error 275 | DecodeTime(*time.Time) error 276 | DecodeUint(*uint) error 277 | DecodeUint8(*uint8) error 278 | DecodeUint16(*uint16) error 279 | DecodeUint32(*uint32) error 280 | DecodeUint64(*uint64) error 281 | PeekCode() (Code, error) 282 | ReadCode() (Code, error) 283 | Reader() Reader 284 | 285 | // SetSource is a utility tool that allows the user to swap out the 286 | // reader object the Decoder is reading from, there by saving the 287 | // extra cost of re-instantiaion. 288 | SetSource(io.Reader) 289 | } 290 | 291 | type decoder struct { 292 | nl *decoderNL 293 | mu sync.RWMutex 294 | } 295 | 296 | // decoderNL is a type of decoder that does no locking of 297 | // the member fields when public methods are called. 298 | // in contrast, calling public methods for the equivalent 299 | // locking version will force other method calls to wait while 300 | // an operation is progressing on the object. 301 | type decoderNL struct { 302 | raw *bufio.Reader 303 | src Reader 304 | } 305 | -------------------------------------------------------------------------------- /internal/cmd/gendecoder/gendecoder.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "io" 7 | "log" 8 | "os" 9 | "reflect" 10 | "sort" 11 | 12 | "github.com/lestrrat-go/msgpack/internal/util" 13 | "github.com/pkg/errors" 14 | ) 15 | 16 | type argument struct { 17 | name string 18 | typ string 19 | } 20 | type numericType struct { 21 | Code string 22 | Bits int 23 | Unsigned bool 24 | } 25 | 26 | var floatTypes = map[reflect.Kind]numericType{ 27 | reflect.Float32: {Code: "Float", Bits: 32}, 28 | reflect.Float64: {Code: "Double", Bits: 64}, 29 | } 30 | var integerTypes = map[reflect.Kind]numericType{ 31 | reflect.Int: {Code: "Int64", Bits: 64}, 32 | reflect.Int8: {Code: "Int8", Bits: 8}, 33 | reflect.Int16: {Code: "Int16", Bits: 16}, 34 | reflect.Int32: {Code: "Int32", Bits: 32}, 35 | reflect.Int64: {Code: "Int64", Bits: 64}, 36 | reflect.Uint: {Code: "Uint64", Bits: 64, Unsigned: true}, 37 | reflect.Uint8: {Code: "Uint8", Bits: 8, Unsigned: true}, 38 | reflect.Uint16: {Code: "Uint16", Bits: 16, Unsigned: true}, 39 | reflect.Uint32: {Code: "Uint32", Bits: 32, Unsigned: true}, 40 | reflect.Uint64: {Code: "Uint64", Bits: 64, Unsigned: true}, 41 | } 42 | 43 | func main() { 44 | if err := _main(); err != nil { 45 | log.Printf("%s", err) 46 | os.Exit(1) 47 | } 48 | } 49 | 50 | func _main() error { 51 | if err := generateNumericDecoders(); err != nil { 52 | return errors.Wrap(err, `failed to generate numeric decoders`) 53 | } 54 | 55 | if err := generateLockingWrappers(); err != nil { 56 | return errors.Wrap(err, `failed to generate locking wrappers`) 57 | } 58 | return nil 59 | } 60 | 61 | func writeLockingWrapper(dst io.Writer, methodName string, args []argument, rets []string) error { 62 | fmt.Fprintf(dst, "\n\nfunc (d *decoder) %s(", methodName) 63 | for i, arg := range args { 64 | fmt.Fprintf(dst, "%s %s", arg.name, arg.typ) 65 | if i != len(args)-1 { 66 | fmt.Fprint(dst, ", ") 67 | } 68 | } 69 | fmt.Fprint(dst, ") ") 70 | 71 | if len(rets) > 1 { 72 | fmt.Fprint(dst, "(") 73 | } 74 | for i, ret := range rets { 75 | fmt.Fprint(dst, ret) 76 | if i != len(rets)-1 { 77 | fmt.Fprint(dst, ", ") 78 | } 79 | } 80 | if len(rets) > 1 { 81 | fmt.Fprint(dst, ")") 82 | } 83 | fmt.Fprint(dst, " {") 84 | fmt.Fprintf(dst, "\nd.mu.RLock()") 85 | fmt.Fprintf(dst, "\ndefer d.mu.RUnlock()") 86 | fmt.Fprintf(dst, "\nreturn d.nl.%s(", methodName) 87 | for i, arg := range args { 88 | fmt.Fprint(dst, arg.name) 89 | if i != len(args)-1 { 90 | fmt.Fprint(dst, ", ") 91 | } 92 | } 93 | fmt.Fprint(dst, ")") 94 | 95 | fmt.Fprintf(dst, "\n}") 96 | return nil 97 | } 98 | 99 | func generateLockingWrappers() error { 100 | var dst = &bytes.Buffer{} 101 | 102 | dst.WriteString("package msgpack") 103 | dst.WriteString("\n\n// Auto-generated by internal/cmd/gendecoder/gendecoder.go. DO NOT EDIT!") 104 | dst.WriteString("\n\nimport (") 105 | dst.WriteString("\n\"reflect\"") 106 | dst.WriteString("\n\"time\"") 107 | dst.WriteString("\n)") 108 | 109 | wrappers := []struct { 110 | name string 111 | args []argument 112 | rets []string 113 | }{ 114 | { 115 | name: "Decode", 116 | args: []argument{ 117 | {name: "v", typ: "interface{}"}, 118 | }, 119 | rets: []string{"error"}, 120 | }, 121 | { 122 | name: "DecodeArray", 123 | args: []argument{ 124 | {name: "v", typ: "interface{}"}, 125 | }, 126 | rets: []string{"error"}, 127 | }, 128 | { 129 | name: "DecodeArrayLength", 130 | args: []argument{ 131 | {name: "v", typ: "*int"}, 132 | }, 133 | rets: []string{"error"}, 134 | }, 135 | { 136 | name: "DecodeBool", 137 | args: []argument{ 138 | {name: "v", typ: "*bool"}, 139 | }, 140 | rets: []string{"error"}, 141 | }, 142 | { 143 | name: "DecodeBytes", 144 | args: []argument{ 145 | {name: "v", typ: "*[]byte"}, 146 | }, 147 | rets: []string{"error"}, 148 | }, 149 | { 150 | name: "DecodeExt", 151 | args: []argument{ 152 | {name: "v", typ: "DecodeMsgpacker"}, 153 | }, 154 | rets: []string{"error"}, 155 | }, 156 | { 157 | name: "DecodeExtLength", 158 | args: []argument{ 159 | {name: "v", typ: "*int"}, 160 | }, 161 | rets: []string{"error"}, 162 | }, 163 | { 164 | name: "DecodeExtType", 165 | args: []argument{ 166 | {name: "v", typ: "*reflect.Type"}, 167 | }, 168 | rets: []string{"error"}, 169 | }, 170 | { 171 | name: "DecodeMap", 172 | args: []argument{ 173 | {name: "v", typ: "*map[string]interface{}"}, 174 | }, 175 | rets: []string{"error"}, 176 | }, 177 | { 178 | name: "DecodeMapLength", 179 | args: []argument{ 180 | {name: "v", typ: "*int"}, 181 | }, 182 | rets: []string{"error"}, 183 | }, 184 | { 185 | name: "DecodeNil", 186 | args: []argument{ 187 | {name: "v", typ: "*interface{}"}, 188 | }, 189 | rets: []string{"error"}, 190 | }, 191 | { 192 | name: "DecodeString", 193 | args: []argument{ 194 | {name: "v", typ: "*string"}, 195 | }, 196 | rets: []string{"error"}, 197 | }, 198 | { 199 | name: "DecodeStruct", 200 | args: []argument{ 201 | {name: "v", typ: "interface{}"}, 202 | }, 203 | rets: []string{"error"}, 204 | }, 205 | { 206 | name: "DecodeTime", 207 | args: []argument{ 208 | {name: "v", typ: "*time.Time"}, 209 | }, 210 | rets: []string{"error"}, 211 | }, 212 | { 213 | name: "PeekCode", 214 | rets: []string{"Code", "error"}, 215 | }, 216 | { 217 | name: "ReadCode", 218 | rets: []string{"Code", "error"}, 219 | }, 220 | { 221 | name: "Reader", 222 | rets: []string{"Reader"}, 223 | }, 224 | } 225 | 226 | for _, w := range wrappers { 227 | writeLockingWrapper(dst, w.name, w.args, w.rets) 228 | } 229 | // numeric stuff 230 | keys := make([]reflect.Kind, 0, len(integerTypes)+len(floatTypes)) 231 | for k := range integerTypes { 232 | keys = append(keys, k) 233 | } 234 | for k := range floatTypes { 235 | keys = append(keys, k) 236 | } 237 | 238 | sort.Slice(keys, func(i, j int) bool { 239 | return uint(keys[i]) < uint(keys[j]) 240 | }) 241 | 242 | for _, typ := range keys { 243 | writeLockingWrapper( 244 | dst, 245 | fmt.Sprintf("Decode%s", util.Ucfirst(typ.String())), 246 | []argument{ 247 | {name: "v", typ: "*" + typ.String()}, 248 | }, 249 | []string{"error"}, 250 | ) 251 | } 252 | 253 | if err := util.WriteFormattedFile("decoder_locking_gen.go", dst.Bytes()); err != nil { 254 | return errors.Wrap(err, `failed to write to file`) 255 | } 256 | return nil 257 | } 258 | 259 | func generateNumericDecoders() error { 260 | 261 | var buf bytes.Buffer 262 | 263 | buf.WriteString("package msgpack") 264 | buf.WriteString("\n\n// Auto-generated by internal/cmd/gendecoder/gendecoder.go. DO NOT EDIT!") 265 | buf.WriteString("\n\nimport (") 266 | buf.WriteString("\n\"math\"") 267 | buf.WriteString("\n\n\"github.com/pkg/errors\"") 268 | buf.WriteString("\n)") 269 | 270 | if err := generateIntegerTypes(&buf); err != nil { 271 | return errors.Wrap(err, `failed to generate integer decoders`) 272 | } 273 | 274 | if err := generateFloatTypes(&buf); err != nil { 275 | return errors.Wrap(err, `failed to generate float decoders`) 276 | } 277 | 278 | if err := util.WriteFormattedFile("decoder_numeric_gen.go", buf.Bytes()); err != nil { 279 | return errors.Wrap(err, `failed to write to file`) 280 | } 281 | return nil 282 | } 283 | 284 | func generateIntegerTypes(dst io.Writer) error { 285 | types := integerTypes 286 | 287 | keys := make([]reflect.Kind, 0, len(types)) 288 | for k := range types { 289 | keys = append(keys, k) 290 | } 291 | sort.Slice(keys, func(i, j int) bool { 292 | return uint(keys[i]) < uint(keys[j]) 293 | }) 294 | for _, typ := range keys { 295 | data := types[typ] 296 | fmt.Fprintf(dst, "\n\nfunc (dnl *decoderNL) Decode%s(v *%s) error {", util.Ucfirst(typ.String()), typ) 297 | fmt.Fprintf(dst, "\ncode, err := dnl.src.ReadByte()") 298 | fmt.Fprintf(dst, "\nif err != nil {") 299 | fmt.Fprintf(dst, "\nreturn errors.Wrap(err, `msgpack: failed to read code for %s`)", data.Code) 300 | fmt.Fprintf(dst, "\n}") 301 | fmt.Fprintf(dst, "\nif IsFixNumFamily(Code(code)) {") 302 | fmt.Fprintf(dst, "\n*v = %s(code)", typ) 303 | fmt.Fprintf(dst, "\nreturn nil") 304 | fmt.Fprintf(dst, "\n}") 305 | // We need to allow numbers with lower bit sizes that fit in this type 306 | var baseName string 307 | if data.Unsigned { 308 | baseName = "Uint" 309 | } else { 310 | baseName = "Int" 311 | } 312 | fmt.Fprintf(dst, "\nswitch Code(code) {") 313 | for size := data.Bits; size >= 8; size /= 2 { 314 | fmt.Fprintf(dst, "\ncase %s%d:", baseName, size) 315 | fmt.Fprintf(dst, "\nx, err := dnl.src.ReadUint%d()", size) 316 | fmt.Fprintf(dst, "\nif err != nil {") 317 | fmt.Fprintf(dst, "\nreturn errors.Wrap(err, `msgpack: failed to read payload for %s`)", typ) 318 | fmt.Fprintf(dst, "\n}") 319 | fmt.Fprintf(dst, "\n*v = %s(x)", typ) 320 | fmt.Fprintf(dst, "\nreturn nil") 321 | } 322 | fmt.Fprintf(dst, "\n}") // end switch Code(code) 323 | fmt.Fprintf(dst, "\nreturn errors.Errorf(`msgpack: invalid numeric type %%s for %s`, Code(code))", typ) 324 | fmt.Fprintf(dst, "\n}") 325 | } 326 | return nil 327 | } 328 | 329 | func generateFloatTypes(dst io.Writer) error { 330 | types := floatTypes 331 | 332 | keys := make([]reflect.Kind, 0, len(types)) 333 | for k := range types { 334 | keys = append(keys, k) 335 | } 336 | sort.Slice(keys, func(i, j int) bool { 337 | return uint(keys[i]) < uint(keys[j]) 338 | }) 339 | for _, typ := range keys { 340 | data := types[typ] 341 | 342 | fmt.Fprintf(dst, "\n\nfunc (dnl *decoderNL) Decode%s(v *%s) error {", util.Ucfirst(typ.String()), typ) 343 | fmt.Fprintf(dst, "\ncode, x, err := dnl.src.ReadByteUint%d()", data.Bits) 344 | fmt.Fprintf(dst, "\nif err != nil {") 345 | fmt.Fprintf(dst, "\nreturn errors.Wrap(err, `msgpack: failed to read %s`)", typ) 346 | fmt.Fprintf(dst, "\n}") 347 | fmt.Fprintf(dst, "\n\nif code != %s.Byte() {", data.Code) 348 | fmt.Fprintf(dst, "\nreturn errors.Errorf(`msgpack: expected %s, got %%s`, Code(code))", data.Code) 349 | fmt.Fprintf(dst, "\n}") 350 | fmt.Fprintf(dst, "\n\n*v = math.Float%dfrombits(x)", data.Bits) 351 | fmt.Fprintf(dst, "\nreturn nil") 352 | fmt.Fprintf(dst, "\n}") 353 | } 354 | return nil 355 | } 356 | -------------------------------------------------------------------------------- /decoder_numeric_gen.go: -------------------------------------------------------------------------------- 1 | package msgpack 2 | 3 | // Auto-generated by internal/cmd/gendecoder/gendecoder.go. DO NOT EDIT! 4 | 5 | import ( 6 | "math" 7 | 8 | "github.com/pkg/errors" 9 | ) 10 | 11 | func (dnl *decoderNL) DecodeInt(v *int) error { 12 | code, err := dnl.src.ReadByte() 13 | if err != nil { 14 | return errors.Wrap(err, `msgpack: failed to read code for Int64`) 15 | } 16 | if IsFixNumFamily(Code(code)) { 17 | *v = int(code) 18 | return nil 19 | } 20 | switch Code(code) { 21 | case Int64: 22 | x, err := dnl.src.ReadUint64() 23 | if err != nil { 24 | return errors.Wrap(err, `msgpack: failed to read payload for int`) 25 | } 26 | *v = int(x) 27 | return nil 28 | case Int32: 29 | x, err := dnl.src.ReadUint32() 30 | if err != nil { 31 | return errors.Wrap(err, `msgpack: failed to read payload for int`) 32 | } 33 | *v = int(x) 34 | return nil 35 | case Int16: 36 | x, err := dnl.src.ReadUint16() 37 | if err != nil { 38 | return errors.Wrap(err, `msgpack: failed to read payload for int`) 39 | } 40 | *v = int(x) 41 | return nil 42 | case Int8: 43 | x, err := dnl.src.ReadUint8() 44 | if err != nil { 45 | return errors.Wrap(err, `msgpack: failed to read payload for int`) 46 | } 47 | *v = int(x) 48 | return nil 49 | } 50 | return errors.Errorf(`msgpack: invalid numeric type %s for int`, Code(code)) 51 | } 52 | 53 | func (dnl *decoderNL) DecodeInt8(v *int8) error { 54 | code, err := dnl.src.ReadByte() 55 | if err != nil { 56 | return errors.Wrap(err, `msgpack: failed to read code for Int8`) 57 | } 58 | if IsFixNumFamily(Code(code)) { 59 | *v = int8(code) 60 | return nil 61 | } 62 | switch Code(code) { 63 | case Int8: 64 | x, err := dnl.src.ReadUint8() 65 | if err != nil { 66 | return errors.Wrap(err, `msgpack: failed to read payload for int8`) 67 | } 68 | *v = int8(x) 69 | return nil 70 | } 71 | return errors.Errorf(`msgpack: invalid numeric type %s for int8`, Code(code)) 72 | } 73 | 74 | func (dnl *decoderNL) DecodeInt16(v *int16) error { 75 | code, err := dnl.src.ReadByte() 76 | if err != nil { 77 | return errors.Wrap(err, `msgpack: failed to read code for Int16`) 78 | } 79 | if IsFixNumFamily(Code(code)) { 80 | *v = int16(code) 81 | return nil 82 | } 83 | switch Code(code) { 84 | case Int16: 85 | x, err := dnl.src.ReadUint16() 86 | if err != nil { 87 | return errors.Wrap(err, `msgpack: failed to read payload for int16`) 88 | } 89 | *v = int16(x) 90 | return nil 91 | case Int8: 92 | x, err := dnl.src.ReadUint8() 93 | if err != nil { 94 | return errors.Wrap(err, `msgpack: failed to read payload for int16`) 95 | } 96 | *v = int16(x) 97 | return nil 98 | } 99 | return errors.Errorf(`msgpack: invalid numeric type %s for int16`, Code(code)) 100 | } 101 | 102 | func (dnl *decoderNL) DecodeInt32(v *int32) error { 103 | code, err := dnl.src.ReadByte() 104 | if err != nil { 105 | return errors.Wrap(err, `msgpack: failed to read code for Int32`) 106 | } 107 | if IsFixNumFamily(Code(code)) { 108 | *v = int32(code) 109 | return nil 110 | } 111 | switch Code(code) { 112 | case Int32: 113 | x, err := dnl.src.ReadUint32() 114 | if err != nil { 115 | return errors.Wrap(err, `msgpack: failed to read payload for int32`) 116 | } 117 | *v = int32(x) 118 | return nil 119 | case Int16: 120 | x, err := dnl.src.ReadUint16() 121 | if err != nil { 122 | return errors.Wrap(err, `msgpack: failed to read payload for int32`) 123 | } 124 | *v = int32(x) 125 | return nil 126 | case Int8: 127 | x, err := dnl.src.ReadUint8() 128 | if err != nil { 129 | return errors.Wrap(err, `msgpack: failed to read payload for int32`) 130 | } 131 | *v = int32(x) 132 | return nil 133 | } 134 | return errors.Errorf(`msgpack: invalid numeric type %s for int32`, Code(code)) 135 | } 136 | 137 | func (dnl *decoderNL) DecodeInt64(v *int64) error { 138 | code, err := dnl.src.ReadByte() 139 | if err != nil { 140 | return errors.Wrap(err, `msgpack: failed to read code for Int64`) 141 | } 142 | if IsFixNumFamily(Code(code)) { 143 | *v = int64(code) 144 | return nil 145 | } 146 | switch Code(code) { 147 | case Int64: 148 | x, err := dnl.src.ReadUint64() 149 | if err != nil { 150 | return errors.Wrap(err, `msgpack: failed to read payload for int64`) 151 | } 152 | *v = int64(x) 153 | return nil 154 | case Int32: 155 | x, err := dnl.src.ReadUint32() 156 | if err != nil { 157 | return errors.Wrap(err, `msgpack: failed to read payload for int64`) 158 | } 159 | *v = int64(x) 160 | return nil 161 | case Int16: 162 | x, err := dnl.src.ReadUint16() 163 | if err != nil { 164 | return errors.Wrap(err, `msgpack: failed to read payload for int64`) 165 | } 166 | *v = int64(x) 167 | return nil 168 | case Int8: 169 | x, err := dnl.src.ReadUint8() 170 | if err != nil { 171 | return errors.Wrap(err, `msgpack: failed to read payload for int64`) 172 | } 173 | *v = int64(x) 174 | return nil 175 | } 176 | return errors.Errorf(`msgpack: invalid numeric type %s for int64`, Code(code)) 177 | } 178 | 179 | func (dnl *decoderNL) DecodeUint(v *uint) error { 180 | code, err := dnl.src.ReadByte() 181 | if err != nil { 182 | return errors.Wrap(err, `msgpack: failed to read code for Uint64`) 183 | } 184 | if IsFixNumFamily(Code(code)) { 185 | *v = uint(code) 186 | return nil 187 | } 188 | switch Code(code) { 189 | case Uint64: 190 | x, err := dnl.src.ReadUint64() 191 | if err != nil { 192 | return errors.Wrap(err, `msgpack: failed to read payload for uint`) 193 | } 194 | *v = uint(x) 195 | return nil 196 | case Uint32: 197 | x, err := dnl.src.ReadUint32() 198 | if err != nil { 199 | return errors.Wrap(err, `msgpack: failed to read payload for uint`) 200 | } 201 | *v = uint(x) 202 | return nil 203 | case Uint16: 204 | x, err := dnl.src.ReadUint16() 205 | if err != nil { 206 | return errors.Wrap(err, `msgpack: failed to read payload for uint`) 207 | } 208 | *v = uint(x) 209 | return nil 210 | case Uint8: 211 | x, err := dnl.src.ReadUint8() 212 | if err != nil { 213 | return errors.Wrap(err, `msgpack: failed to read payload for uint`) 214 | } 215 | *v = uint(x) 216 | return nil 217 | } 218 | return errors.Errorf(`msgpack: invalid numeric type %s for uint`, Code(code)) 219 | } 220 | 221 | func (dnl *decoderNL) DecodeUint8(v *uint8) error { 222 | code, err := dnl.src.ReadByte() 223 | if err != nil { 224 | return errors.Wrap(err, `msgpack: failed to read code for Uint8`) 225 | } 226 | if IsFixNumFamily(Code(code)) { 227 | *v = uint8(code) 228 | return nil 229 | } 230 | switch Code(code) { 231 | case Uint8: 232 | x, err := dnl.src.ReadUint8() 233 | if err != nil { 234 | return errors.Wrap(err, `msgpack: failed to read payload for uint8`) 235 | } 236 | *v = uint8(x) 237 | return nil 238 | } 239 | return errors.Errorf(`msgpack: invalid numeric type %s for uint8`, Code(code)) 240 | } 241 | 242 | func (dnl *decoderNL) DecodeUint16(v *uint16) error { 243 | code, err := dnl.src.ReadByte() 244 | if err != nil { 245 | return errors.Wrap(err, `msgpack: failed to read code for Uint16`) 246 | } 247 | if IsFixNumFamily(Code(code)) { 248 | *v = uint16(code) 249 | return nil 250 | } 251 | switch Code(code) { 252 | case Uint16: 253 | x, err := dnl.src.ReadUint16() 254 | if err != nil { 255 | return errors.Wrap(err, `msgpack: failed to read payload for uint16`) 256 | } 257 | *v = uint16(x) 258 | return nil 259 | case Uint8: 260 | x, err := dnl.src.ReadUint8() 261 | if err != nil { 262 | return errors.Wrap(err, `msgpack: failed to read payload for uint16`) 263 | } 264 | *v = uint16(x) 265 | return nil 266 | } 267 | return errors.Errorf(`msgpack: invalid numeric type %s for uint16`, Code(code)) 268 | } 269 | 270 | func (dnl *decoderNL) DecodeUint32(v *uint32) error { 271 | code, err := dnl.src.ReadByte() 272 | if err != nil { 273 | return errors.Wrap(err, `msgpack: failed to read code for Uint32`) 274 | } 275 | if IsFixNumFamily(Code(code)) { 276 | *v = uint32(code) 277 | return nil 278 | } 279 | switch Code(code) { 280 | case Uint32: 281 | x, err := dnl.src.ReadUint32() 282 | if err != nil { 283 | return errors.Wrap(err, `msgpack: failed to read payload for uint32`) 284 | } 285 | *v = uint32(x) 286 | return nil 287 | case Uint16: 288 | x, err := dnl.src.ReadUint16() 289 | if err != nil { 290 | return errors.Wrap(err, `msgpack: failed to read payload for uint32`) 291 | } 292 | *v = uint32(x) 293 | return nil 294 | case Uint8: 295 | x, err := dnl.src.ReadUint8() 296 | if err != nil { 297 | return errors.Wrap(err, `msgpack: failed to read payload for uint32`) 298 | } 299 | *v = uint32(x) 300 | return nil 301 | } 302 | return errors.Errorf(`msgpack: invalid numeric type %s for uint32`, Code(code)) 303 | } 304 | 305 | func (dnl *decoderNL) DecodeUint64(v *uint64) error { 306 | code, err := dnl.src.ReadByte() 307 | if err != nil { 308 | return errors.Wrap(err, `msgpack: failed to read code for Uint64`) 309 | } 310 | if IsFixNumFamily(Code(code)) { 311 | *v = uint64(code) 312 | return nil 313 | } 314 | switch Code(code) { 315 | case Uint64: 316 | x, err := dnl.src.ReadUint64() 317 | if err != nil { 318 | return errors.Wrap(err, `msgpack: failed to read payload for uint64`) 319 | } 320 | *v = uint64(x) 321 | return nil 322 | case Uint32: 323 | x, err := dnl.src.ReadUint32() 324 | if err != nil { 325 | return errors.Wrap(err, `msgpack: failed to read payload for uint64`) 326 | } 327 | *v = uint64(x) 328 | return nil 329 | case Uint16: 330 | x, err := dnl.src.ReadUint16() 331 | if err != nil { 332 | return errors.Wrap(err, `msgpack: failed to read payload for uint64`) 333 | } 334 | *v = uint64(x) 335 | return nil 336 | case Uint8: 337 | x, err := dnl.src.ReadUint8() 338 | if err != nil { 339 | return errors.Wrap(err, `msgpack: failed to read payload for uint64`) 340 | } 341 | *v = uint64(x) 342 | return nil 343 | } 344 | return errors.Errorf(`msgpack: invalid numeric type %s for uint64`, Code(code)) 345 | } 346 | 347 | func (dnl *decoderNL) DecodeFloat32(v *float32) error { 348 | code, x, err := dnl.src.ReadByteUint32() 349 | if err != nil { 350 | return errors.Wrap(err, `msgpack: failed to read float32`) 351 | } 352 | 353 | if code != Float.Byte() { 354 | return errors.Errorf(`msgpack: expected Float, got %s`, Code(code)) 355 | } 356 | 357 | *v = math.Float32frombits(x) 358 | return nil 359 | } 360 | 361 | func (dnl *decoderNL) DecodeFloat64(v *float64) error { 362 | code, x, err := dnl.src.ReadByteUint64() 363 | if err != nil { 364 | return errors.Wrap(err, `msgpack: failed to read float64`) 365 | } 366 | 367 | if code != Double.Byte() { 368 | return errors.Errorf(`msgpack: expected Double, got %s`, Code(code)) 369 | } 370 | 371 | *v = math.Float64frombits(x) 372 | return nil 373 | } 374 | -------------------------------------------------------------------------------- /decoder_test.go: -------------------------------------------------------------------------------- 1 | package msgpack_test 2 | 3 | import ( 4 | "bytes" 5 | "encoding/binary" 6 | "fmt" 7 | "io" 8 | "math" 9 | "reflect" 10 | "testing" 11 | 12 | "github.com/lestrrat-go/msgpack" 13 | "github.com/stretchr/testify/assert" 14 | ) 15 | 16 | func unmarshalMatch(t *testing.T, src []byte, v interface{}, expected interface{}) { 17 | t.Helper() 18 | if !assert.NoError(t, msgpack.Unmarshal(src, v), "Unmarshal should succeed") { 19 | return 20 | } 21 | 22 | if rv := reflect.ValueOf(v); rv.Kind() == reflect.Ptr { 23 | v = rv.Elem().Interface() 24 | } 25 | if !assert.Equal(t, expected, v, "value should be %v", expected) { 26 | return 27 | } 28 | } 29 | 30 | func decodeMatch(t *testing.T, src io.Reader, v interface{}, expected interface{}) { 31 | t.Helper() 32 | if !assert.NoError(t, msgpack.NewDecoder(src).Decode(v), "Decode should succeed") { 33 | return 34 | } 35 | 36 | if rv := reflect.ValueOf(v); rv.Kind() == reflect.Ptr { 37 | v = rv.Elem().Interface() 38 | } 39 | if !assert.Equal(t, expected, v, "value should be %v", expected) { 40 | return 41 | } 42 | } 43 | 44 | func decodeTest(t *testing.T, code msgpack.Code, b []byte, e interface{}) { 45 | t.Helper() 46 | decodeTestConcrete(t, code, b, e) 47 | decodeTestInterface(t, code, b, e) 48 | } 49 | 50 | func decodeTestConcrete(t *testing.T, code msgpack.Code, b []byte, e interface{}) { 51 | t.Helper() 52 | typ := reflect.TypeOf(e) 53 | t.Run(fmt.Sprintf("decode %s via Unmarshal (concrete)", code), func(t *testing.T) { 54 | t.Parallel() 55 | v := reflect.New(typ).Elem().Interface() 56 | unmarshalMatch(t, b, &v, e) 57 | }) 58 | 59 | t.Run(fmt.Sprintf("decode %s via Decoder (concrete)", code), func(t *testing.T) { 60 | t.Parallel() 61 | v := reflect.New(typ).Elem().Interface() 62 | decodeMatch(t, bytes.NewBuffer(b), &v, e) 63 | }) 64 | } 65 | 66 | func decodeTestInterface(t *testing.T, code msgpack.Code, b []byte, e interface{}) { 67 | t.Helper() 68 | t.Run(fmt.Sprintf("decode %s via Unmarshal (interface{})", code), func(t *testing.T) { 69 | t.Parallel() 70 | var v interface{} 71 | unmarshalMatch(t, b, &v, e) 72 | }) 73 | 74 | t.Run(fmt.Sprintf("decode %s via Decoder (interface{})", code), func(t *testing.T) { 75 | t.Parallel() 76 | var v interface{} 77 | decodeMatch(t, bytes.NewBuffer(b), &v, e) 78 | }) 79 | } 80 | 81 | func decodeTestString(t *testing.T, code msgpack.Code, b []byte, e interface{}) { 82 | t.Helper() 83 | decodeTest(t, code, b, e) 84 | // decodeTestMethod(t, code, "DecodeString", b, e) 85 | } 86 | 87 | func decodeTestMethod(t *testing.T, code msgpack.Code, method string, b []byte, e interface{}) { 88 | t.Helper() 89 | t.Run(fmt.Sprintf("decode %s via %s", code, method), func(t *testing.T) { 90 | t.Parallel() 91 | val := reflect.New(reflect.TypeOf(e)) 92 | dec := msgpack.NewDecoder(bytes.NewBuffer(b)) 93 | ret := reflect.ValueOf(dec).MethodByName(method).Call([]reflect.Value{val}) 94 | if !assert.Len(t, ret, 1, "%s should return 1 values", method) { 95 | return 96 | } 97 | 98 | if !assert.Nil(t, ret[0].Interface(), "DecodeString should succeed") { 99 | return 100 | } 101 | 102 | if !assert.Equal(t, e, val.Elem().Interface(), "value should be %s", e) { 103 | return 104 | } 105 | }) 106 | } 107 | 108 | func TestDecodeNil(t *testing.T) { 109 | t.Parallel() 110 | var e interface{} 111 | var b = []byte{msgpack.Nil.Byte()} 112 | 113 | t.Run("decode via Unmarshal", func(t *testing.T) { 114 | t.Parallel() 115 | var v interface{} 116 | unmarshalMatch(t, b, &v, e) 117 | }) 118 | t.Run("decode via DecodeNil", func(t *testing.T) { 119 | t.Parallel() 120 | var v interface{} = &struct{}{} 121 | buf := bytes.NewBuffer(b) 122 | if !assert.NoError(t, msgpack.NewDecoder(buf).DecodeNil(&v), "DecodeNil should succeed") { 123 | return 124 | } 125 | if !assert.Nil(t, v, "value should be nil") { 126 | return 127 | } 128 | }) 129 | t.Run("decode via Decoder (interface{})", func(t *testing.T) { 130 | t.Parallel() 131 | var v interface{} = 0xdeadcafe 132 | decodeMatch(t, bytes.NewBuffer(b), &v, e) 133 | }) 134 | } 135 | 136 | func TestDecodeBool(t *testing.T) { 137 | t.Parallel() 138 | for _, code := range []msgpack.Code{msgpack.True, msgpack.False} { 139 | var e bool 140 | if code == msgpack.True { 141 | e = true 142 | } 143 | var b = []byte{code.Byte()} 144 | 145 | decodeTest(t, code, b, e) 146 | decodeTestMethod(t, code, "DecodeBool", b, e) 147 | } 148 | } 149 | 150 | func TestDecodeFloat32(t *testing.T) { 151 | t.Parallel() 152 | var e = float32(math.MaxFloat32) 153 | var b = make([]byte, 5) 154 | b[0] = msgpack.Float.Byte() 155 | binary.BigEndian.PutUint32(b[1:], math.Float32bits(e)) 156 | 157 | decodeTest(t, msgpack.Float, b, e) 158 | decodeTestMethod(t, msgpack.Float, "DecodeFloat32", b, e) 159 | } 160 | 161 | func TestDecodeFloat64(t *testing.T) { 162 | t.Parallel() 163 | var e = float64(math.MaxFloat64) 164 | var b = make([]byte, 9) 165 | b[0] = msgpack.Double.Byte() 166 | binary.BigEndian.PutUint64(b[1:], math.Float64bits(e)) 167 | 168 | decodeTest(t, msgpack.Double, b, e) 169 | decodeTestMethod(t, msgpack.Float, "DecodeFloat64", b, e) 170 | } 171 | 172 | func TestDecodeUint8(t *testing.T) { 173 | t.Parallel() 174 | var e = uint8(math.MaxUint8) 175 | var b = []byte{msgpack.Uint8.Byte(), byte(e)} 176 | 177 | decodeTest(t, msgpack.Uint8, b, e) 178 | decodeTestMethod(t, msgpack.Uint8, "DecodeUint8", b, e) 179 | } 180 | 181 | func TestDecodeUint16(t *testing.T) { 182 | t.Parallel() 183 | var e = uint16(math.MaxUint16) 184 | var b = make([]byte, 3) 185 | b[0] = msgpack.Uint16.Byte() 186 | binary.BigEndian.PutUint16(b[1:], uint16(e)) 187 | 188 | decodeTest(t, msgpack.Uint16, b, e) 189 | decodeTestMethod(t, msgpack.Uint16, "DecodeUint16", b, e) 190 | } 191 | 192 | func TestDecodeUint32(t *testing.T) { 193 | t.Parallel() 194 | var e = uint32(math.MaxUint32) 195 | var b = make([]byte, 5) 196 | b[0] = msgpack.Uint32.Byte() 197 | binary.BigEndian.PutUint32(b[1:], uint32(e)) 198 | 199 | decodeTest(t, msgpack.Uint32, b, e) 200 | decodeTestMethod(t, msgpack.Uint32, "DecodeUint32", b, e) 201 | } 202 | 203 | func TestDecodeUint64(t *testing.T) { 204 | t.Parallel() 205 | var e = uint64(math.MaxUint64) 206 | var b = make([]byte, 9) 207 | b[0] = msgpack.Uint64.Byte() 208 | binary.BigEndian.PutUint64(b[1:], uint64(e)) 209 | 210 | decodeTest(t, msgpack.Uint64, b, e) 211 | decodeTestMethod(t, msgpack.Uint64, "DecodeUint64", b, e) 212 | } 213 | 214 | func TestDecodeInt8(t *testing.T) { 215 | t.Parallel() 216 | var e = int8(math.MaxInt8) 217 | var b = []byte{msgpack.Int8.Byte(), byte(e)} 218 | 219 | decodeTest(t, msgpack.Int8, b, e) 220 | decodeTestMethod(t, msgpack.Int8, "DecodeInt8", b, e) 221 | } 222 | 223 | func TestDecodeInt16(t *testing.T) { 224 | t.Parallel() 225 | var e = int16(math.MaxInt16) 226 | var b = make([]byte, 3) 227 | b[0] = msgpack.Int16.Byte() 228 | binary.BigEndian.PutUint16(b[1:], uint16(e)) 229 | 230 | decodeTest(t, msgpack.Int16, b, e) 231 | decodeTestMethod(t, msgpack.Int16, "DecodeInt16", b, e) 232 | } 233 | 234 | func TestDecodeInt32(t *testing.T) { 235 | t.Parallel() 236 | var e = int32(math.MaxInt32) 237 | var b = make([]byte, 5) 238 | b[0] = msgpack.Int32.Byte() 239 | binary.BigEndian.PutUint32(b[1:], uint32(e)) 240 | 241 | decodeTest(t, msgpack.Int32, b, e) 242 | decodeTestMethod(t, msgpack.Int32, "DecodeInt32", b, e) 243 | } 244 | 245 | func TestDecodeInt64(t *testing.T) { 246 | t.Parallel() 247 | var e = int64(math.MaxInt64) 248 | var b = make([]byte, 9) 249 | b[0] = msgpack.Int64.Byte() 250 | binary.BigEndian.PutUint64(b[1:], uint64(e)) 251 | 252 | decodeTest(t, msgpack.Int64, b, e) 253 | decodeTestMethod(t, msgpack.Int64, "DecodeInt64", b, e) 254 | } 255 | 256 | func TestDecodeStr8(t *testing.T) { 257 | t.Parallel() 258 | var l = math.MaxUint8 259 | var e = makeString(l) 260 | var b = make([]byte, l+2) 261 | b[0] = msgpack.Str8.Byte() 262 | b[1] = byte(l) 263 | copy(b[2:], []byte(e)) 264 | 265 | decodeTestString(t, msgpack.Str8, b, e) 266 | } 267 | 268 | func TestDecodeStr16(t *testing.T) { 269 | t.Parallel() 270 | var l = math.MaxUint16 271 | var e = makeString(l) 272 | var b = make([]byte, l+3) 273 | b[0] = msgpack.Str16.Byte() 274 | binary.BigEndian.PutUint16(b[1:], uint16(l)) 275 | copy(b[3:], []byte(e)) 276 | 277 | decodeTestString(t, msgpack.Str16, b, e) 278 | } 279 | 280 | func TestDecodeStr32(t *testing.T) { 281 | t.Parallel() 282 | var l = math.MaxUint16 + 1 283 | var e = makeString(l) 284 | var b = make([]byte, l+5) 285 | b[0] = msgpack.Str32.Byte() 286 | binary.BigEndian.PutUint32(b[1:], uint32(l)) 287 | copy(b[5:], []byte(e)) 288 | 289 | decodeTestString(t, msgpack.Str32, b, e) 290 | } 291 | 292 | func TestDecodeFixStr(t *testing.T) { 293 | t.Parallel() 294 | for l := 1; l < 32; l++ { 295 | var e = makeString(l) 296 | var b = make([]byte, l+1) 297 | b[0] = byte(msgpack.FixStr0.Byte() + byte(l)) 298 | copy(b[1:], []byte(e)) 299 | 300 | decodeTestString(t, msgpack.Code(b[0]), b, e) 301 | } 302 | } 303 | 304 | func TestDecodeStruct(t *testing.T) { 305 | t.Parallel() 306 | var buf bytes.Buffer 307 | w := msgpack.NewWriter(&buf) 308 | w.WriteByte(msgpack.FixMap2.Byte()) 309 | w.WriteByte(msgpack.FixStr3.Byte()) 310 | w.Write([]byte("Foo")) 311 | w.WriteByte(msgpack.Int8.Byte()) 312 | w.WriteUint8(uint8(100)) 313 | w.WriteByte(msgpack.FixStr3.Byte()) 314 | w.Write([]byte("bar")) 315 | w.WriteByte(msgpack.FixMap1.Byte()) 316 | w.WriteByte(msgpack.FixStr11.Byte()) 317 | w.Write([]byte("bar.content")) 318 | w.WriteByte(msgpack.FixStr13.Byte()) 319 | w.Write([]byte("Hello, World!")) 320 | b := buf.Bytes() 321 | 322 | var e = testStruct{ 323 | Foo: 100, 324 | } 325 | e.Bar.BarContent = "Hello, World!" 326 | 327 | decodeTestConcrete(t, msgpack.FixMap2, b, e) 328 | } 329 | 330 | type nestedInner struct { 331 | Foo string 332 | } 333 | 334 | type nestedOuter struct { 335 | InnerStruct *nestedInner 336 | InnerSlice []*nestedInner 337 | } 338 | 339 | func TestDecodeArray(t *testing.T) { 340 | t.Parallel() 341 | var e []nestedOuter 342 | e = append(e, nestedOuter{InnerStruct: &nestedInner{Foo: "Hello"}}) 343 | 344 | buf, err := msgpack.Marshal(e) 345 | if !assert.NoError(t, err, "Marshal should succeed") { 346 | return 347 | } 348 | 349 | var r []nestedOuter 350 | if !assert.NoError(t, msgpack.Unmarshal(buf, &r), "Unmarshal should succeed") { 351 | return 352 | } 353 | 354 | if !assert.Len(t, r, 1, `r should be length 1`) { 355 | return 356 | } 357 | } 358 | 359 | func TestDecodeNestedStruct(t *testing.T) { 360 | t.Parallel() 361 | t.Run("regular case", func(t *testing.T) { 362 | t.Parallel() 363 | var e *nestedOuter = &nestedOuter{ 364 | InnerStruct: &nestedInner{Foo: "Hello"}, 365 | InnerSlice: []*nestedInner{ 366 | {Foo: "World"}, 367 | }, 368 | } 369 | 370 | buf, err := msgpack.Marshal(e) 371 | if !assert.NoError(t, err, "Marshal should succeed") { 372 | return 373 | } 374 | 375 | var r nestedOuter 376 | if !assert.NoError(t, msgpack.Unmarshal(buf, &r), "Unmarshal should succeed") { 377 | return 378 | } 379 | }) 380 | t.Run("unitinialized case", func(t *testing.T) { 381 | t.Parallel() 382 | var e *nestedOuter = &nestedOuter{ 383 | InnerSlice: []*nestedInner{ 384 | {Foo: "World"}, 385 | }, 386 | } 387 | 388 | buf, err := msgpack.Marshal(e) 389 | if !assert.NoError(t, err, "Marshal should succeed") { 390 | return 391 | } 392 | 393 | var r nestedOuter 394 | if !assert.NoError(t, msgpack.Unmarshal(buf, &r), "Unmarshal should succeed") { 395 | return 396 | } 397 | if !assert.Nil(t, r.InnerStruct, "r.InnerStruct should be nil") { 398 | return 399 | } 400 | }) 401 | } 402 | -------------------------------------------------------------------------------- /encoder.go: -------------------------------------------------------------------------------- 1 | package msgpack 2 | 3 | import ( 4 | "io" 5 | "math" 6 | "reflect" 7 | "strings" 8 | "time" 9 | 10 | "github.com/pkg/errors" 11 | ) 12 | 13 | // NewEncoder creates a new Encoder that writes serialized forms 14 | // to the specified io.Writer 15 | // 16 | // Note that Encoders are NEVER meant to be shared concurrently 17 | // between goroutines. You DO NOT write serialized data concurrently 18 | // to the same destination. 19 | func NewEncoder(w io.Writer) Encoder { 20 | enc := &encoder{nl: &encoderNL{}} 21 | enc.nl.SetDestination(w) 22 | return enc 23 | } 24 | 25 | // NewEncoderNoLock creates a new Encoder that DOES NOT protect 26 | // users against accidental race conditions caused by concurrent 27 | // method access. If you have complete control over the usage of 28 | // this object, then the object returned by this constructor will 29 | // shorten a whopping 30~50ns per method call. Use at your own peril 30 | func NewEncoderNoLock(w io.Writer) Encoder { 31 | enc := &encoderNL{} 32 | enc.SetDestination(w) 33 | return enc 34 | } 35 | 36 | func (e *encoder) SetDestination(r io.Writer) { 37 | e.mu.Lock() 38 | defer e.mu.Unlock() 39 | e.nl.SetDestination(r) 40 | } 41 | 42 | func (enl *encoderNL) SetDestination(w io.Writer) { 43 | var dst Writer 44 | if x, ok := w.(Writer); ok { 45 | dst = x 46 | } else { 47 | dst = NewWriter(w) 48 | } 49 | 50 | enl.dst = dst 51 | } 52 | 53 | func inPositiveFixNumRange(i int64) bool { 54 | return i >= 0 && i <= 127 55 | } 56 | 57 | func inNegativeFixNumRange(i int64) bool { 58 | return i >= -31 && i <= -1 59 | } 60 | 61 | func isExtType(t reflect.Type) bool { 62 | muExtEncode.RLock() 63 | _, ok := extEncodeRegistry[t] 64 | muExtEncode.RUnlock() 65 | return ok 66 | } 67 | 68 | func isEncodeMsgpacker(t reflect.Type) bool { 69 | return t.Implements(encodeMsgpackerType) 70 | } 71 | 72 | func (enl *encoderNL) Writer() Writer { 73 | return enl.dst 74 | } 75 | 76 | //nolint:stylecheck,golint 77 | func (enl *encoderNL) encodeBuiltin(v interface{}) (error, bool) { 78 | switch v := v.(type) { 79 | case string: 80 | return enl.EncodeString(v), true 81 | case []byte: 82 | return enl.EncodeBytes(v), true 83 | case bool: 84 | return enl.EncodeBool(v), true 85 | case float32: 86 | return enl.EncodeFloat32(v), true 87 | case float64: 88 | return enl.EncodeFloat64(v), true 89 | case uint: 90 | return enl.EncodeUint64(uint64(v)), true 91 | case uint8: 92 | return enl.EncodeUint8(v), true 93 | case uint16: 94 | return enl.EncodeUint16(v), true 95 | case uint32: 96 | return enl.EncodeUint32(v), true 97 | case uint64: 98 | return enl.EncodeUint64(v), true 99 | case int: 100 | return enl.EncodeInt64(int64(v)), true 101 | case int8: 102 | return enl.EncodeInt8(v), true 103 | case int16: 104 | return enl.EncodeInt16(v), true 105 | case int32: 106 | return enl.EncodeInt32(v), true 107 | case int64: 108 | return enl.EncodeInt64(v), true 109 | } 110 | 111 | return nil, false 112 | } 113 | 114 | func (enl *encoderNL) Encode(v interface{}) error { 115 | if err, ok := enl.encodeBuiltin(v); ok { 116 | return err 117 | } 118 | 119 | // Find the first non-pointer, non-interface{} 120 | rv := reflect.ValueOf(v) 121 | if rv.Kind() == reflect.Ptr && rv.Elem().IsValid() { 122 | if err, ok := enl.encodeBuiltin(rv.Elem().Interface()); ok { 123 | return err 124 | } 125 | } 126 | 127 | INDIRECT: 128 | for { 129 | if !rv.IsValid() { 130 | return enl.EncodeNil() 131 | } 132 | 133 | if isExtType(rv.Type()) { 134 | return enl.EncodeExt(rv.Interface().(EncodeMsgpacker)) 135 | } 136 | 137 | if ok := isEncodeMsgpacker(rv.Type()); ok { 138 | return rv.Interface().(EncodeMsgpacker).EncodeMsgpack(enl) 139 | } 140 | switch rv.Kind() { 141 | case reflect.Ptr, reflect.Interface: 142 | rv = rv.Elem() 143 | default: 144 | break INDIRECT 145 | } 146 | } 147 | 148 | if !rv.IsValid() { 149 | return enl.EncodeNil() 150 | } 151 | 152 | v = rv.Interface() 153 | switch rv.Kind() { 154 | case reflect.Slice: // , reflect.Array: 155 | return enl.EncodeArray(v) 156 | case reflect.Map: 157 | return enl.EncodeMap(v) 158 | case reflect.Struct: 159 | return enl.EncodeStruct(v) 160 | } 161 | 162 | return errors.Errorf(`msgpack: encode unimplemented for type %s`, rv.Type()) 163 | } 164 | 165 | func (enl *encoderNL) encodePositiveFixNum(i uint8) error { 166 | return enl.dst.WriteByte(byte(i)) 167 | } 168 | 169 | func (enl *encoderNL) encodeNegativeFixNum(i int8) error { 170 | return enl.dst.WriteByte(byte(i)) 171 | } 172 | 173 | func (enl *encoderNL) EncodeNil() error { 174 | return enl.dst.WriteByte(Nil.Byte()) 175 | } 176 | 177 | func (enl *encoderNL) EncodeBool(b bool) error { 178 | var code Code 179 | if b { 180 | code = True 181 | } else { 182 | code = False 183 | } 184 | return enl.dst.WriteByte(code.Byte()) 185 | } 186 | 187 | func (enl *encoderNL) EncodePositiveFixNum(i uint8) error { 188 | if i > uint8(MaxPositiveFixNum) { 189 | return errors.Errorf(`msgpack: value %d is not in range for positive FixNum (127 >= x >= 0)`, i) 190 | } 191 | 192 | if err := enl.dst.WriteByte(byte(i)); err != nil { 193 | return errors.Wrap(err, `msgpack: failed to write FixNum`) 194 | } 195 | return nil 196 | } 197 | 198 | func (enl *encoderNL) EncodeNegativeFixNum(i int8) error { 199 | if i < -31 || i >= 0 { 200 | return errors.Errorf(`msgpack: value %d is not in range for positive FixNum (0 > x >= -31)`, i) 201 | } 202 | 203 | if err := enl.dst.WriteByte(byte(i)); err != nil { 204 | return errors.Wrap(err, `msgpack: failed to write FixNum`) 205 | } 206 | return nil 207 | } 208 | 209 | func (enl *encoderNL) EncodeBytes(b []byte) error { 210 | l := len(b) 211 | 212 | var w int 213 | var code Code 214 | switch { 215 | case l <= math.MaxUint8: 216 | code = Bin8 217 | w = 1 218 | case l <= math.MaxUint16: 219 | code = Bin16 220 | w = 2 221 | case l <= math.MaxUint32: 222 | code = Bin32 223 | w = 4 224 | default: 225 | return errors.Errorf(`msgpack: string is too long (len=%d)`, l) 226 | } 227 | 228 | if err := enl.writePreamble(code, w, l); err != nil { 229 | return errors.Wrap(err, `msgpack: failed to write []byte preamble`) 230 | } 231 | if _, err := enl.dst.Write(b); err != nil { 232 | return errors.Wrap(err, `msgpack: failed to write []byte`) 233 | } 234 | return nil 235 | } 236 | 237 | func (enl *encoderNL) EncodeString(s string) error { 238 | l := len(s) 239 | switch { 240 | case l < 32: 241 | if err := enl.dst.WriteByte(FixStr0.Byte() | uint8(l)); err != nil { 242 | return errors.Wrap(err, `failed to encode fixed string length`) 243 | } 244 | case l <= math.MaxUint8: 245 | if err := enl.dst.WriteByte(Str8.Byte()); err != nil { 246 | return errors.Wrap(err, `msgpack: failed to encode 8-bit string length prefix`) 247 | } 248 | if err := enl.dst.WriteUint8(uint8(l)); err != nil { 249 | return errors.Wrap(err, `msgpack: failed to encode 8-bit string length`) 250 | } 251 | case l <= math.MaxUint16: 252 | if err := enl.dst.WriteByte(Str16.Byte()); err != nil { 253 | return errors.Wrap(err, `msgpack: failed to encode 16-bit string length prefix`) 254 | } 255 | if err := enl.dst.WriteUint16(uint16(l)); err != nil { 256 | return errors.Wrap(err, `msgpack: failed to encode 16-bit string length`) 257 | } 258 | case l <= math.MaxUint32: 259 | if err := enl.dst.WriteByte(Str32.Byte()); err != nil { 260 | return errors.Wrap(err, `msgpack: failed to encode 32-bit string length prefix`) 261 | } 262 | if err := enl.dst.WriteUint32(uint32(l)); err != nil { 263 | return errors.Wrap(err, `msgpack: failed to encode 32-bit string length`) 264 | } 265 | default: 266 | return errors.Errorf(`msgpack: string is too long (len=%d)`, l) 267 | } 268 | 269 | if _, err := enl.dst.WriteString(s); err != nil { 270 | return errors.Wrap(err, `msgpack: failed to write string`) 271 | } 272 | return nil 273 | } 274 | 275 | func (enl *encoderNL) writePreamble(code Code, w int, l int) error { 276 | if err := enl.dst.WriteByte(code.Byte()); err != nil { 277 | return errors.Wrap(err, `msgpack: failed to write code`) 278 | } 279 | 280 | switch w { 281 | case 1: 282 | if err := enl.dst.WriteUint8(uint8(l)); err != nil { 283 | return errors.Wrap(err, `msgpack: failed to write length`) 284 | } 285 | case 2: 286 | if err := enl.dst.WriteUint16(uint16(l)); err != nil { 287 | return errors.Wrap(err, `msgpack: failed to write length`) 288 | } 289 | case 4: 290 | if err := enl.dst.WriteUint32(uint32(l)); err != nil { 291 | return errors.Wrap(err, `msgpack: failed to write length`) 292 | } 293 | } 294 | return nil 295 | } 296 | 297 | func (enl *encoderNL) EncodeArrayHeader(l int) error { 298 | if err := WriteArrayHeader(enl.dst, l); err != nil { 299 | return errors.Wrap(err, `msgpack: failed to write array header`) 300 | } 301 | return nil 302 | } 303 | 304 | func (enl *encoderNL) EncodeArray(v interface{}) error { 305 | rv := reflect.ValueOf(v) 306 | switch rv.Kind() { 307 | case reflect.Slice, reflect.Array: 308 | default: 309 | return errors.Errorf(`msgpack: argument must be an array or a slice`) 310 | } 311 | 312 | if err := enl.EncodeArrayHeader(rv.Len()); err != nil { 313 | return err 314 | } 315 | 316 | switch rv.Type().Elem().Kind() { 317 | case reflect.String: 318 | return enl.encodeArrayString(rv.Convert(reflect.TypeOf([]string{})).Interface()) 319 | case reflect.Bool: 320 | return enl.encodeArrayBool(v) 321 | case reflect.Int: 322 | return enl.encodeArrayInt(v) 323 | case reflect.Int8: 324 | return enl.encodeArrayInt8(v) 325 | case reflect.Int16: 326 | return enl.encodeArrayInt16(v) 327 | case reflect.Int32: 328 | return enl.encodeArrayInt32(v) 329 | case reflect.Int64: 330 | return enl.encodeArrayInt64(v) 331 | case reflect.Uint: 332 | return enl.encodeArrayUint(v) 333 | case reflect.Uint8: 334 | return enl.encodeArrayUint8(v) 335 | case reflect.Uint16: 336 | return enl.encodeArrayUint16(v) 337 | case reflect.Uint32: 338 | return enl.encodeArrayUint32(v) 339 | case reflect.Uint64: 340 | return enl.encodeArrayUint64(v) 341 | case reflect.Float32: 342 | return enl.encodeArrayFloat32(v) 343 | case reflect.Float64: 344 | return enl.encodeArrayFloat64(v) 345 | } 346 | 347 | for i := 0; i < rv.Len(); i++ { 348 | if err := enl.Encode(rv.Index(i).Interface()); err != nil { 349 | return errors.Wrap(err, `msgpack: failed to write array payload`) 350 | } 351 | } 352 | return nil 353 | } 354 | 355 | func (enl *encoderNL) EncodeMap(v interface{}) error { 356 | rv := reflect.ValueOf(v) 357 | 358 | if !rv.IsValid() { 359 | return enl.EncodeNil() 360 | } 361 | 362 | if rv.Kind() != reflect.Map { 363 | var typ string 364 | if !rv.IsValid() { 365 | typ = "invalid" 366 | } else { 367 | typ = rv.Type().String() 368 | } 369 | return errors.Errorf(`msgpack: argument to EncodeMap must be a map (not %s)`, typ) 370 | } 371 | 372 | if rv.IsNil() { 373 | return enl.EncodeNil() 374 | } 375 | 376 | if rv.Type().Key().Kind() != reflect.String { 377 | return errors.Errorf(`msgpack: keys to maps must be strings (not %s)`, rv.Type().Key()) 378 | } 379 | 380 | // XXX We do NOT use MapBuilder's convenience methods except for the 381 | // WriteHeader bit, purely for performance reasons. 382 | keys := rv.MapKeys() 383 | if err := WriteMapHeader(enl.dst, len(keys)); err != nil { 384 | return errors.Wrap(err, `msgpack: failed to encode map header`) 385 | } 386 | 387 | // These are silly fast paths for common cases 388 | switch rv.Type().Elem().Kind() { 389 | case reflect.String: 390 | return enl.encodeMapString(v) 391 | case reflect.Bool: 392 | return enl.encodeMapBool(v) 393 | case reflect.Uint: 394 | return enl.encodeMapUint(v) 395 | case reflect.Uint8: 396 | return enl.encodeMapUint8(v) 397 | case reflect.Uint16: 398 | return enl.encodeMapUint16(v) 399 | case reflect.Uint32: 400 | return enl.encodeMapUint32(v) 401 | case reflect.Uint64: 402 | return enl.encodeMapUint64(v) 403 | case reflect.Int: 404 | return enl.encodeMapInt(v) 405 | case reflect.Int8: 406 | return enl.encodeMapInt8(v) 407 | case reflect.Int16: 408 | return enl.encodeMapInt16(v) 409 | case reflect.Int32: 410 | return enl.encodeMapInt32(v) 411 | case reflect.Int64: 412 | return enl.encodeMapInt64(v) 413 | case reflect.Float32: 414 | return enl.encodeMapFloat32(v) 415 | case reflect.Float64: 416 | return enl.encodeMapFloat64(v) 417 | default: 418 | for _, key := range keys { 419 | if err := enl.EncodeString(key.Interface().(string)); err != nil { 420 | return errors.Wrap(err, `failed to encode map key`) 421 | } 422 | 423 | if err := enl.Encode(rv.MapIndex(key).Interface()); err != nil { 424 | return errors.Wrap(err, `failed to encode map value`) 425 | } 426 | } 427 | } 428 | return nil 429 | } 430 | 431 | func parseMsgpackTag(rv reflect.StructField) (string, bool) { 432 | var tags = []string{`msgpack`, `msg`} 433 | 434 | var name = rv.Name 435 | var omitempty bool 436 | 437 | // We will support both msg and msgpack tags, the former 438 | // is used by tinylib/msgp, and the latter vmihailenco/msgpack 439 | LOOP: 440 | for _, tagName := range tags { 441 | if tag, ok := rv.Tag.Lookup(tagName); ok && tag != "" { 442 | l := strings.Split(tag, ",") 443 | if len(l) > 0 && l[0] != "" { 444 | name = l[0] 445 | } 446 | 447 | if len(l) > 1 && l[1] == "omitempty" { 448 | omitempty = true 449 | } 450 | break LOOP 451 | } 452 | } 453 | return name, omitempty 454 | } 455 | 456 | // EncodeTime encodes time.Time as a sequence of two integers 457 | func (enl *encoderNL) EncodeTime(t time.Time) error { 458 | if err := enl.dst.WriteByte(FixArray0.Byte() + byte(2)); err != nil { 459 | return errors.Wrap(err, `msgpack: failed to encode time header`) 460 | } 461 | 462 | if err := enl.EncodeInt64(t.Unix()); err != nil { 463 | return errors.Wrap(err, `msgpack: failed to encode seconds for time.Time`) 464 | } 465 | 466 | if err := enl.EncodeInt(t.Nanosecond()); err != nil { 467 | return errors.Wrap(err, `msgpack: failed to encode nanoseconds for time.Time`) 468 | } 469 | return nil 470 | } 471 | 472 | // EncodeStruct encodes a struct value as a map object. 473 | func (enl *encoderNL) EncodeStruct(v interface{}) error { 474 | rv := reflect.ValueOf(v) 475 | if !rv.IsValid() { 476 | return enl.EncodeNil() 477 | } 478 | 479 | if isExtType(rv.Type()) { 480 | return enl.EncodeExt(v.(EncodeMsgpacker)) 481 | } 482 | 483 | if v, ok := v.(EncodeMsgpacker); ok { 484 | return v.EncodeMsgpack(enl) 485 | } 486 | 487 | // Special case 488 | if v, ok := v.(time.Time); ok { 489 | return enl.EncodeTime(v) 490 | } 491 | 492 | if rv.Kind() != reflect.Struct { 493 | return errors.Errorf(`msgpack: argument to EncodeStruct must be a struct (not %s)`, rv.Type()) 494 | } 495 | mapb := NewMapBuilder() 496 | 497 | rt := rv.Type() 498 | for i := 0; i < rt.NumField(); i++ { 499 | ft := rt.Field(i) 500 | if ft.PkgPath != "" { 501 | continue 502 | } 503 | 504 | name, omitempty := parseMsgpackTag(ft) 505 | if name == "-" { 506 | continue 507 | } 508 | 509 | field := rv.Field(i) 510 | if omitempty { 511 | if reflect.DeepEqual(field.Interface(), reflect.Zero(field.Type()).Interface()) { 512 | continue 513 | } 514 | } 515 | 516 | mapb.Add(name, field.Interface()) 517 | } 518 | 519 | if err := mapb.Encode(enl.dst); err != nil { 520 | return errors.Wrap(err, `msgpack: failed to write map payload`) 521 | } 522 | return nil 523 | } 524 | 525 | func (enl *encoderNL) EncodeExtType(v EncodeMsgpacker) error { 526 | t := reflect.TypeOf(v) 527 | 528 | muExtDecode.RLock() 529 | typ, ok := extEncodeRegistry[t] 530 | muExtDecode.RUnlock() 531 | 532 | if !ok { 533 | return errors.Errorf(`msgpack: type %s has not been registered as an extension`, reflect.TypeOf(v)) 534 | } 535 | 536 | if err := enl.dst.WriteByte(byte(typ)); err != nil { 537 | return errors.Wrapf(err, `msgpack: failed to write ext type for %s`, t) 538 | } 539 | return nil 540 | } 541 | 542 | func (enl *encoderNL) EncodeExt(v EncodeMsgpacker) error { 543 | w := newAppendingWriter(9) 544 | elocal := NewEncoder(w) 545 | 546 | if err := v.EncodeMsgpack(elocal); err != nil { 547 | return errors.Wrapf(err, `msgpack: failed during call to EncodeMsgpack for %s`, reflect.TypeOf(v)) 548 | } 549 | 550 | buf := w.Bytes() 551 | if err := enl.EncodeExtHeader(len(buf)); err != nil { 552 | return errors.Wrap(err, `failed to encode ext header`) 553 | } 554 | if err := enl.EncodeExtType(v); err != nil { 555 | return errors.Wrap(err, `failed to encode ext type`) 556 | } 557 | 558 | for b := buf; len(b) > 0; { 559 | n, err := enl.dst.Write(buf) 560 | b = b[n:] 561 | if err != nil { 562 | return errors.Wrap(err, `msgpack: failed to write extension payload`) 563 | } 564 | } 565 | 566 | return nil 567 | } 568 | 569 | func (enl *encoderNL) EncodeExtHeader(l int) error { 570 | switch { 571 | case l == 1: 572 | if err := enl.dst.WriteByte(FixExt1.Byte()); err != nil { 573 | return errors.Wrap(err, `msgpack: failed to write fixext1 code`) 574 | } 575 | case l == 2: 576 | if err := enl.dst.WriteByte(FixExt2.Byte()); err != nil { 577 | return errors.Wrap(err, `msgpack: failed to write fixext2 code`) 578 | } 579 | case l == 4: 580 | if err := enl.dst.WriteByte(FixExt4.Byte()); err != nil { 581 | return errors.Wrap(err, `msgpack: failed to write fixext4 code`) 582 | } 583 | case l == 8: 584 | if err := enl.dst.WriteByte(FixExt8.Byte()); err != nil { 585 | return errors.Wrap(err, `msgpack: failed to write fixext8 code`) 586 | } 587 | case l == 16: 588 | if err := enl.dst.WriteByte(FixExt16.Byte()); err != nil { 589 | return errors.Wrap(err, `msgpack: failed to write fixext16 code`) 590 | } 591 | case l <= math.MaxUint8: 592 | if err := enl.dst.WriteByteUint8(Ext8.Byte(), uint8(l)); err != nil { 593 | return errors.Wrap(err, `msgpack: failed to write ext8 code and payload length`) 594 | } 595 | case l <= math.MaxUint16: 596 | if err := enl.dst.WriteByteUint16(Ext16.Byte(), uint16(l)); err != nil { 597 | return errors.Wrap(err, `msgpack: failed to write ext16 code and payload length`) 598 | } 599 | case l <= math.MaxUint32: 600 | if err := enl.dst.WriteByteUint32(Ext32.Byte(), uint32(l)); err != nil { 601 | return errors.Wrap(err, `msgpack: failed to write ext32 code and payload length`) 602 | } 603 | default: 604 | return errors.Errorf(`msgpack: extension payload too large: %d bytes`, l) 605 | } 606 | 607 | return nil 608 | } 609 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # msgpack 2 | 3 | A `msgpack` serializer and deserializer 4 | 5 | [![Build Status](https://travis-ci.org/lestrrat-go/msgpack.png?branch=master)](https://travis-ci.org/lestrrat-go/msgpack) 6 | 7 | [![GoDoc](https://godoc.org/github.com/lestrrat-go/msgpack?status.svg)](https://godoc.org/github.com/lestrrat-go/msgpack) 8 | 9 | # SYNOPSIS 10 | 11 | ```go 12 | package msgpack_test 13 | 14 | import ( 15 | "fmt" 16 | "time" 17 | 18 | msgpack "github.com/lestrrat-go/msgpack" 19 | "github.com/pkg/errors" 20 | ) 21 | 22 | type EventTime struct { 23 | time.Time 24 | } 25 | 26 | func init() { 27 | if err := msgpack.RegisterExt(0, EventTime{}); err != nil { 28 | panic(err) 29 | } 30 | } 31 | 32 | func (t *EventTime) DecodeMsgpack(d msgpack.Decoder) error { 33 | r := d.Reader() 34 | sec, err := r.ReadUint32() 35 | if err != nil { 36 | return errors.Wrap(err, `failed to read uint32 from first 4 bytes`) 37 | } 38 | 39 | nsec, err := r.ReadUint32() 40 | if err != nil { 41 | return errors.Wrap(err, `failed to read uint32 from second 4 bytes`) 42 | } 43 | 44 | t.Time = time.Unix(int64(sec), int64(nsec)).UTC() 45 | return nil 46 | } 47 | 48 | func (t EventTime) EncodeMsgpack(e msgpack.Encoder) error { 49 | w := e.Writer() 50 | if err := w.WriteUint32(uint32(t.Unix())); err != nil { 51 | return errors.Wrap(err, `failed to write EventTime seconds payload`) 52 | } 53 | 54 | if err := w.WriteUint32(uint32(t.Nanosecond())); err != nil { 55 | return errors.Wrap(err, `failed to write EventTime nanoseconds payload`) 56 | } 57 | 58 | return nil 59 | } 60 | 61 | type FluentdMessage struct { 62 | Tag string 63 | Time EventTime 64 | Record map[string]interface{} 65 | Option map[string]interface{} 66 | } 67 | 68 | func (m FluentdMessage) EncodeMsgpack(e msgpack.Encoder) error { 69 | if err := e.EncodeArrayHeader(4); err != nil { 70 | return errors.Wrap(err, `failed to encode array header`) 71 | } 72 | if err := e.EncodeString(m.Tag); err != nil { 73 | return errors.Wrap(err, `failed to encode tag`) 74 | } 75 | if err := e.EncodeStruct(m.Time); err != nil { 76 | return errors.Wrap(err, `failed to encode time`) 77 | } 78 | if err := e.EncodeMap(m.Record); err != nil { 79 | return errors.Wrap(err, `failed to encode record`) 80 | } 81 | if err := e.EncodeMap(m.Option); err != nil { 82 | return errors.Wrap(err, `failed to encode option`) 83 | } 84 | return nil 85 | } 86 | 87 | func (m *FluentdMessage) DecodeMsgpack(e msgpack.Decoder) error { 88 | var l int 89 | if err := e.DecodeArrayLength(&l); err != nil { 90 | return errors.Wrap(err, `failed to decode msgpack array length`) 91 | } 92 | 93 | if l != 4 { 94 | return errors.Errorf(`invalid array length %d (expected 4)`, l) 95 | } 96 | 97 | if err := e.DecodeString(&m.Tag); err != nil { 98 | return errors.Wrap(err, `failed to decode fluentd message tag`) 99 | } 100 | 101 | if err := e.DecodeStruct(&m.Time); err != nil { 102 | return errors.Wrap(err, `failed to decode fluentd time`) 103 | } 104 | 105 | if err := e.DecodeMap(&m.Record); err != nil { 106 | return errors.Wrap(err, `failed to decode fluentd record`) 107 | } 108 | 109 | if err := e.DecodeMap(&m.Option); err != nil { 110 | return errors.Wrap(err, `failed to decode fluentd option`) 111 | } 112 | 113 | return nil 114 | } 115 | 116 | func ExampleFluentdMessage() { 117 | var f1 = FluentdMessage{ 118 | Tag: "foo", 119 | Time: EventTime{Time: time.Unix(1234567890, 123).UTC()}, 120 | Record: map[string]interface{}{ 121 | "count": 1000, 122 | }, 123 | } 124 | 125 | b, err := msgpack.Marshal(f1) 126 | if err != nil { 127 | fmt.Printf("%s\n", err) 128 | return 129 | } 130 | 131 | var f2 FluentdMessage 132 | if err := msgpack.Unmarshal(b, &f2); err != nil { 133 | fmt.Printf("%s\n", err) 134 | return 135 | } 136 | 137 | fmt.Printf("%s %s %v %v\n", f2.Tag, f2.Time, f2.Record, f2.Option) 138 | // OUTPUT: 139 | // foo 2009-02-13 23:31:30.000000123 +0000 UTC map[count:1000] map[] 140 | } 141 | 142 | func ExampleEventTime() { 143 | var e1 = EventTime{Time: time.Unix(1234567890, 123).UTC()} 144 | 145 | b, err := msgpack.Marshal(e1) 146 | if err != nil { 147 | fmt.Printf("%s\n", err) 148 | return 149 | } 150 | 151 | var e2 interface{} 152 | if err := msgpack.Unmarshal(b, &e2); err != nil { 153 | fmt.Printf("%s\n", err) 154 | return 155 | } 156 | // OUTPUT: 157 | } 158 | ``` 159 | 160 | # STATUS 161 | 162 | * Requires more testing for array/map/struct types 163 | 164 | # DESCRIPTION 165 | 166 | While tinkering with low-level `msgpack` stuff for the first time, 167 | I realized that I didn't know enough about its internal workings to make 168 | suggestions of have confidence producing bug reports, and I really 169 | should: So I wrote one for my own amusement and education. 170 | 171 | # FEATURES 172 | 173 | ## API Compatibility With stdlib 174 | 175 | `github.com/vmihailenco/msgpack.v2`, which this library was initially 176 | based upon, has subtle differences with the stdlib. For example, 177 | `"github.com/vmihailenco/msgpack.v2".Decoder.Decode()` has a signature 178 | of `Decode(v ...interface{})`, which doesn't match with the signature 179 | in, for example, `encoding/json`. This subtle difference makes it hard 180 | to use interfaces to make swappable serializers. 181 | 182 | Also, all decoding API takes an argument to be assigned to instead of 183 | returning a value. 184 | 185 | ## Custom Serialization 186 | 187 | If you would like to customize serialization for a particular type, 188 | you can create a type that implements the `msgpack.EncodeMsgpacker` 189 | and/or `msgpack.DecodeMsgpacker` interface. 190 | 191 | ```go 192 | func (v *Object) EncodeMsgpack(e msgpack.Encoder) error { 193 | ... 194 | } 195 | 196 | func (v *Object) DecodeMsgpack(d msgpack.Decoder) error { 197 | ... 198 | } 199 | ``` 200 | 201 | Please note that while the Encoder/Decoder instance that you get from 202 | normal instatiation (`NewEncoder()/NewDecoder()`) are protected by mutexes 203 | to avoid accidental race conditions by the user, the instances passed to 204 | these methods above _ARE NOT_ safe to be used concurrently. You should also 205 | never store these values for later use. 206 | 207 | ## Low Level Writer/Reader 208 | 209 | In some rare cases, such as when you are creating extensions, you need 210 | a more fine grained control on what you read or write. For this, you may 211 | use the `msgpack.Writer` and `msgpack.Reader` objects. 212 | 213 | These objects know how to read or write bytes of data in the correct 214 | byte order. 215 | 216 | ## Struct Tags 217 | 218 | Struct tags are supported via the `msgpack` keyword. The syntax follows that of 219 | `encoding/json` package: 220 | 221 | ```go 222 | type Example struct { 223 | Foo struct `msgpack:"foo"` 224 | Bar struct `msgpack:"bar,omitempty"` 225 | } 226 | ``` 227 | 228 | For convenience for those migrating from github.com/tinylib/msgpack, we also 229 | support the "msg" struct tag. 230 | 231 | # PROS/CONS 232 | 233 | ## PROS 234 | 235 | As most late comers are, I believe the project is a little bit cleaner than my predecessors, which **possibly** could mean a slightly easier experience for the users to hack and tweak it. I know, it's very subjective. 236 | 237 | As far as comparisons against `gopkg.in/vmihailenco/msgpack.v2` goes, this library tries to keep the API as compatible as possible to the standard library's `encoding/*` packages. For example, `encoding/json` allows: 238 | 239 | ```go 240 | b, _ := json.Marshal(true) 241 | 242 | // using uninitialized empty interface 243 | var v interface{} 244 | json.Unmarshal(b, &v) 245 | ``` 246 | 247 | But if you do the same with `gopkg.in/vmihailenco/msgpack.v2`, this throws a panic: 248 | 249 | ```go 250 | b, _ := msgpack.Marshal(true) 251 | 252 | // using uninitialized empty interface 253 | var v interface{} 254 | msgpack.Unmarshal(b, &v) 255 | ``` 256 | 257 | This library follows the semantics for `encoding/json`, and you can safely pass an uninitialized empty inteface to Unmarsha/Decode 258 | 259 | ## CONS 260 | 261 | As previously described, I have been learning by implementing this library. 262 | I intend to work on it until I'm satisfied, but unless you are the type of 263 | person who likes to live on the bleeding edge, you probably want to use another library. 264 | 265 | # BENCHMARKS 266 | 267 | Current status 268 | 269 | ``` 270 | $ go test -tags bench -v -run=none -benchmem -bench . 271 | BenchmarkEncodeFloat32/___lestrrat/float32_via_Encode()-4 30000000 51.0 ns/op 4 B/op 1 allocs/op 272 | BenchmarkEncodeFloat32/___lestrrat/float32_via_EncodeFloat32()-4 100000000 22.4 ns/op 0 B/op 0 allocs/op 273 | BenchmarkEncodeFloat32/vmihailenco/float32_via_Encode()-4 20000000 55.8 ns/op 4 B/op 1 allocs/op 274 | BenchmarkEncodeFloat32/vmihailenco/float32_via_EncodeFloat32()-4 100000000 23.9 ns/op 0 B/op 0 allocs/op 275 | BenchmarkEncodeFloat64/___lestrrat/float64_via_Encode()-4 30000000 57.7 ns/op 8 B/op 1 allocs/op 276 | BenchmarkEncodeFloat64/___lestrrat/float64_via_EncodeFloat64()-4 100000000 25.6 ns/op 0 B/op 0 allocs/op 277 | BenchmarkEncodeFloat64/vmihailenco/float64_via_Encode()-4 20000000 60.4 ns/op 8 B/op 1 allocs/op 278 | BenchmarkEncodeFloat64/vmihailenco/float64_via_EncodeFloat64()-4 50000000 25.7 ns/op 0 B/op 0 allocs/op 279 | BenchmarkEncodeUint8/___lestrrat/uint8_via_Encode()-4 30000000 43.8 ns/op 1 B/op 1 allocs/op 280 | BenchmarkEncodeUint8/___lestrrat/uint8_via_EncodeUint8()-4 100000000 22.7 ns/op 0 B/op 0 allocs/op 281 | BenchmarkEncodeUint8/vmihailenco/uint8_via_Encode()-4 10000000 178 ns/op 1 B/op 1 allocs/op 282 | BenchmarkEncodeUint8/vmihailenco/uint8_via_EncodeUint8()-4 50000000 26.9 ns/op 0 B/op 0 allocs/op 283 | BenchmarkEncodeUint16/___lestrrat/uint16_via_Encode()-4 20000000 54.0 ns/op 2 B/op 1 allocs/op 284 | BenchmarkEncodeUint16/___lestrrat/uint16_via_EncodeUint16()-4 100000000 24.6 ns/op 0 B/op 0 allocs/op 285 | BenchmarkEncodeUint16/vmihailenco/uint16_via_Encode()-4 5000000 210 ns/op 2 B/op 1 allocs/op 286 | BenchmarkEncodeUint16/vmihailenco/uint16_via_EncodeUint16()-4 50000000 27.1 ns/op 0 B/op 0 allocs/op 287 | BenchmarkEncodeUint32/___lestrrat/uint32_via_Encode()-4 20000000 56.2 ns/op 4 B/op 1 allocs/op 288 | BenchmarkEncodeUint32/___lestrrat/uint32_via_EncodeUint32()-4 50000000 23.5 ns/op 0 B/op 0 allocs/op 289 | BenchmarkEncodeUint32/vmihailenco/uint32_via_Encode()-4 10000000 203 ns/op 4 B/op 1 allocs/op 290 | BenchmarkEncodeUint32/vmihailenco/uint32_via_EncodeUint32()-4 50000000 49.7 ns/op 0 B/op 0 allocs/op 291 | BenchmarkEncodeUint64/___lestrrat/uint64_via_Encode()-4 20000000 75.2 ns/op 8 B/op 1 allocs/op 292 | BenchmarkEncodeUint64/___lestrrat/uint64_via_EncodeUint64()-4 50000000 29.9 ns/op 0 B/op 0 allocs/op 293 | BenchmarkEncodeUint64/vmihailenco/uint64_via_Encode()-4 20000000 82.9 ns/op 8 B/op 1 allocs/op 294 | BenchmarkEncodeUint64/vmihailenco/uint64_via_EncodeUint64()-4 50000000 40.8 ns/op 0 B/op 0 allocs/op 295 | BenchmarkEncodeInt8/___lestrrat/int8_via_Encode()-4 20000000 61.3 ns/op 1 B/op 1 allocs/op 296 | BenchmarkEncodeInt8/___lestrrat/int8_via_EncodeInt8()-4 30000000 37.8 ns/op 0 B/op 0 allocs/op 297 | BenchmarkEncodeInt8/vmihailenco/int8_via_Encode()-4 5000000 277 ns/op 2 B/op 2 allocs/op 298 | BenchmarkEncodeInt8/vmihailenco/int8_via_EncodeInt8()-4 20000000 52.3 ns/op 1 B/op 1 allocs/op 299 | BenchmarkEncodeInt8FixNum/___lestrrat/int8_via_Encode()-4 20000000 63.2 ns/op 1 B/op 1 allocs/op 300 | BenchmarkEncodeInt8FixNum/___lestrrat/int8_via_EncodeInt8()-4 50000000 26.7 ns/op 0 B/op 0 allocs/op 301 | BenchmarkEncodeInt8FixNum/vmihailenco/int8_via_Encode()-4 5000000 210 ns/op 2 B/op 2 allocs/op 302 | BenchmarkEncodeInt8FixNum/vmihailenco/int8_via_EncodeInt8()-4 50000000 35.1 ns/op 1 B/op 1 allocs/op 303 | BenchmarkEncodeInt16/___lestrrat/int16_via_Encode()-4 30000000 50.4 ns/op 2 B/op 1 allocs/op 304 | BenchmarkEncodeInt16/___lestrrat/int16_via_EncodeInt16()-4 100000000 23.4 ns/op 0 B/op 0 allocs/op 305 | BenchmarkEncodeInt16/vmihailenco/int16_via_Encode()-4 10000000 186 ns/op 2 B/op 1 allocs/op 306 | BenchmarkEncodeInt16/vmihailenco/int16_via_EncodeInt16()-4 50000000 44.7 ns/op 0 B/op 0 allocs/op 307 | BenchmarkEncodeInt32/___lestrrat/int32_via_Encode()-4 20000000 67.5 ns/op 4 B/op 1 allocs/op 308 | BenchmarkEncodeInt32/___lestrrat/int32_via_EncodeInt32()-4 50000000 33.0 ns/op 0 B/op 0 allocs/op 309 | BenchmarkEncodeInt32/vmihailenco/int32_via_Encode()-4 5000000 301 ns/op 4 B/op 1 allocs/op 310 | BenchmarkEncodeInt32/vmihailenco/int32_via_EncodeInt32()-4 50000000 32.1 ns/op 0 B/op 0 allocs/op 311 | BenchmarkEncodeInt64/___lestrrat/int64_via_Encode()-4 30000000 56.9 ns/op 8 B/op 1 allocs/op 312 | BenchmarkEncodeInt64/___lestrrat/int64_via_EncodeInt64()-4 100000000 24.8 ns/op 0 B/op 0 allocs/op 313 | BenchmarkEncodeInt64/vmihailenco/int64_via_Encode()-4 20000000 62.3 ns/op 8 B/op 1 allocs/op 314 | BenchmarkEncodeInt64/vmihailenco/int64_via_EncodeInt64()-4 50000000 30.6 ns/op 0 B/op 0 allocs/op 315 | BenchmarkEncodeString/___lestrrat/string_(255_bytes)_via_Encode()-4 10000000 208 ns/op 272 B/op 2 allocs/op 316 | BenchmarkEncodeString/___lestrrat/string_(255_bytes)_via_EncodeString()-4 10000000 149 ns/op 256 B/op 1 allocs/op 317 | BenchmarkEncodeString/___lestrrat/string_(256_bytes)_via_Encode()-4 10000000 190 ns/op 272 B/op 2 allocs/op 318 | BenchmarkEncodeString/___lestrrat/string_(256_bytes)_via_EncodeString()-4 10000000 153 ns/op 256 B/op 1 allocs/op 319 | BenchmarkEncodeString/___lestrrat/string_(65536_bytes)_via_Encode()-4 100000 13031 ns/op 65552 B/op 2 allocs/op 320 | BenchmarkEncodeString/___lestrrat/string_(65536_bytes)_via_EncodeString()-4 100000 13420 ns/op 65536 B/op 1 allocs/op 321 | BenchmarkEncodeString/vmihailenco/string_(255_bytes)_via_Encode()-4 10000000 204 ns/op 272 B/op 2 allocs/op 322 | BenchmarkEncodeString/vmihailenco/string_(255_bytes)_via_EncodeString()-4 10000000 148 ns/op 256 B/op 1 allocs/op 323 | BenchmarkEncodeString/vmihailenco/string_(256_bytes)_via_Encode()-4 10000000 206 ns/op 272 B/op 2 allocs/op 324 | BenchmarkEncodeString/vmihailenco/string_(256_bytes)_via_EncodeString()-4 10000000 163 ns/op 256 B/op 1 allocs/op 325 | BenchmarkEncodeString/vmihailenco/string_(65536_bytes)_via_Encode()-4 100000 14108 ns/op 65552 B/op 2 allocs/op 326 | BenchmarkEncodeString/vmihailenco/string_(65536_bytes)_via_EncodeString()-4 100000 19093 ns/op 65536 B/op 1 allocs/op 327 | BenchmarkEncodeArray/___lestrrat/array_via_Encode()-4 3000000 484 ns/op 56 B/op 4 allocs/op 328 | BenchmarkEncodeArray/___lestrrat/array_via_EncodeArray()-4 5000000 345 ns/op 56 B/op 4 allocs/op 329 | BenchmarkEncodeArray/vmihailenco/array_via_Encode()-4 2000000 757 ns/op 33 B/op 2 allocs/op 330 | BenchmarkEncodeMap/___lestrrat/map_via_Encode()-4 2000000 994 ns/op 208 B/op 8 allocs/op 331 | BenchmarkEncodeMap/___lestrrat/map_via_EncodeMap()-4 1000000 1092 ns/op 208 B/op 8 allocs/op 332 | BenchmarkEncodeMap/vmihailenco/map_via_Encode()-4 1000000 1995 ns/op 224 B/op 11 allocs/op 333 | BenchmarkDecodeUint8/___lestrrat/uint8_via_DecodeUint8()-4 20000000 60.0 ns/op 0 B/op 0 allocs/op 334 | BenchmarkDecodeUint8/vmihailenco/uint8_via_DecodeUint8()_(return)-4 30000000 54.2 ns/op 0 B/op 0 allocs/op 335 | BenchmarkDecodeUint16/___lestrrat/uint16_via_DecodeUint16()-4 30000000 53.6 ns/op 0 B/op 0 allocs/op 336 | BenchmarkDecodeUint16/vmihailenco/uint16_via_DecodeUint16()_(return)-4 20000000 94.0 ns/op 0 B/op 0 allocs/op 337 | BenchmarkDecodeUint32/___lestrrat/uint32_via_DecodeUint32()-4 30000000 45.7 ns/op 0 B/op 0 allocs/op 338 | BenchmarkDecodeUint32/vmihailenco/uint32_via_DecodeUint32()_(return)-4 20000000 92.8 ns/op 0 B/op 0 allocs/op 339 | BenchmarkDecodeUint64/___lestrrat/uint64_via_DecodeUint64()-4 30000000 48.5 ns/op 0 B/op 0 allocs/op 340 | BenchmarkDecodeUint64/vmihailenco/uint64_via_DecodeUint64()_(return)-4 20000000 86.1 ns/op 0 B/op 0 allocs/op 341 | BenchmarkDecodeInt8FixNum/___lestrrat/int8_via_DecodeInt8()-4 50000000 34.8 ns/op 0 B/op 0 allocs/op 342 | BenchmarkDecodeInt8FixNum/vmihailenco/int8_via_DecodeInt8()_(return)-4 30000000 42.2 ns/op 0 B/op 0 allocs/op 343 | BenchmarkDecodeInt8/___lestrrat/int8_via_DecodeInt8()-4 30000000 48.6 ns/op 0 B/op 0 allocs/op 344 | BenchmarkDecodeInt8/vmihailenco/int8_via_DecodeInt8()_(return)-4 30000000 55.5 ns/op 0 B/op 0 allocs/op 345 | BenchmarkDecodeInt16/___lestrrat/int16_via_DecodeInt16()-4 30000000 47.2 ns/op 0 B/op 0 allocs/op 346 | BenchmarkDecodeInt16/vmihailenco/int16_via_DecodeInt16()_(return)-4 20000000 87.8 ns/op 0 B/op 0 allocs/op 347 | BenchmarkDecodeInt32/___lestrrat/int32_via_DecodeInt32()-4 30000000 44.3 ns/op 0 B/op 0 allocs/op 348 | BenchmarkDecodeInt32/vmihailenco/int32_via_DecodeInt32()_(return)-4 20000000 87.5 ns/op 0 B/op 0 allocs/op 349 | BenchmarkDecodeInt64/___lestrrat/int64_via_DecodeInt64()-4 30000000 47.6 ns/op 0 B/op 0 allocs/op 350 | BenchmarkDecodeInt64/vmihailenco/int64_via_DecodeInt64()_(return)-4 20000000 84.3 ns/op 0 B/op 0 allocs/op 351 | BenchmarkDecodeFloat32/___lestrrat/float32_via_DecodeFloat32()-4 30000000 39.1 ns/op 0 B/op 0 allocs/op 352 | BenchmarkDecodeFloat32/vmihailenco/float32_via_DecodeFloat32()_(return)-4 20000000 82.0 ns/op 0 B/op 0 allocs/op 353 | BenchmarkDecodeFloat64/___lestrrat/float64_via_DecodeFloat64()-4 30000000 38.4 ns/op 0 B/op 0 allocs/op 354 | BenchmarkDecodeFloat64/vmihailenco/float64_via_DecodeFloat64()_(return)-4 20000000 84.7 ns/op 0 B/op 0 allocs/op 355 | BenchmarkDecodeString/___lestrrat/string_via_Decode()-4 5000000 294 ns/op 256 B/op 1 allocs/op 356 | BenchmarkDecodeString/___lestrrat/string_via_DecodeString()-4 5000000 288 ns/op 256 B/op 1 allocs/op 357 | BenchmarkDecodeString/vmihailenco/string_via_Decode()-4 10000000 223 ns/op 256 B/op 1 allocs/op 358 | BenchmarkDecodeString/vmihailenco/string_via_DecodeString()_(return)-4 10000000 211 ns/op 256 B/op 1 allocs/op 359 | BenchmarkDecodeArray/___lestrrat/array_via_Decode()_(concrete)-4 2000000 773 ns/op 104 B/op 5 allocs/op 360 | BenchmarkDecodeArray/___lestrrat/array_via_Decode()_(interface{})-4 2000000 942 ns/op 120 B/op 6 allocs/op 361 | BenchmarkDecodeArray/___lestrrat/array_via_DecodeArray()-4 2000000 763 ns/op 104 B/op 5 allocs/op 362 | BenchmarkDecodeArray/vmihailenco/array_via_Decode()_(concrete)-4 1000000 1607 ns/op 248 B/op 9 allocs/op 363 | BenchmarkDecodeArray/vmihailenco/array_via_Decode()_(interface{})-4 2000000 727 ns/op 120 B/op 6 allocs/op 364 | BenchmarkDecodeMap/___lestrrat/map_via_Decode()-4 1000000 1660 ns/op 440 B/op 12 allocs/op 365 | BenchmarkDecodeMap/___lestrrat/map_via_DecodeMap()-4 1000000 1609 ns/op 440 B/op 12 allocs/op 366 | BenchmarkDecodeMap/vmihailenco/map_via_Decode()-4 1000000 1070 ns/op 392 B/op 9 allocs/op 367 | PASS 368 | ok github.com/lestrrat-go/msgpack 171.139s 369 | ``` 370 | 371 | # ACKNOWLEDGEMENTS 372 | 373 | Much has been stolen from https://github.com/vmihailenco/msgpack 374 | -------------------------------------------------------------------------------- /encoder_test.go: -------------------------------------------------------------------------------- 1 | package msgpack_test 2 | 3 | import ( 4 | "bytes" 5 | "encoding/binary" 6 | "fmt" 7 | "io/ioutil" 8 | "math" 9 | "testing" 10 | 11 | msgpack "github.com/lestrrat-go/msgpack" 12 | "github.com/stretchr/testify/assert" 13 | ) 14 | 15 | type tagTest struct { 16 | Foo string `msg:"foooo"` 17 | Bar string `msgpack:"baaaaaaar"` 18 | Baz string `msgpack:"-"` 19 | } 20 | 21 | func TestTag(t *testing.T) { 22 | t.Parallel() 23 | v := tagTest{ 24 | Foo: "Hello", 25 | Bar: "World!", 26 | Baz: "Abracadabra", 27 | } 28 | 29 | data, err := msgpack.Marshal(v) 30 | if !assert.NoError(t, err, "msgpack.Marshal should succeed") { 31 | return 32 | } 33 | 34 | var m = make(map[string]interface{}) 35 | if !assert.NoError(t, msgpack.Unmarshal(data, &m), "msgpack.Unmarshal should succeed") { 36 | return 37 | } 38 | 39 | if !assert.Equal(t, m["foooo"], "Hello", "key foooo should match") { 40 | return 41 | } 42 | if !assert.Equal(t, m["baaaaaaar"], "World!", "key baaaaaaar should match") { 43 | return 44 | } 45 | if !assert.Empty(t, m["Baz"], "key baaaaaaar should match") { 46 | return 47 | } 48 | } 49 | 50 | func TestEncodeMapInvalidValue(t *testing.T) { 51 | t.Parallel() 52 | var f struct { 53 | Foo string 54 | } 55 | 56 | // shouldn't panic 57 | msgpack.NewEncoder(ioutil.Discard).EncodeMap(f) 58 | } 59 | 60 | func TestEncodeNil(t *testing.T) { 61 | t.Parallel() 62 | var e = []byte{msgpack.Nil.Byte()} 63 | 64 | t.Run("encode via Marshal", func(t *testing.T) { 65 | t.Parallel() 66 | b, err := msgpack.Marshal(nil) 67 | if !assert.NoError(t, err, "Marshal should succeed") { 68 | return 69 | } 70 | 71 | if !assert.Equal(t, e, b, "Output should match") { 72 | return 73 | } 74 | }) 75 | t.Run("encode via Encode", func(t *testing.T) { 76 | t.Parallel() 77 | var buf bytes.Buffer 78 | if !assert.NoError(t, msgpack.NewEncoder(&buf).Encode(nil), "Encode should succeed") { 79 | return 80 | } 81 | 82 | if !assert.Equal(t, e, buf.Bytes(), "Output should match") { 83 | return 84 | } 85 | }) 86 | t.Run("encode via EncodeNil", func(t *testing.T) { 87 | t.Parallel() 88 | var buf bytes.Buffer 89 | if !assert.NoError(t, msgpack.NewEncoder(&buf).EncodeNil(), "EncodeNil should succeed") { 90 | return 91 | } 92 | 93 | if !assert.Equal(t, e, buf.Bytes(), "Output should match") { 94 | return 95 | } 96 | }) 97 | } 98 | 99 | func TestEncodeBool(t *testing.T) { 100 | t.Parallel() 101 | for _, code := range []msgpack.Code{msgpack.True, msgpack.False} { 102 | var v bool 103 | if code == msgpack.True { 104 | v = true 105 | } 106 | var e = []byte{code.Byte()} 107 | 108 | t.Run(fmt.Sprintf("encode %s via Marshal", code), func(t *testing.T) { 109 | t.Parallel() 110 | b, err := msgpack.Marshal(v) 111 | if !assert.NoError(t, err, "Marshal should succeed") { 112 | return 113 | } 114 | if !assert.Equal(t, e, b, "Output should match") { 115 | return 116 | } 117 | }) 118 | t.Run(fmt.Sprintf("encode %s via EncodeBool", code), func(t *testing.T) { 119 | t.Parallel() 120 | var buf bytes.Buffer 121 | if !assert.NoError(t, msgpack.NewEncoder(&buf).EncodeBool(v), "EncodeBool should succeed") { 122 | return 123 | } 124 | if !assert.Equal(t, e, buf.Bytes(), "Output should match") { 125 | return 126 | } 127 | }) 128 | t.Run(fmt.Sprintf("encode %s via Encode", code), func(t *testing.T) { 129 | t.Parallel() 130 | var buf bytes.Buffer 131 | if !assert.NoError(t, msgpack.NewEncoder(&buf).Encode(v), "Encode should succeed") { 132 | return 133 | } 134 | 135 | if !assert.Equal(t, e, buf.Bytes(), "Output should match") { 136 | return 137 | } 138 | }) 139 | } 140 | } 141 | 142 | func TestEncodeFloat32(t *testing.T) { 143 | t.Parallel() 144 | var v = float32(math.MaxFloat32) 145 | var e = make([]byte, 5) 146 | e[0] = msgpack.Float.Byte() 147 | binary.BigEndian.PutUint32(e[1:], math.Float32bits(v)) 148 | 149 | t.Run("encode via Marshal", func(t *testing.T) { 150 | t.Parallel() 151 | b, err := msgpack.Marshal(v) 152 | if !assert.NoError(t, err, "Marshal should succeed") { 153 | return 154 | } 155 | if !assert.Equal(t, e, b, "Output should match") { 156 | return 157 | } 158 | }) 159 | t.Run("encode via EncodeFloat32", func(t *testing.T) { 160 | t.Parallel() 161 | var buf bytes.Buffer 162 | if !assert.NoError(t, msgpack.NewEncoder(&buf).EncodeFloat32(v), "EncodeFloat32 should succeed") { 163 | return 164 | } 165 | 166 | if !assert.Equal(t, e, buf.Bytes(), "Output should match") { 167 | return 168 | } 169 | }) 170 | t.Run("encode via Encode", func(t *testing.T) { 171 | t.Parallel() 172 | var buf bytes.Buffer 173 | if !assert.NoError(t, msgpack.NewEncoder(&buf).Encode(v), "Encode should succeed") { 174 | return 175 | } 176 | 177 | if !assert.Equal(t, e, buf.Bytes(), "Output should match") { 178 | return 179 | } 180 | }) 181 | } 182 | 183 | func TestEncodeFloat64(t *testing.T) { 184 | t.Parallel() 185 | var v = float64(math.MaxFloat64) 186 | var e = make([]byte, 9) 187 | e[0] = msgpack.Double.Byte() 188 | binary.BigEndian.PutUint64(e[1:], math.Float64bits(v)) 189 | 190 | t.Run("encode via Marshal", func(t *testing.T) { 191 | t.Parallel() 192 | b, err := msgpack.Marshal(v) 193 | if !assert.NoError(t, err, "Marshal should succeed") { 194 | return 195 | } 196 | if !assert.Equal(t, e, b, "Output should match") { 197 | return 198 | } 199 | }) 200 | t.Run("encode via EncodeFloat64", func(t *testing.T) { 201 | t.Parallel() 202 | var buf bytes.Buffer 203 | if !assert.NoError(t, msgpack.NewEncoder(&buf).EncodeFloat64(v), "EncodeFloat64 should succeed") { 204 | return 205 | } 206 | 207 | if !assert.Equal(t, e, buf.Bytes(), "Output should match") { 208 | return 209 | } 210 | }) 211 | t.Run("encode via Encode", func(t *testing.T) { 212 | t.Parallel() 213 | var buf bytes.Buffer 214 | if !assert.NoError(t, msgpack.NewEncoder(&buf).Encode(v), "Encode should succeed") { 215 | return 216 | } 217 | 218 | if !assert.Equal(t, e, buf.Bytes(), "Output should match") { 219 | return 220 | } 221 | }) 222 | } 223 | 224 | func TestEncodeUint8(t *testing.T) { 225 | t.Parallel() 226 | var v = uint8(math.MaxUint8) 227 | var e = []byte{msgpack.Uint8.Byte(), byte(v)} 228 | 229 | t.Run("encode via Marshal", func(t *testing.T) { 230 | t.Parallel() 231 | b, err := msgpack.Marshal(v) 232 | if !assert.NoError(t, err, "Marshal should succeed") { 233 | return 234 | } 235 | 236 | if !assert.Equal(t, e, b, "Output should match") { 237 | return 238 | } 239 | }) 240 | 241 | t.Run("encode via EncodeUint8", func(t *testing.T) { 242 | t.Parallel() 243 | var buf bytes.Buffer 244 | if !assert.NoError(t, msgpack.NewEncoder(&buf).EncodeUint8(v), "EncodeUint8 should succeed") { 245 | return 246 | } 247 | 248 | if !assert.Equal(t, e, buf.Bytes(), "Output should match") { 249 | return 250 | } 251 | }) 252 | 253 | t.Run("encode via Encoder", func(t *testing.T) { 254 | t.Parallel() 255 | var buf bytes.Buffer 256 | if !assert.NoError(t, msgpack.NewEncoder(&buf).Encode(v), "Encode should succeed") { 257 | return 258 | } 259 | 260 | if !assert.Equal(t, e, buf.Bytes(), "Output should match") { 261 | return 262 | } 263 | }) 264 | } 265 | 266 | func TestEncodeUint16(t *testing.T) { 267 | t.Parallel() 268 | var v = uint16(math.MaxUint16) 269 | var e = make([]byte, 3) 270 | e[0] = msgpack.Uint16.Byte() 271 | binary.BigEndian.PutUint16(e[1:], v) 272 | 273 | t.Run("encode via Marshal", func(t *testing.T) { 274 | t.Parallel() 275 | b, err := msgpack.Marshal(v) 276 | if !assert.NoError(t, err, "Marshal should succeed") { 277 | return 278 | } 279 | 280 | if !assert.Equal(t, e, b, "Output should match") { 281 | return 282 | } 283 | }) 284 | 285 | t.Run("encode via EncodeUint16", func(t *testing.T) { 286 | t.Parallel() 287 | var buf bytes.Buffer 288 | if !assert.NoError(t, msgpack.NewEncoder(&buf).EncodeUint16(v), "EncodeUint16 should succeed") { 289 | return 290 | } 291 | 292 | if !assert.Equal(t, e, buf.Bytes(), "Output should match") { 293 | return 294 | } 295 | }) 296 | 297 | t.Run("encode via Encoder", func(t *testing.T) { 298 | t.Parallel() 299 | var buf bytes.Buffer 300 | if !assert.NoError(t, msgpack.NewEncoder(&buf).Encode(v), "Encode should succeed") { 301 | return 302 | } 303 | 304 | if !assert.Equal(t, e, buf.Bytes(), "Output should match") { 305 | return 306 | } 307 | }) 308 | } 309 | 310 | func TestEncodeUint32(t *testing.T) { 311 | t.Parallel() 312 | var v = uint32(math.MaxUint32) 313 | var e = make([]byte, 5) 314 | e[0] = msgpack.Uint32.Byte() 315 | binary.BigEndian.PutUint32(e[1:], v) 316 | 317 | t.Run("encode via Marshal", func(t *testing.T) { 318 | t.Parallel() 319 | b, err := msgpack.Marshal(v) 320 | if !assert.NoError(t, err, "Marshal should succeed") { 321 | return 322 | } 323 | 324 | if !assert.Equal(t, e, b, "Output should match") { 325 | return 326 | } 327 | }) 328 | 329 | t.Run("encode via EncodeUint32", func(t *testing.T) { 330 | t.Parallel() 331 | var buf bytes.Buffer 332 | if !assert.NoError(t, msgpack.NewEncoder(&buf).EncodeUint32(v), "EncodeUint32 should succeed") { 333 | return 334 | } 335 | 336 | if !assert.Equal(t, e, buf.Bytes(), "Output should match") { 337 | return 338 | } 339 | }) 340 | 341 | t.Run("encode via Encoder", func(t *testing.T) { 342 | t.Parallel() 343 | var buf bytes.Buffer 344 | if !assert.NoError(t, msgpack.NewEncoder(&buf).Encode(v), "Encode should succeed") { 345 | return 346 | } 347 | 348 | if !assert.Equal(t, e, buf.Bytes(), "Output should match") { 349 | return 350 | } 351 | }) 352 | } 353 | 354 | func TestEncodeUint64(t *testing.T) { 355 | t.Parallel() 356 | var v = uint64(math.MaxUint64) 357 | var e = make([]byte, 9) 358 | e[0] = msgpack.Uint64.Byte() 359 | binary.BigEndian.PutUint64(e[1:], v) 360 | 361 | t.Run("encode via Marshal", func(t *testing.T) { 362 | t.Parallel() 363 | b, err := msgpack.Marshal(v) 364 | if !assert.NoError(t, err, "Marshal should succeed") { 365 | return 366 | } 367 | 368 | if !assert.Equal(t, e, b, "Output should match") { 369 | return 370 | } 371 | }) 372 | 373 | t.Run("encode via EncodeUint64", func(t *testing.T) { 374 | t.Parallel() 375 | var buf bytes.Buffer 376 | if !assert.NoError(t, msgpack.NewEncoder(&buf).EncodeUint64(v), "EncodeUint64 should succeed") { 377 | return 378 | } 379 | 380 | if !assert.Equal(t, e, buf.Bytes(), "Output should match") { 381 | return 382 | } 383 | }) 384 | 385 | t.Run("encode via Encoder", func(t *testing.T) { 386 | t.Parallel() 387 | var buf bytes.Buffer 388 | if !assert.NoError(t, msgpack.NewEncoder(&buf).Encode(v), "Encode should succeed") { 389 | return 390 | } 391 | 392 | if !assert.Equal(t, e, buf.Bytes(), "Output should match") { 393 | return 394 | } 395 | }) 396 | } 397 | 398 | func TestEncodePositiveFixNum(t *testing.T) { 399 | t.Parallel() 400 | for i := 0; i < 127; i++ { 401 | i := i 402 | t.Run(fmt.Sprintf("encode %d should result in fix num", i), func(t *testing.T) { 403 | t.Parallel() 404 | b, err := msgpack.Marshal(uint(i)) 405 | if !assert.NoError(t, err, `msgpack.Marshal should succeed`) { 406 | return 407 | } 408 | 409 | if !assert.Len(t, b, 1, "encoded number should be 1 byte") { 410 | return 411 | } 412 | 413 | // linter says b[0] >= 0 is unnnecessary, so, yeah. 414 | if !assert.True(t, b[0] <= 127, "b should be 0 <= b <= 127") { 415 | return 416 | } 417 | }) 418 | } 419 | } 420 | 421 | func TestEncodeNegativeFixNum(t *testing.T) { 422 | t.Parallel() 423 | for i := -1; i < 0; i++ { 424 | i := i 425 | t.Run(fmt.Sprintf("encode %d should result in fix num", i), func(t *testing.T) { 426 | t.Parallel() 427 | b, err := msgpack.Marshal(int(i)) 428 | if !assert.NoError(t, err, `msgpack.Marshal should succeed`) { 429 | return 430 | } 431 | 432 | if !assert.Len(t, b, 1, "encoded number should be 1 byte") { 433 | return 434 | } 435 | 436 | if !assert.Equal(t, i, int(int8(b[0])), "b should be negative number") { 437 | return 438 | } 439 | }) 440 | } 441 | } 442 | 443 | func TestEncodeInt8(t *testing.T) { 444 | t.Parallel() 445 | var v = int8(math.MaxInt8) 446 | var e = []byte{msgpack.Int8.Byte(), byte(v)} 447 | 448 | t.Run("encode via Marshal", func(t *testing.T) { 449 | t.Parallel() 450 | b, err := msgpack.Marshal(v) 451 | if !assert.NoError(t, err, "Marshal should succeed") { 452 | return 453 | } 454 | 455 | if !assert.Equal(t, e, b, "Output should match") { 456 | return 457 | } 458 | }) 459 | 460 | t.Run("encode via EncodeInt8", func(t *testing.T) { 461 | t.Parallel() 462 | var buf bytes.Buffer 463 | if !assert.NoError(t, msgpack.NewEncoder(&buf).EncodeInt8(v), "EncodeInt8 should succeed") { 464 | return 465 | } 466 | 467 | if !assert.Equal(t, e, buf.Bytes(), "Output should match") { 468 | return 469 | } 470 | }) 471 | 472 | t.Run("encode via Encoder", func(t *testing.T) { 473 | t.Parallel() 474 | var buf bytes.Buffer 475 | if !assert.NoError(t, msgpack.NewEncoder(&buf).Encode(v), "Encode should succeed") { 476 | return 477 | } 478 | 479 | if !assert.Equal(t, e, buf.Bytes(), "Output should match") { 480 | return 481 | } 482 | }) 483 | } 484 | 485 | func TestEncodeInt16(t *testing.T) { 486 | t.Parallel() 487 | var v = int16(math.MaxInt16) 488 | var e = make([]byte, 3) 489 | e[0] = msgpack.Int16.Byte() 490 | binary.BigEndian.PutUint16(e[1:], uint16(v)) 491 | 492 | t.Run("encode via Marshal", func(t *testing.T) { 493 | t.Parallel() 494 | b, err := msgpack.Marshal(v) 495 | if !assert.NoError(t, err, "Marshal should succeed") { 496 | return 497 | } 498 | 499 | if !assert.Equal(t, e, b, "Output should match") { 500 | return 501 | } 502 | }) 503 | 504 | t.Run("encode via EncodeInt16", func(t *testing.T) { 505 | t.Parallel() 506 | var buf bytes.Buffer 507 | if !assert.NoError(t, msgpack.NewEncoder(&buf).EncodeInt16(v), "EncodeInt16 should succeed") { 508 | return 509 | } 510 | 511 | if !assert.Equal(t, e, buf.Bytes(), "Output should match") { 512 | return 513 | } 514 | }) 515 | 516 | t.Run("encode via Encoder", func(t *testing.T) { 517 | t.Parallel() 518 | var buf bytes.Buffer 519 | if !assert.NoError(t, msgpack.NewEncoder(&buf).Encode(v), "Encode should succeed") { 520 | return 521 | } 522 | 523 | if !assert.Equal(t, e, buf.Bytes(), "Output should match") { 524 | return 525 | } 526 | }) 527 | } 528 | 529 | func TestEncodeInt32(t *testing.T) { 530 | t.Parallel() 531 | var v = int32(math.MaxInt32) 532 | var e = make([]byte, 5) 533 | e[0] = msgpack.Int32.Byte() 534 | binary.BigEndian.PutUint32(e[1:], uint32(v)) 535 | 536 | t.Run("encode via Marshal", func(t *testing.T) { 537 | t.Parallel() 538 | b, err := msgpack.Marshal(v) 539 | if !assert.NoError(t, err, "Marshal should succeed") { 540 | return 541 | } 542 | 543 | if !assert.Equal(t, e, b, "Output should match") { 544 | return 545 | } 546 | }) 547 | 548 | t.Run("encode via EncodeInt32", func(t *testing.T) { 549 | t.Parallel() 550 | var buf bytes.Buffer 551 | if !assert.NoError(t, msgpack.NewEncoder(&buf).EncodeInt32(v), "EncodeInt32 should succeed") { 552 | return 553 | } 554 | 555 | if !assert.Equal(t, e, buf.Bytes(), "Output should match") { 556 | return 557 | } 558 | }) 559 | 560 | t.Run("encode via Encoder", func(t *testing.T) { 561 | t.Parallel() 562 | var buf bytes.Buffer 563 | if !assert.NoError(t, msgpack.NewEncoder(&buf).Encode(v), "Encode should succeed") { 564 | return 565 | } 566 | 567 | if !assert.Equal(t, e, buf.Bytes(), "Output should match") { 568 | return 569 | } 570 | }) 571 | } 572 | 573 | func TestEncodeInt64(t *testing.T) { 574 | t.Parallel() 575 | var v = int64(math.MaxInt64) 576 | var e = make([]byte, 9) 577 | e[0] = msgpack.Int64.Byte() 578 | binary.BigEndian.PutUint64(e[1:], uint64(v)) 579 | 580 | t.Run("encode via Marshal", func(t *testing.T) { 581 | t.Parallel() 582 | b, err := msgpack.Marshal(v) 583 | if !assert.NoError(t, err, "Marshal should succeed") { 584 | return 585 | } 586 | 587 | if !assert.Equal(t, e, b, "Output should match") { 588 | return 589 | } 590 | }) 591 | 592 | t.Run("encode via EncodeInt64", func(t *testing.T) { 593 | t.Parallel() 594 | var buf bytes.Buffer 595 | if !assert.NoError(t, msgpack.NewEncoder(&buf).EncodeInt64(v), "EncodeInt64 should succeed") { 596 | return 597 | } 598 | 599 | if !assert.Equal(t, e, buf.Bytes(), "Output should match") { 600 | return 601 | } 602 | }) 603 | 604 | t.Run("encode via Encoder", func(t *testing.T) { 605 | t.Parallel() 606 | var buf bytes.Buffer 607 | if !assert.NoError(t, msgpack.NewEncoder(&buf).Encode(v), "Encode should succeed") { 608 | return 609 | } 610 | 611 | if !assert.Equal(t, e, buf.Bytes(), "Output should match") { 612 | return 613 | } 614 | }) 615 | } 616 | 617 | func makeString(l int) string { 618 | var buf bytes.Buffer 619 | var x int 620 | for i := 0; i < l; i++ { 621 | if x >= 10 { 622 | x = 0 623 | } 624 | buf.WriteByte(byte(x + 48)) 625 | x++ 626 | } 627 | return buf.String() 628 | } 629 | 630 | func TestEncodeStr8(t *testing.T) { 631 | t.Parallel() 632 | var v = makeString(math.MaxUint8) 633 | var e = make([]byte, math.MaxUint8+2) 634 | e[0] = msgpack.Str8.Byte() 635 | e[1] = math.MaxUint8 636 | copy(e[2:], []byte(v)) 637 | 638 | t.Run("encode via Marshal", func(t *testing.T) { 639 | t.Parallel() 640 | b, err := msgpack.Marshal(v) 641 | if !assert.NoError(t, err, "Marshal should succeed") { 642 | return 643 | } 644 | 645 | if !assert.Equal(t, e, b, "Output should match") { 646 | return 647 | } 648 | }) 649 | 650 | t.Run("encode via EncodeString", func(t *testing.T) { 651 | t.Parallel() 652 | var buf bytes.Buffer 653 | if !assert.NoError(t, msgpack.NewEncoder(&buf).EncodeString(v), "EncodeString should succeed") { 654 | return 655 | } 656 | 657 | if !assert.Equal(t, e, buf.Bytes(), "Output should match") { 658 | return 659 | } 660 | }) 661 | 662 | t.Run("encode via Encoder", func(t *testing.T) { 663 | t.Parallel() 664 | var buf bytes.Buffer 665 | if !assert.NoError(t, msgpack.NewEncoder(&buf).Encode(v), "Encode should succeed") { 666 | return 667 | } 668 | 669 | if !assert.Equal(t, e, buf.Bytes(), "Output should match") { 670 | return 671 | } 672 | }) 673 | } 674 | 675 | func TestEncodeStr16(t *testing.T) { 676 | t.Parallel() 677 | var v = makeString(math.MaxUint16) 678 | var e = make([]byte, math.MaxUint16+3) 679 | e[0] = msgpack.Str16.Byte() 680 | binary.BigEndian.PutUint16(e[1:], math.MaxUint16) 681 | copy(e[3:], []byte(v)) 682 | 683 | t.Run("encode via Marshal", func(t *testing.T) { 684 | t.Parallel() 685 | b, err := msgpack.Marshal(v) 686 | if !assert.NoError(t, err, "Marshal should succeed") { 687 | return 688 | } 689 | 690 | if !assert.Equal(t, e, b, "Output should match") { 691 | return 692 | } 693 | }) 694 | 695 | t.Run("encode via EncodeString", func(t *testing.T) { 696 | t.Parallel() 697 | var buf bytes.Buffer 698 | if !assert.NoError(t, msgpack.NewEncoder(&buf).EncodeString(v), "EncodeString should succeed") { 699 | return 700 | } 701 | 702 | if !assert.Equal(t, e, buf.Bytes(), "Output should match") { 703 | return 704 | } 705 | }) 706 | 707 | t.Run("encode via Encoder", func(t *testing.T) { 708 | t.Parallel() 709 | var buf bytes.Buffer 710 | if !assert.NoError(t, msgpack.NewEncoder(&buf).Encode(v), "Encode should succeed") { 711 | return 712 | } 713 | 714 | if !assert.Equal(t, e, buf.Bytes(), "Output should match") { 715 | return 716 | } 717 | }) 718 | } 719 | 720 | func TestEncodeStr32(t *testing.T) { 721 | t.Parallel() 722 | var l = math.MaxUint16 + 1 723 | var v = makeString(l) 724 | var e = make([]byte, l+5) 725 | e[0] = msgpack.Str32.Byte() 726 | binary.BigEndian.PutUint32(e[1:], uint32(l)) 727 | copy(e[5:], []byte(v)) 728 | 729 | t.Run("encode via Marshal", func(t *testing.T) { 730 | t.Parallel() 731 | b, err := msgpack.Marshal(v) 732 | if !assert.NoError(t, err, "Marshal should succeed") { 733 | return 734 | } 735 | 736 | if !assert.Equal(t, e, b, "Output should match") { 737 | return 738 | } 739 | }) 740 | 741 | t.Run("encode via EncodeString", func(t *testing.T) { 742 | t.Parallel() 743 | var buf bytes.Buffer 744 | if !assert.NoError(t, msgpack.NewEncoder(&buf).EncodeString(v), "EncodeString should succeed") { 745 | return 746 | } 747 | 748 | if !assert.Equal(t, e, buf.Bytes(), "Output should match") { 749 | return 750 | } 751 | }) 752 | 753 | t.Run("encode via Encoder", func(t *testing.T) { 754 | t.Parallel() 755 | var buf bytes.Buffer 756 | if !assert.NoError(t, msgpack.NewEncoder(&buf).Encode(v), "Encode should succeed") { 757 | return 758 | } 759 | 760 | if !assert.Equal(t, e, buf.Bytes(), "Output should match") { 761 | return 762 | } 763 | }) 764 | } 765 | 766 | func TestEncodeFixStr(t *testing.T) { 767 | t.Parallel() 768 | 769 | for l := 1; l < 32; l++ { 770 | var v = makeString(l) 771 | var e = make([]byte, l+1) 772 | e[0] = msgpack.FixStr0.Byte() + byte(l) 773 | copy(e[1:], []byte(v)) 774 | 775 | t.Run(fmt.Sprintf("encode via Marshal (fixstr%d)", l), func(t *testing.T) { 776 | t.Parallel() 777 | b, err := msgpack.Marshal(v) 778 | if !assert.NoError(t, err, "Marshal should succeed") { 779 | return 780 | } 781 | 782 | if !assert.Equal(t, e, b, "Output should match") { 783 | return 784 | } 785 | }) 786 | 787 | t.Run(fmt.Sprintf("encode via EncodeString (fixstr%d)", l), func(t *testing.T) { 788 | t.Parallel() 789 | var buf bytes.Buffer 790 | if !assert.NoError(t, msgpack.NewEncoder(&buf).EncodeString(v), "EncodeString should succeed") { 791 | return 792 | } 793 | 794 | if !assert.Equal(t, e, buf.Bytes(), "Output should match") { 795 | return 796 | } 797 | }) 798 | 799 | t.Run(fmt.Sprintf("encode via Encoder (fixstr%d)", l), func(t *testing.T) { 800 | t.Parallel() 801 | var buf bytes.Buffer 802 | if !assert.NoError(t, msgpack.NewEncoder(&buf).Encode(v), "Encode should succeed") { 803 | return 804 | } 805 | 806 | if !assert.Equal(t, e, buf.Bytes(), "Output should match") { 807 | return 808 | } 809 | }) 810 | } 811 | } 812 | 813 | func TestEncodeBytes(t *testing.T) { 814 | t.Parallel() 815 | var v = []byte(makeString(math.MaxUint8)) 816 | var e = make([]byte, math.MaxUint8+2) 817 | e[0] = msgpack.Bin8.Byte() 818 | e[1] = math.MaxUint8 819 | copy(e[2:], v) 820 | 821 | t.Run("encode via Marshal", func(t *testing.T) { 822 | t.Parallel() 823 | b, err := msgpack.Marshal(v) 824 | if !assert.NoError(t, err, "Marshal should succeed") { 825 | return 826 | } 827 | 828 | if !assert.Equal(t, e, b, "Output should match") { 829 | return 830 | } 831 | }) 832 | 833 | t.Run("encode via EncodeString", func(t *testing.T) { 834 | t.Parallel() 835 | var buf bytes.Buffer 836 | if !assert.NoError(t, msgpack.NewEncoder(&buf).EncodeBytes(v), "EncodeBytes should succeed") { 837 | return 838 | } 839 | 840 | if !assert.Equal(t, e, buf.Bytes(), "Output should match") { 841 | return 842 | } 843 | }) 844 | 845 | t.Run("encode via Encoder", func(t *testing.T) { 846 | t.Parallel() 847 | var buf bytes.Buffer 848 | if !assert.NoError(t, msgpack.NewEncoder(&buf).Encode(v), "Encode should succeed") { 849 | return 850 | } 851 | 852 | if !assert.Equal(t, e, buf.Bytes(), "Output should match") { 853 | return 854 | } 855 | }) 856 | } 857 | 858 | type testStruct struct { 859 | Foo int 860 | Bar struct { 861 | BarContent string `msgpack:"bar.content"` 862 | } `msgpack:"bar"` 863 | Baz string `msgpack:",omitempty"` 864 | Quux string `msgpack:"-"` 865 | } 866 | 867 | func TestEncodeStruct(t *testing.T) { 868 | t.Parallel() 869 | 870 | var v = testStruct{ 871 | Foo: 100, 872 | Quux: "quux", 873 | } 874 | v.Bar.BarContent = "Hello, World!" 875 | 876 | mapb := msgpack.NewMapBuilder() 877 | mapb.Add("Foo", 100) 878 | mapb.Add("bar", v.Bar) 879 | e, err := mapb.Bytes() 880 | if !assert.NoError(t, err, "MapBuilder.Bytes() should succeed") { 881 | return 882 | } 883 | 884 | b, err := msgpack.Marshal(v) 885 | if !assert.NoError(t, err, `Marshal should succeed`) { 886 | return 887 | } 888 | 889 | if !assert.Equal(t, e, b, `Output should match`) { 890 | return 891 | } 892 | } 893 | 894 | func TestEncodeArray(t *testing.T) { 895 | t.Parallel() 896 | t.Run("encode []bool", func(t *testing.T) { 897 | t.Parallel() 898 | msgpack.Marshal([]bool{true, false}) 899 | }) 900 | t.Run("encode mixed types", func(t *testing.T) { 901 | t.Parallel() 902 | var buf bytes.Buffer 903 | arrayb := msgpack.NewArrayBuilder() 904 | arrayb.Add(int32(100)) 905 | arrayb.Add("foo") 906 | arrayb.Add(float32(0)) 907 | if !assert.NoError(t, arrayb.Encode(&buf), "Encode should succeed") { 908 | return 909 | } 910 | 911 | e := buf.Bytes() 912 | v := []interface{}{int32(100), "foo", float32(0)} 913 | b, err := msgpack.Marshal(v) 914 | if !assert.NoError(t, err, `Marshal should succeed`) { 915 | return 916 | } 917 | 918 | if !assert.Equal(t, e, b, `Output should match`) { 919 | return 920 | } 921 | }) 922 | } 923 | -------------------------------------------------------------------------------- /decoder.go: -------------------------------------------------------------------------------- 1 | package msgpack 2 | 3 | import ( 4 | "bufio" 5 | "io" 6 | "reflect" 7 | "time" 8 | 9 | bufferpool "github.com/lestrrat-go/bufferpool" 10 | "github.com/pkg/errors" 11 | ) 12 | 13 | // NewDecoder creates a Decoder instance 14 | func NewDecoder(r io.Reader) Decoder { 15 | d := &decoder{nl: &decoderNL{}} 16 | d.nl.SetSource(r) 17 | return d 18 | } 19 | 20 | // NewDecoderNoLock creates a new Decoder that DOES NOT protect 21 | // users against accidental race conditions caused by concurrent 22 | // method access. If you have complete control over the usage of 23 | // this object, then the object returned by this constructor will 24 | // shorten a whopping 30~50ns per method call. Use at your own peril 25 | func NewDecoderNoLock(r io.Reader) Decoder { 26 | d := &decoderNL{} 27 | d.SetSource(r) 28 | return d 29 | } 30 | 31 | func (d *decoder) SetSource(r io.Reader) { 32 | d.mu.Lock() 33 | defer d.mu.Unlock() 34 | d.nl.SetSource(r) 35 | } 36 | 37 | func (dnl *decoderNL) SetSource(r io.Reader) { 38 | dnl.raw = bufio.NewReader(r) 39 | dnl.src = NewReader(dnl.raw) 40 | } 41 | 42 | func (dnl *decoderNL) Reader() Reader { 43 | return dnl.src 44 | } 45 | 46 | func (dnl *decoderNL) ReadCode() (Code, error) { 47 | b, err := dnl.raw.ReadByte() 48 | if err != nil { 49 | return Code(0), errors.Wrap(err, `msgpack: failed to read code`) 50 | } 51 | 52 | return Code(b), nil 53 | } 54 | 55 | func (dnl *decoderNL) PeekCode() (Code, error) { 56 | code, err := dnl.ReadCode() 57 | if err != nil { 58 | return code, errors.Wrap(err, `msgpack: failed to peek code`) 59 | } 60 | 61 | if err := dnl.raw.UnreadByte(); err != nil { 62 | return Code(0), errors.Wrap(err, `msgpack: failed to unread code`) 63 | } 64 | return code, nil 65 | } 66 | 67 | func (dnl *decoderNL) isNil() bool { 68 | code, err := dnl.PeekCode() 69 | if err != nil { 70 | return false 71 | } 72 | return code == Nil 73 | } 74 | 75 | func (dnl *decoderNL) DecodeNil(v *interface{}) error { 76 | code, err := dnl.ReadCode() 77 | if err != nil { 78 | return errors.Wrap(err, `msgpack: failed to read code`) 79 | } 80 | if code != Nil { 81 | return errors.Errorf(`msgpack: expected Nil, got %s`, code) 82 | } 83 | if v != nil { 84 | *v = nil 85 | } 86 | return nil 87 | } 88 | 89 | func (dnl *decoderNL) DecodeBool(b *bool) error { 90 | code, err := dnl.ReadCode() 91 | if err != nil { 92 | return errors.Wrap(err, `msgpack: failed to read code`) 93 | } 94 | 95 | switch code { 96 | case True: 97 | *b = true 98 | return nil 99 | case False: 100 | *b = false 101 | return nil 102 | default: 103 | return errors.Errorf(`msgpack: expected True/False, got %s`, code) 104 | } 105 | } 106 | 107 | func (dnl *decoderNL) DecodeBytes(v *[]byte) error { 108 | code, err := dnl.ReadCode() 109 | if err != nil { 110 | return errors.Wrap(err, `msgpack: failed to read code`) 111 | } 112 | 113 | var l int64 114 | switch { 115 | case code == Bin8: 116 | v, err := dnl.src.ReadUint8() 117 | if err != nil { 118 | return errors.Wrap(err, `msgpack: failed to read length for string/byte slice`) 119 | } 120 | l = int64(v) 121 | case code == Bin16: 122 | v, err := dnl.src.ReadUint16() 123 | if err != nil { 124 | return errors.Wrap(err, `msgpack: failed to read length for string/byte slice`) 125 | } 126 | l = int64(v) 127 | case code == Bin32: 128 | v, err := dnl.src.ReadUint32() 129 | if err != nil { 130 | return errors.Wrap(err, `msgpack: failed to read length for string/byte slice`) 131 | } 132 | l = int64(v) 133 | default: 134 | return errors.Errorf(`msgpack: invalid code: expected Bin8/Bin16/Bin32, got %s`, code) 135 | } 136 | 137 | // Sanity check 138 | if l < 0 { 139 | return errors.Errorf(`msgpack: invalid byte slice length %d`, l) 140 | } 141 | 142 | b := make([]byte, l) 143 | for x := b; len(x) > 0; { 144 | n, err := dnl.raw.Read(x) 145 | if err != nil { 146 | return errors.Wrap(err, `msgpack: failed to read byte slice`) 147 | } 148 | x = x[n:] 149 | } 150 | 151 | *v = b 152 | return nil 153 | } 154 | 155 | func (dnl *decoderNL) DecodeString(s *string) error { 156 | code, err := dnl.ReadCode() 157 | if err != nil { 158 | return errors.Wrap(err, `msgpack: failed to read code`) 159 | } 160 | 161 | var l int64 162 | switch { 163 | case code >= FixStr0 && code <= FixStr31: 164 | l = int64(code.Byte() - FixStr0.Byte()) 165 | case code == Str8: 166 | v, err := dnl.src.ReadUint8() 167 | if err != nil { 168 | return errors.Wrap(err, `msgpack: failed to read length for string/byte slice`) 169 | } 170 | l = int64(v) 171 | case code == Str16: 172 | v, err := dnl.src.ReadUint16() 173 | if err != nil { 174 | return errors.Wrap(err, `msgpack: failed to read length for string/byte slice`) 175 | } 176 | l = int64(v) 177 | case code == Str32: 178 | v, err := dnl.src.ReadUint32() 179 | if err != nil { 180 | return errors.Wrap(err, `msgpack: failed to read length for string/byte slice`) 181 | } 182 | l = int64(v) 183 | default: 184 | return errors.Errorf(`msgpack: invalid code: expected FixStr/Str8/Str16/Str32, got %s`, code) 185 | } 186 | 187 | // Sanity check 188 | if l < 0 { 189 | return errors.Errorf(`msgpack: invalid string length %d`, l) 190 | } 191 | 192 | // Read the contents of the string. 193 | // Now, here's the tricky part: conversion from byte slice to string is 194 | // just going to create a copy of b as an immutable string, and so this 195 | // byte slice is just thrown away. It would be nice if we could reuse 196 | // this memory later... 197 | buf := bufferpool.Get() 198 | defer bufferpool.Release(buf) 199 | 200 | // Make sure we can write l bytes 201 | buf.Grow(int(l)) 202 | b := buf.Bytes() 203 | for x := b[:l]; len(x) > 0; { 204 | n, err := dnl.raw.Read(x) 205 | if err != nil { 206 | return errors.Wrap(err, `msgpack: failed to read string`) 207 | } 208 | x = x[n:] 209 | } 210 | 211 | *s = string(b[:l]) 212 | return nil 213 | } 214 | 215 | func (dnl *decoderNL) DecodeArrayLength(l *int) error { 216 | code, err := dnl.ReadCode() 217 | if err != nil { 218 | return errors.Wrap(err, `msgpack: failed to read code`) 219 | } 220 | 221 | if code >= FixArray0 && code <= FixArray15 { 222 | *l = int(code.Byte() - FixArray0.Byte()) 223 | return nil 224 | } 225 | 226 | switch code { 227 | case Array16: 228 | s, err := dnl.src.ReadUint16() 229 | if err != nil { 230 | return errors.Wrap(err, `msgpack: failed to read array size for Array16`) 231 | } 232 | *l = int(s) 233 | case Array32: 234 | s, err := dnl.src.ReadUint32() 235 | if err != nil { 236 | return errors.Wrap(err, `msgpack: failed to read array size for Array32`) 237 | } 238 | *l = int(s) 239 | default: 240 | return errors.Errorf(`msgpack: unsupported array type %s`, code) 241 | } 242 | 243 | return nil 244 | } 245 | 246 | func (dnl *decoderNL) DecodeArray(v interface{}) error { 247 | var size int 248 | if err := dnl.DecodeArrayLength(&size); err != nil { 249 | return errors.Wrap(err, `msgpack: failed to decode array length`) 250 | } 251 | 252 | rv := reflect.ValueOf(v) 253 | if rv.Kind() != reflect.Ptr { 254 | return errors.Errorf(`msgpack: DecodeArray expected pointer to slice, got %s`, rv.Type()) 255 | } 256 | rv = rv.Elem() 257 | if rv.Kind() != reflect.Slice { 258 | return errors.Errorf(`msgpack: DecodeArray expected slice, got %s`, rv.Type()) 259 | } 260 | 261 | slice := reflect.MakeSlice(rv.Type(), size, size) 262 | for i := 0; i < size; i++ { 263 | e := slice.Index(i) 264 | if e.Kind() == reflect.Ptr { 265 | if e.IsNil() { 266 | e.Set(reflect.New(e.Type().Elem())) 267 | } 268 | } else { 269 | e = e.Addr() 270 | } 271 | if err := dnl.Decode(e.Interface()); err != nil { 272 | return errors.Wrapf(err, `msgpack: failed to decode array element %d`, i) 273 | } 274 | } 275 | 276 | rv.Set(slice) 277 | return nil 278 | } 279 | 280 | func (dnl *decoderNL) DecodeMapLength(l *int) error { 281 | code, err := dnl.ReadCode() 282 | if err != nil { 283 | return errors.Wrap(err, `msgpack: failed to read code`) 284 | } 285 | 286 | if code == Nil { 287 | *l = -1 288 | return nil 289 | } 290 | 291 | if code >= FixMap0 && code <= FixMap15 { 292 | *l = int(code.Byte() - FixMap0.Byte()) 293 | return nil 294 | } 295 | 296 | switch code { 297 | case Map16: 298 | s, err := dnl.src.ReadUint16() 299 | if err != nil { 300 | return errors.Wrap(err, `msgpack: failed to read array size for Map16`) 301 | } 302 | *l = int(s) 303 | case Map32: 304 | s, err := dnl.src.ReadUint32() 305 | if err != nil { 306 | return errors.Wrap(err, `msgpack: failed to read array size for Map32`) 307 | } 308 | *l = int(s) 309 | default: 310 | return errors.Errorf(`msgpack: unsupported map type %s`, code) 311 | } 312 | 313 | return nil 314 | } 315 | 316 | func (dnl *decoderNL) DecodeMap(v *map[string]interface{}) error { 317 | var size int 318 | if err := dnl.DecodeMapLength(&size); err != nil { 319 | return errors.Wrap(err, `msgpack: failed to decode map length`) 320 | } 321 | 322 | if size == -1 { 323 | *v = nil 324 | return nil 325 | } 326 | 327 | m := make(map[string]interface{}) 328 | for i := 0; i < size; i++ { 329 | var s string 330 | if err := dnl.DecodeString(&s); err != nil { 331 | return errors.Wrap(err, `msgpack: failed to decode map key`) 332 | } 333 | 334 | var v interface{} 335 | if err := dnl.Decode(&v); err != nil { 336 | return errors.Wrapf(err, `msgpack: failed to decode map element for key %s`, s) 337 | } 338 | m[s] = v 339 | } 340 | *v = m 341 | return nil 342 | } 343 | 344 | func (dnl *decoderNL) DecodeTime(v *time.Time) error { 345 | var size int 346 | if err := dnl.DecodeArrayLength(&size); err != nil { 347 | return errors.Wrap(err, `msgpack: failed to decode array length for time.Time`) 348 | } 349 | if size != 2 { 350 | return errors.Errorf(`msgpack: expected array of size 2 (got %d)`, size) 351 | } 352 | 353 | var seconds int64 354 | if err := dnl.DecodeInt64(&seconds); err != nil { 355 | return errors.Wrap(err, `msgpack: failed to decode seconds part for time.Time`) 356 | } 357 | var nanosecs int 358 | if err := dnl.DecodeInt(&nanosecs); err != nil { 359 | return errors.Wrap(err, `msgpack: failed to decode nanoseconds part for time.Time`) 360 | } 361 | 362 | *v = time.Unix(seconds, int64(nanosecs)) 363 | return nil 364 | } 365 | 366 | func (dnl *decoderNL) DecodeStruct(v interface{}) error { 367 | if v, ok := v.(DecodeMsgpacker); ok { 368 | return dnl.DecodeExt(v) 369 | } 370 | 371 | if v, ok := v.(*time.Time); ok { 372 | return dnl.DecodeTime(v) 373 | } 374 | 375 | var size int 376 | if err := dnl.DecodeMapLength(&size); err != nil { 377 | return errors.Wrap(err, `msgpack: failed to decode map length`) 378 | } 379 | 380 | var rv = reflect.ValueOf(v) 381 | // You better be a pointer to a struct, damnit 382 | if rv.Kind() != reflect.Ptr || rv.Elem().Kind() != reflect.Struct { 383 | return errors.New(`msgpack: expected pointer to struct`) 384 | } 385 | 386 | if size == -1 { 387 | if rv.CanSet() { 388 | rv.Set(reflect.Value{}) 389 | } 390 | return nil 391 | } 392 | 393 | var rt = rv.Elem().Type() 394 | // Find the fields 395 | name2field := map[string]reflect.Value{} 396 | for i := 0; i < rt.NumField(); i++ { 397 | field := rt.Field(i) 398 | if field.PkgPath != "" { 399 | continue 400 | } 401 | 402 | name, _ := parseMsgpackTag(field) 403 | if name == "-" { 404 | continue 405 | } 406 | 407 | name2field[name] = rv.Elem().Field(i) 408 | } 409 | 410 | var key string 411 | for i := 0; i < size; i++ { 412 | if err := dnl.Decode(&key); err != nil { 413 | return errors.Wrapf(err, `msgpack: failed to decode struct key at index %d`, i) 414 | } 415 | 416 | f, ok := name2field[key] 417 | if !ok { 418 | continue 419 | } 420 | if dnl.isNil() { 421 | if err := dnl.DecodeNil(nil); err != nil { 422 | return errors.Wrapf(err, `msgpack: failed to decode nil field %s`, key) 423 | } 424 | continue 425 | } 426 | 427 | if f.Kind() == reflect.Slice { 428 | r := reflect.New(f.Type()).Elem() 429 | if err := dnl.Decode(r.Addr().Interface()); err != nil { 430 | return errors.Wrapf(err, `msgpack: failed to decode slice value for key %s`, key) 431 | } 432 | f.Set(r) 433 | } else if f.Kind() == reflect.Struct { 434 | if err := dnl.Decode(f.Addr().Interface()); err != nil { 435 | return errors.Wrapf(err, `msgpack: failed to decode struct value for key %s (struct)`, key) 436 | } 437 | } else if f.Kind() == reflect.Ptr && f.Type().Elem().Kind() == reflect.Struct { 438 | r := reflect.New(f.Type().Elem()) 439 | if err := dnl.Decode(r.Interface()); err != nil { 440 | return errors.Wrapf(err, `msgpack: failed to decode struct value for key %s (pointer to struct)`, key) 441 | } 442 | f.Set(r) 443 | } else { 444 | var fv reflect.Value 445 | if f.Kind() == reflect.Ptr { 446 | fv = reflect.New(f.Type().Elem()) 447 | } else { 448 | fv = reflect.New(f.Type()) 449 | } 450 | if err := dnl.Decode(fv.Interface()); err != nil { 451 | return errors.Wrapf(err, `msgpack: failed to decode struct value for key %s (not struct/pointer to struct)`, key) 452 | } 453 | 454 | if err := assignIfCompatible(f, fv.Elem()); err != nil { 455 | return errors.Wrapf(err, `msgpack: failed to assign struct value for key %s`, key) 456 | } 457 | } 458 | } 459 | 460 | return nil 461 | } 462 | 463 | func assignIfCompatible(dst, src reflect.Value) (err error) { 464 | // src will always be from result of a Decode. therefore 465 | // we will have no pointers. But dst can be either a 466 | // a pointer or the actual type 467 | var dstlist = []reflect.Value{dst} 468 | if dst.Kind() == reflect.Ptr { 469 | if dst.Elem().IsValid() { 470 | dstlist = append(dstlist, dst.Elem()) 471 | } else { 472 | v := reflect.New(dst.Type().Elem()) 473 | dstlist = append(dstlist, v.Elem()) 474 | defer func() { 475 | if err == nil { 476 | dst.Set(v) 477 | } 478 | }() 479 | } 480 | } 481 | 482 | for _, dst := range dstlist { 483 | if !dst.IsValid() { 484 | continue 485 | } 486 | 487 | if dst.Type() == emptyInterfaceType { 488 | dst.Set(reflect.ValueOf(src.Interface())) 489 | return nil 490 | } 491 | 492 | // Unmarshalers need to assign in case of pointers, too 493 | 494 | if src.Type().AssignableTo(dst.Type()) { 495 | dst.Set(src) 496 | return nil 497 | } 498 | 499 | if src.Type().ConvertibleTo(dst.Type()) { 500 | dst.Set(src.Convert(dst.Type())) 501 | return nil 502 | } 503 | 504 | // We may have a container... 505 | if dst.Kind() == reflect.Slice && src.Kind() == reflect.Slice { 506 | slice := reflect.MakeSlice(dst.Type(), src.Len(), src.Len()) 507 | if dst.Type().Elem() == emptyInterfaceType { 508 | // if this is the case, we can assign everything from 509 | // src to dst 510 | for i := 0; i < src.Len(); i++ { 511 | dst.Index(i).Set(src.Index(i)) 512 | } 513 | return nil 514 | } 515 | 516 | if src.Type().Elem() == emptyInterfaceType { 517 | sliceElemType := dst.Type().Elem() // []string -> string 518 | isSliceElemPtr := dst.Type().Elem().Kind() == reflect.Ptr 519 | 520 | // See if we can install src's contents into dst 521 | SLICE: 522 | for i := 0; i < src.Len(); i++ { 523 | e := src.Index(i) 524 | 525 | var assignErr error 526 | switch { 527 | case sliceElemType == e.Elem().Type(): 528 | if assignErr = assignIfCompatible(slice.Index(i), e.Elem()); assignErr == nil { 529 | continue SLICE 530 | } 531 | case isSliceElemPtr: 532 | if sliceElemType.Elem() == e.Elem().Type() { 533 | if assignErr = assignIfCompatible(slice.Index(i), e.Elem().Addr()); assignErr == nil { 534 | continue SLICE 535 | } 536 | } else if e.Elem().Type().ConvertibleTo(sliceElemType.Elem()) { 537 | v := reflect.New(sliceElemType.Elem()) 538 | v.Elem().Set(e.Elem().Convert(sliceElemType.Elem())) 539 | if assignErr = assignIfCompatible(slice.Index(i), v); assignErr == nil { 540 | continue SLICE 541 | } 542 | } 543 | } 544 | 545 | return errors.Wrapf(assignErr, `msgpack: cannot assign slice element on index %d (slice type = %s, element type = %s)`, i, dst.Type(), e.Elem().Type()) 546 | } 547 | dst.Set(slice) 548 | return nil 549 | } 550 | } 551 | } 552 | return errors.Errorf(`invalid type for assignment: dst = %s, src = %s`, dst.Type(), src.Type()) 553 | } 554 | 555 | var emptyInterfaceType = reflect.TypeOf((*interface{})(nil)).Elem() 556 | 557 | func (dnl *decoderNL) Decode(v interface{}) error { 558 | rv := reflect.ValueOf(v) 559 | 560 | // The result of decoding must be assigned to v, and v 561 | // should be a pointer 562 | if rv.Kind() == reflect.Interface { 563 | // if it's an interface, get the underlying type 564 | rv = rv.Elem() 565 | } 566 | 567 | if rv.Kind() != reflect.Ptr || rv.IsNil() { 568 | // report error 569 | var typ reflect.Type 570 | if rv.IsValid() { 571 | typ = rv.Type() 572 | } 573 | return &InvalidDecodeError{ 574 | Type: typ, 575 | } 576 | } 577 | 578 | // First, try guessing what to do by checking the type of the 579 | // incoming payload. These are the easy choices 580 | switch v := v.(type) { 581 | case *interface{}: 582 | goto FromCode 583 | case *int: 584 | return dnl.DecodeInt(v) 585 | case *int8: 586 | return dnl.DecodeInt8(v) 587 | case *int16: 588 | return dnl.DecodeInt16(v) 589 | case *int32: 590 | return dnl.DecodeInt32(v) 591 | case *int64: 592 | return dnl.DecodeInt64(v) 593 | case *uint: 594 | return dnl.DecodeUint(v) 595 | case *uint8: 596 | return dnl.DecodeUint8(v) 597 | case *uint16: 598 | return dnl.DecodeUint16(v) 599 | case *uint32: 600 | return dnl.DecodeUint32(v) 601 | case *uint64: 602 | return dnl.DecodeUint64(v) 603 | case *float32: 604 | return dnl.DecodeFloat32(v) 605 | case *float64: 606 | return dnl.DecodeFloat64(v) 607 | case *[]byte: 608 | return dnl.DecodeBytes(v) 609 | case *string: 610 | return dnl.DecodeString(v) 611 | case *map[string]interface{}: 612 | return dnl.DecodeMap(v) 613 | case DecodeMsgpacker: 614 | // If we know this object does its own decoding, we bypass everything 615 | // and just let it handle itself 616 | return v.DecodeMsgpack(dnl) 617 | } 618 | 619 | // Next up: try using reflect to find out the general family of 620 | // the payload. 621 | switch rv.Elem().Kind() { 622 | case reflect.Struct: 623 | return dnl.DecodeStruct(v) 624 | case reflect.Slice: 625 | list := reflect.New(rv.Elem().Type()) 626 | if err := dnl.DecodeArray(list.Interface()); err != nil { 627 | return errors.Wrap(err, `msgpack: failed to decode array`) 628 | } 629 | if err := assignIfCompatible(reflect.ValueOf(v).Elem(), list.Elem()); err != nil { 630 | return errors.Wrap(err, `msgpack: error while assigning slice elements`) 631 | } 632 | return nil 633 | } 634 | 635 | FromCode: 636 | decoded, err := dnl.decodeInterface(v) 637 | if err != nil { 638 | return errors.Wrap(err, `msgpack: failed to decode interface value`) 639 | } 640 | 641 | // if decoded == nil, then we have a special case, where we need 642 | // to assign a nil to v, but the type of the nil must match v 643 | // (if you get what I mean) 644 | if decoded == nil { 645 | // Note: I wish I could just return without doing anything, but 646 | // because the encoded value is explicitly nil, it's only right 647 | // to properly assign a nil to whatever value that was passed to 648 | // this method. 649 | rv.Elem().Set(reflect.Zero(rv.Elem().Type())) 650 | return nil 651 | } 652 | 653 | dv := reflect.ValueOf(decoded) 654 | 655 | // Since we know rv to be a pointer, we must set the new value 656 | // to the destination of the pointer. 657 | dst := rv.Elem() 658 | 659 | // If it's assignable, assign, and we're done. 660 | if err := assignIfCompatible(dst, dv); err == nil { 661 | return nil 662 | } 663 | 664 | // This could only happen if we have a decoder that creates 665 | // the value dynamically, such as in the case of struct 666 | // decoder or extension decoder. 667 | if reflect.PtrTo(dst.Type()) == dv.Type() { 668 | dst.Set(dv.Elem()) 669 | return nil 670 | } 671 | 672 | return errors.Errorf(`msgpack: cannot assign %s to %s`, dv.Type(), dst.Type()) 673 | } 674 | 675 | // Note: v is only used as a hint. do not assign to it inside this method 676 | func (dnl *decoderNL) decodeInterface(v interface{}) (interface{}, error) { 677 | code, err := dnl.PeekCode() 678 | if err != nil { 679 | return nil, errors.Wrap(err, `msgpack: failed to peek code`) 680 | } 681 | 682 | switch { 683 | case IsExtFamily(code): 684 | var size int 685 | if err := dnl.DecodeExtLength(&size); err != nil { 686 | return nil, errors.Wrap(err, `msgpack: failed to read extension sizes`) 687 | } 688 | 689 | var typ reflect.Type 690 | if err := dnl.DecodeExtType(&typ); err != nil { 691 | return nil, errors.Wrap(err, `msgpack: faied to read extension type`) 692 | } 693 | 694 | rv := reflect.New(typ).Interface().(DecodeMsgpacker) 695 | if err := rv.DecodeMsgpack(dnl); err != nil { 696 | return nil, errors.Wrap(err, `msgpack: failed to decode extension`) 697 | } 698 | return rv, nil 699 | case IsFixNumFamily(code): 700 | return int8(code), nil 701 | case code == Nil: 702 | // Optimization: doesn't require any more handling than to 703 | // throw away the code 704 | if _, err := dnl.raw.ReadByte(); err != nil { 705 | return nil, errors.Wrap(err, `msgpack: failed to ready byte`) 706 | } 707 | return nil, nil 708 | case code == True: 709 | // Optimization: doesn't require any more handling than to 710 | // throw away the code 711 | if _, err := dnl.raw.ReadByte(); err != nil { 712 | return false, errors.Wrap(err, `msgpack: failed to read byte`) 713 | } 714 | return true, nil 715 | case code == False: 716 | // Optimization: doesn't require any more handling than to 717 | // throw away the code 718 | if _, err := dnl.raw.ReadByte(); err != nil { 719 | return false, errors.Wrap(err, `msgpack: failed to read byte`) 720 | } 721 | return false, nil 722 | case code == Int8: 723 | var x int8 724 | if err := dnl.DecodeInt8(&x); err != nil { 725 | return nil, errors.Wrap(err, `msgpack: failed to decode Int8`) 726 | } 727 | return x, nil 728 | case code == Int16: 729 | var x int16 730 | if err := dnl.DecodeInt16(&x); err != nil { 731 | return nil, errors.Wrap(err, `msgpack: failed to decode Int16`) 732 | } 733 | return x, nil 734 | case code == Int32: 735 | var x int32 736 | if err := dnl.DecodeInt32(&x); err != nil { 737 | return nil, errors.Wrap(err, `msgpack: failed to decode Int32`) 738 | } 739 | return x, nil 740 | case code == Int64: 741 | var x int64 742 | if err := dnl.DecodeInt64(&x); err != nil { 743 | return nil, errors.Wrap(err, `msgpack: failed to decode Int64`) 744 | } 745 | return x, nil 746 | case code == Uint8: 747 | var x uint8 748 | if err := dnl.DecodeUint8(&x); err != nil { 749 | return nil, errors.Wrap(err, `msgpack: failed to decode Uint8`) 750 | } 751 | return x, nil 752 | case code == Uint16: 753 | var x uint16 754 | if err := dnl.DecodeUint16(&x); err != nil { 755 | return nil, errors.Wrap(err, `msgpack: failed to decode Uint16`) 756 | } 757 | return x, nil 758 | case code == Uint32: 759 | var x uint32 760 | if err := dnl.DecodeUint32(&x); err != nil { 761 | return nil, errors.Wrap(err, `msgpack: failed to decode Uint32`) 762 | } 763 | return x, nil 764 | case code == Uint64: 765 | var x uint64 766 | if err := dnl.DecodeUint64(&x); err != nil { 767 | return nil, errors.Wrap(err, `msgpack: failed to decode Uint64`) 768 | } 769 | return x, nil 770 | case code == Float: 771 | var x float32 772 | if err := dnl.DecodeFloat32(&x); err != nil { 773 | return nil, errors.Wrap(err, `msgpack: failed to decode Float`) 774 | } 775 | return x, nil 776 | case code == Double: 777 | var x float64 778 | if err := dnl.DecodeFloat64(&x); err != nil { 779 | return nil, errors.Wrap(err, `msgpack: failed to decode Double`) 780 | } 781 | return x, nil 782 | case IsBinFamily(code): 783 | var b []byte 784 | if err := dnl.DecodeBytes(&b); err != nil { 785 | return nil, errors.Wrapf(err, `msgpack: failed to decode %s`, code) 786 | } 787 | return b, nil 788 | case IsStrFamily(code): 789 | var s string 790 | if err := dnl.DecodeString(&s); err != nil { 791 | return nil, errors.Wrapf(err, `msgpack: failed to decode %s`, code) 792 | } 793 | return s, nil 794 | case IsArrayFamily(code): 795 | var l []interface{} 796 | if err := dnl.DecodeArray(&l); err != nil { 797 | return nil, errors.Wrapf(err, `msgpack: failed to decode %s`, code) 798 | } 799 | return l, nil 800 | case IsMapFamily(code): 801 | // Special case: If the object is a Map type, and the target object 802 | // is a Struct, we do the struct decoding bit. 803 | // could be &struct, interface{}(&struct{}), or interface{}(&interface{}(struct{})) 804 | rv := reflect.ValueOf(v) 805 | if rv.Type().Kind() == reflect.Interface { 806 | rv = rv.Elem() 807 | } 808 | 809 | if rv.Kind() == reflect.Ptr { 810 | rv = rv.Elem() 811 | if rv.Kind() == reflect.Interface { 812 | rv = rv.Elem() 813 | } 814 | if rv.Kind() == reflect.Struct { 815 | v := reflect.New(rv.Type()).Interface() 816 | if err := dnl.DecodeStruct(v); err != nil { 817 | return nil, errors.Wrap(err, `msgpack: failed to decode struct`) 818 | } 819 | return reflect.ValueOf(v).Elem().Interface(), nil 820 | } 821 | } 822 | 823 | var v = make(map[string]interface{}) 824 | if err := dnl.DecodeMap(&v); err != nil { 825 | return nil, errors.Wrap(err, `msgpack: failed to decode map`) 826 | } 827 | return v, nil 828 | default: 829 | return nil, errors.Errorf(`msgpack: invalid code %s`, code) 830 | } 831 | } 832 | 833 | func (dnl *decoderNL) DecodeExtLength(l *int) error { 834 | code, err := dnl.ReadCode() 835 | if err != nil { 836 | return errors.Wrap(err, `msgpack: failed to read code`) 837 | } 838 | 839 | var payloadSize int 840 | switch code { 841 | case FixExt1: 842 | payloadSize = 1 843 | case FixExt2: 844 | payloadSize = 2 845 | case FixExt4: 846 | payloadSize = 1 847 | case FixExt8: 848 | payloadSize = 8 849 | case FixExt16: 850 | payloadSize = 16 851 | case Ext8: 852 | s, err := dnl.src.ReadUint8() 853 | if err != nil { 854 | return errors.Wrap(err, `msgpack: failed to read size for ext8 value`) 855 | } 856 | payloadSize = int(s) 857 | case Ext16: 858 | s, err := dnl.src.ReadUint16() 859 | if err != nil { 860 | return errors.Wrap(err, `msgpack: failed to read size for ext16 value`) 861 | } 862 | payloadSize = int(s) 863 | case Ext32: 864 | s, err := dnl.src.ReadUint32() 865 | if err != nil { 866 | return errors.Wrap(err, `msgpack: failed to read size for ext32 value`) 867 | } 868 | payloadSize = int(s) 869 | default: 870 | return errors.Errorf(`msgpack: invalid ext code %s`, code) 871 | } 872 | *l = payloadSize 873 | return nil 874 | } 875 | 876 | func (dnl *decoderNL) DecodeExt(v DecodeMsgpacker) error { 877 | var size int 878 | if err := dnl.DecodeExtLength(&size); err != nil { 879 | return errors.Wrap(err, `msgpack: failed to read extension sizes`) 880 | } 881 | 882 | var typ reflect.Type 883 | if err := dnl.DecodeExtType(&typ); err != nil { 884 | return errors.Wrap(err, `msgpack: faied to read extension type`) 885 | } 886 | 887 | if rt := reflect.TypeOf(v); rt != reflect.PtrTo(typ) { 888 | return errors.Errorf(`msgpack: extension should be %s, got %s`, typ, rt) 889 | } 890 | 891 | if err := v.DecodeMsgpack(dnl); err != nil { 892 | return errors.Wrap(err, `msgpack: failed to call DecodeMsgpack`) 893 | } 894 | return nil 895 | } 896 | 897 | func (dnl *decoderNL) DecodeExtType(v *reflect.Type) error { 898 | t, err := dnl.src.ReadUint8() 899 | if err != nil { 900 | return errors.Wrap(err, `msgpack: failed to read type for extension`) 901 | } 902 | 903 | muExtDecode.Lock() 904 | typ, ok := extDecodeRegistry[int(t)] 905 | muExtDecode.Unlock() 906 | 907 | if !ok { 908 | return errors.Errorf(`msgpack: type %d is not registered as an extension`, int(t)) 909 | } 910 | 911 | *v = typ 912 | return nil 913 | } 914 | --------------------------------------------------------------------------------