Bump github.com/hashicorp/terraform-plugin-sdk/v2 from 2.26.1 to 2.27.0

Bumps [github.com/hashicorp/terraform-plugin-sdk/v2](https://github.com/hashicorp/terraform-plugin-sdk) from 2.26.1 to 2.27.0.
- [Release notes](https://github.com/hashicorp/terraform-plugin-sdk/releases)
- [Changelog](https://github.com/hashicorp/terraform-plugin-sdk/blob/main/CHANGELOG.md)
- [Commits](https://github.com/hashicorp/terraform-plugin-sdk/compare/v2.26.1...v2.27.0)

---
updated-dependencies:
- dependency-name: github.com/hashicorp/terraform-plugin-sdk/v2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
This commit is contained in:
dependabot[bot]
2023-07-03 20:21:30 +00:00
committed by GitHub
parent b2403e2569
commit 910ccdb092
722 changed files with 31260 additions and 8125 deletions

View File

@ -1,12 +0,0 @@
run:
concurrency: 8
deadline: 5m
tests: false
linters:
enable-all: true
disable:
- gochecknoglobals
- gocognit
- godox
- wsl
- funlen

View File

@ -1,72 +0,0 @@
# MessagePack encoding for Golang
[![Build Status](https://travis-ci.org/vmihailenco/msgpack.svg?branch=v2)](https://travis-ci.org/vmihailenco/msgpack)
[![GoDoc](https://godoc.org/github.com/vmihailenco/msgpack?status.svg)](https://godoc.org/github.com/vmihailenco/msgpack)
Supports:
- Primitives, arrays, maps, structs, time.Time and interface{}.
- Appengine *datastore.Key and datastore.Cursor.
- [CustomEncoder](https://godoc.org/github.com/vmihailenco/msgpack#example-CustomEncoder)/CustomDecoder interfaces for custom encoding.
- [Extensions](https://godoc.org/github.com/vmihailenco/msgpack#example-RegisterExt) to encode type information.
- Renaming fields via `msgpack:"my_field_name"` and alias via `msgpack:"alias:another_name"`.
- Omitting individual empty fields via `msgpack:",omitempty"` tag or all [empty fields in a struct](https://godoc.org/github.com/vmihailenco/msgpack#example-Marshal--OmitEmpty).
- [Map keys sorting](https://godoc.org/github.com/vmihailenco/msgpack#Encoder.SortMapKeys).
- Encoding/decoding all [structs as arrays](https://godoc.org/github.com/vmihailenco/msgpack#Encoder.UseArrayForStructs) or [individual structs](https://godoc.org/github.com/vmihailenco/msgpack#example-Marshal--AsArray).
- [Encoder.UseJSONTag](https://godoc.org/github.com/vmihailenco/msgpack#Encoder.UseJSONTag) with [Decoder.UseJSONTag](https://godoc.org/github.com/vmihailenco/msgpack#Decoder.UseJSONTag) can turn msgpack into drop-in replacement for JSON.
- Simple but very fast and efficient [queries](https://godoc.org/github.com/vmihailenco/msgpack#example-Decoder-Query).
API docs: https://godoc.org/github.com/vmihailenco/msgpack.
Examples: https://godoc.org/github.com/vmihailenco/msgpack#pkg-examples.
## Installation
This project uses [Go Modules](https://github.com/golang/go/wiki/Modules) and semantic import versioning since v4:
``` shell
go mod init github.com/my/repo
go get github.com/vmihailenco/msgpack/v4
```
## Quickstart
``` go
import "github.com/vmihailenco/msgpack/v4"
func ExampleMarshal() {
type Item struct {
Foo string
}
b, err := msgpack.Marshal(&Item{Foo: "bar"})
if err != nil {
panic(err)
}
var item Item
err = msgpack.Unmarshal(b, &item)
if err != nil {
panic(err)
}
fmt.Println(item.Foo)
// Output: bar
}
```
## Benchmark
```
BenchmarkStructVmihailencoMsgpack-4 200000 12814 ns/op 2128 B/op 26 allocs/op
BenchmarkStructUgorjiGoMsgpack-4 100000 17678 ns/op 3616 B/op 70 allocs/op
BenchmarkStructUgorjiGoCodec-4 100000 19053 ns/op 7346 B/op 23 allocs/op
BenchmarkStructJSON-4 20000 69438 ns/op 7864 B/op 26 allocs/op
BenchmarkStructGOB-4 10000 104331 ns/op 14664 B/op 278 allocs/op
```
## Howto
Please go through [examples](https://godoc.org/github.com/vmihailenco/msgpack#pkg-examples) to get an idea how to use this package.
## See also
- [Golang PostgreSQL ORM](https://github.com/go-pg/pg)
- [Golang message task queue](https://github.com/vmihailenco/taskq)

View File

@ -1,64 +0,0 @@
// +build appengine
package msgpack
import (
"reflect"
ds "google.golang.org/appengine/datastore"
)
func init() {
Register((*ds.Key)(nil), encodeDatastoreKeyValue, decodeDatastoreKeyValue)
Register((*ds.Cursor)(nil), encodeDatastoreCursorValue, decodeDatastoreCursorValue)
}
func EncodeDatastoreKey(e *Encoder, key *ds.Key) error {
if key == nil {
return e.EncodeNil()
}
return e.EncodeString(key.Encode())
}
func encodeDatastoreKeyValue(e *Encoder, v reflect.Value) error {
key := v.Interface().(*ds.Key)
return EncodeDatastoreKey(e, key)
}
func DecodeDatastoreKey(d *Decoder) (*ds.Key, error) {
v, err := d.DecodeString()
if err != nil {
return nil, err
}
if v == "" {
return nil, nil
}
return ds.DecodeKey(v)
}
func decodeDatastoreKeyValue(d *Decoder, v reflect.Value) error {
key, err := DecodeDatastoreKey(d)
if err != nil {
return err
}
v.Set(reflect.ValueOf(key))
return nil
}
func encodeDatastoreCursorValue(e *Encoder, v reflect.Value) error {
cursor := v.Interface().(ds.Cursor)
return e.Encode(cursor.String())
}
func decodeDatastoreCursorValue(d *Decoder, v reflect.Value) error {
s, err := d.DecodeString()
if err != nil {
return err
}
cursor, err := ds.DecodeCursor(s)
if err != nil {
return err
}
v.Set(reflect.ValueOf(cursor))
return nil
}

View File

@ -1,90 +0,0 @@
package codes
type Code byte
var (
PosFixedNumHigh Code = 0x7f
NegFixedNumLow Code = 0xe0
Nil Code = 0xc0
False Code = 0xc2
True Code = 0xc3
Float Code = 0xca
Double Code = 0xcb
Uint8 Code = 0xcc
Uint16 Code = 0xcd
Uint32 Code = 0xce
Uint64 Code = 0xcf
Int8 Code = 0xd0
Int16 Code = 0xd1
Int32 Code = 0xd2
Int64 Code = 0xd3
FixedStrLow Code = 0xa0
FixedStrHigh Code = 0xbf
FixedStrMask Code = 0x1f
Str8 Code = 0xd9
Str16 Code = 0xda
Str32 Code = 0xdb
Bin8 Code = 0xc4
Bin16 Code = 0xc5
Bin32 Code = 0xc6
FixedArrayLow Code = 0x90
FixedArrayHigh Code = 0x9f
FixedArrayMask Code = 0xf
Array16 Code = 0xdc
Array32 Code = 0xdd
FixedMapLow Code = 0x80
FixedMapHigh Code = 0x8f
FixedMapMask Code = 0xf
Map16 Code = 0xde
Map32 Code = 0xdf
FixExt1 Code = 0xd4
FixExt2 Code = 0xd5
FixExt4 Code = 0xd6
FixExt8 Code = 0xd7
FixExt16 Code = 0xd8
Ext8 Code = 0xc7
Ext16 Code = 0xc8
Ext32 Code = 0xc9
)
func IsFixedNum(c Code) bool {
return c <= PosFixedNumHigh || c >= NegFixedNumLow
}
func IsFixedMap(c Code) bool {
return c >= FixedMapLow && c <= FixedMapHigh
}
func IsFixedArray(c Code) bool {
return c >= FixedArrayLow && c <= FixedArrayHigh
}
func IsFixedString(c Code) bool {
return c >= FixedStrLow && c <= FixedStrHigh
}
func IsString(c Code) bool {
return IsFixedString(c) || c == Str8 || c == Str16 || c == Str32
}
func IsBin(c Code) bool {
return c == Bin8 || c == Bin16 || c == Bin32
}
func IsFixedExt(c Code) bool {
return c >= FixExt1 && c <= FixExt16
}
func IsExt(c Code) bool {
return IsFixedExt(c) || c == Ext8 || c == Ext16 || c == Ext32
}

View File

@ -1,244 +0,0 @@
package msgpack
import (
"bytes"
"fmt"
"reflect"
"sync"
"github.com/vmihailenco/msgpack/v4/codes"
)
type extInfo struct {
Type reflect.Type
Decoder decoderFunc
}
var extTypes = make(map[int8]*extInfo)
var bufferPool = &sync.Pool{
New: func() interface{} {
return new(bytes.Buffer)
},
}
// RegisterExt records a type, identified by a value for that type,
// under the provided id. That id will identify the concrete type of a value
// sent or received as an interface variable. Only types that will be
// transferred as implementations of interface values need to be registered.
// Expecting to be used only during initialization, it panics if the mapping
// between types and ids is not a bijection.
func RegisterExt(id int8, value interface{}) {
typ := reflect.TypeOf(value)
if typ.Kind() == reflect.Ptr {
typ = typ.Elem()
}
ptr := reflect.PtrTo(typ)
if _, ok := extTypes[id]; ok {
panic(fmt.Errorf("msgpack: ext with id=%d is already registered", id))
}
registerExt(id, ptr, getEncoder(ptr), getDecoder(ptr))
registerExt(id, typ, getEncoder(typ), getDecoder(typ))
}
func registerExt(id int8, typ reflect.Type, enc encoderFunc, dec decoderFunc) {
if enc != nil {
typeEncMap.Store(typ, makeExtEncoder(id, enc))
}
if dec != nil {
extTypes[id] = &extInfo{
Type: typ,
Decoder: dec,
}
typeDecMap.Store(typ, makeExtDecoder(id, dec))
}
}
func (e *Encoder) EncodeExtHeader(typeID int8, length int) error {
if err := e.encodeExtLen(length); err != nil {
return err
}
if err := e.w.WriteByte(byte(typeID)); err != nil {
return err
}
return nil
}
func makeExtEncoder(typeID int8, enc encoderFunc) encoderFunc {
return func(e *Encoder, v reflect.Value) error {
buf := bufferPool.Get().(*bytes.Buffer)
defer bufferPool.Put(buf)
buf.Reset()
oldw := e.w
e.w = buf
err := enc(e, v)
e.w = oldw
if err != nil {
return err
}
err = e.EncodeExtHeader(typeID, buf.Len())
if err != nil {
return err
}
return e.write(buf.Bytes())
}
}
func makeExtDecoder(typeID int8, dec decoderFunc) decoderFunc {
return func(d *Decoder, v reflect.Value) error {
c, err := d.PeekCode()
if err != nil {
return err
}
if !codes.IsExt(c) {
return dec(d, v)
}
id, extLen, err := d.DecodeExtHeader()
if err != nil {
return err
}
if id != typeID {
return fmt.Errorf("msgpack: got ext type=%d, wanted %d", id, typeID)
}
d.extLen = extLen
return dec(d, v)
}
}
func (e *Encoder) encodeExtLen(l int) error {
switch l {
case 1:
return e.writeCode(codes.FixExt1)
case 2:
return e.writeCode(codes.FixExt2)
case 4:
return e.writeCode(codes.FixExt4)
case 8:
return e.writeCode(codes.FixExt8)
case 16:
return e.writeCode(codes.FixExt16)
}
if l < 256 {
return e.write1(codes.Ext8, uint8(l))
}
if l < 65536 {
return e.write2(codes.Ext16, uint16(l))
}
return e.write4(codes.Ext32, uint32(l))
}
func (d *Decoder) parseExtLen(c codes.Code) (int, error) {
switch c {
case codes.FixExt1:
return 1, nil
case codes.FixExt2:
return 2, nil
case codes.FixExt4:
return 4, nil
case codes.FixExt8:
return 8, nil
case codes.FixExt16:
return 16, nil
case codes.Ext8:
n, err := d.uint8()
return int(n), err
case codes.Ext16:
n, err := d.uint16()
return int(n), err
case codes.Ext32:
n, err := d.uint32()
return int(n), err
default:
return 0, fmt.Errorf("msgpack: invalid code=%x decoding ext length", c)
}
}
func (d *Decoder) extHeader(c codes.Code) (int8, int, error) {
length, err := d.parseExtLen(c)
if err != nil {
return 0, 0, err
}
typeID, err := d.readCode()
if err != nil {
return 0, 0, err
}
return int8(typeID), length, nil
}
func (d *Decoder) DecodeExtHeader() (typeID int8, length int, err error) {
c, err := d.readCode()
if err != nil {
return
}
return d.extHeader(c)
}
func (d *Decoder) extInterface(c codes.Code) (interface{}, error) {
extID, extLen, err := d.extHeader(c)
if err != nil {
return nil, err
}
info, ok := extTypes[extID]
if !ok {
return nil, fmt.Errorf("msgpack: unknown ext id=%d", extID)
}
v := reflect.New(info.Type)
d.extLen = extLen
err = info.Decoder(d, v.Elem())
d.extLen = 0
if err != nil {
return nil, err
}
return v.Interface(), nil
}
func (d *Decoder) skipExt(c codes.Code) error {
n, err := d.parseExtLen(c)
if err != nil {
return err
}
return d.skipN(n + 1)
}
func (d *Decoder) skipExtHeader(c codes.Code) error {
// Read ext type.
_, err := d.readCode()
if err != nil {
return err
}
// Read ext body len.
for i := 0; i < extHeaderLen(c); i++ {
_, err := d.readCode()
if err != nil {
return err
}
}
return nil
}
func extHeaderLen(c codes.Code) int {
switch c {
case codes.Ext8:
return 1
case codes.Ext16:
return 2
case codes.Ext32:
return 4
}
return 0
}

View File

@ -1,236 +0,0 @@
package msgpack
import (
"encoding/binary"
"errors"
"fmt"
"math"
"reflect"
"github.com/vmihailenco/msgpack/v4/codes"
)
var internStringExtID int8 = -128
var errUnexpectedCode = errors.New("msgpack: unexpected code")
func encodeInternInterfaceValue(e *Encoder, v reflect.Value) error {
if v.IsNil() {
return e.EncodeNil()
}
v = v.Elem()
if v.Kind() == reflect.String {
return encodeInternStringValue(e, v)
}
return e.EncodeValue(v)
}
func encodeInternStringValue(e *Encoder, v reflect.Value) error {
s := v.String()
if s != "" {
if idx, ok := e.intern[s]; ok {
return e.internStringIndex(idx)
}
if e.intern == nil {
e.intern = make(map[string]int)
}
idx := len(e.intern)
e.intern[s] = idx
}
return e.EncodeString(s)
}
func (e *Encoder) internStringIndex(idx int) error {
if idx < math.MaxUint8 {
if err := e.writeCode(codes.FixExt1); err != nil {
return err
}
if err := e.w.WriteByte(byte(internStringExtID)); err != nil {
return err
}
return e.w.WriteByte(byte(idx))
}
if idx < math.MaxUint16 {
if err := e.writeCode(codes.FixExt2); err != nil {
return err
}
if err := e.w.WriteByte(byte(internStringExtID)); err != nil {
return err
}
if err := e.w.WriteByte(byte(idx >> 8)); err != nil {
return err
}
return e.w.WriteByte(byte(idx))
}
if int64(idx) < math.MaxUint32 {
if err := e.writeCode(codes.FixExt4); err != nil {
return err
}
if err := e.w.WriteByte(byte(internStringExtID)); err != nil {
return err
}
if err := e.w.WriteByte(byte(idx >> 24)); err != nil {
return err
}
if err := e.w.WriteByte(byte(idx >> 16)); err != nil {
return err
}
if err := e.w.WriteByte(byte(idx >> 8)); err != nil {
return err
}
return e.w.WriteByte(byte(idx))
}
return fmt.Errorf("msgpack: intern string index=%d is too large", idx)
}
//------------------------------------------------------------------------------
func decodeInternInterfaceValue(d *Decoder, v reflect.Value) error {
c, err := d.readCode()
if err != nil {
return err
}
s, err := d.internString(c)
if err == nil {
v.Set(reflect.ValueOf(s))
return nil
}
if err != nil && err != errUnexpectedCode {
return err
}
if err := d.s.UnreadByte(); err != nil {
return err
}
return decodeInterfaceValue(d, v)
}
func decodeInternStringValue(d *Decoder, v reflect.Value) error {
if err := mustSet(v); err != nil {
return err
}
c, err := d.readCode()
if err != nil {
return err
}
s, err := d.internString(c)
if err != nil {
if err == errUnexpectedCode {
return fmt.Errorf("msgpack: invalid code=%x decoding intern string", c)
}
return err
}
v.SetString(s)
return nil
}
func (d *Decoder) internString(c codes.Code) (string, error) {
if codes.IsFixedString(c) {
n := int(c & codes.FixedStrMask)
return d.internStringWithLen(n)
}
switch c {
case codes.FixExt1, codes.FixExt2, codes.FixExt4:
typeID, length, err := d.extHeader(c)
if err != nil {
return "", err
}
if typeID != internStringExtID {
err := fmt.Errorf("msgpack: got ext type=%d, wanted %d",
typeID, internStringExtID)
return "", err
}
idx, err := d.internStringIndex(length)
if err != nil {
return "", err
}
return d.internStringAtIndex(idx)
case codes.Str8, codes.Bin8:
n, err := d.uint8()
if err != nil {
return "", err
}
return d.internStringWithLen(int(n))
case codes.Str16, codes.Bin16:
n, err := d.uint16()
if err != nil {
return "", err
}
return d.internStringWithLen(int(n))
case codes.Str32, codes.Bin32:
n, err := d.uint32()
if err != nil {
return "", err
}
return d.internStringWithLen(int(n))
}
return "", errUnexpectedCode
}
func (d *Decoder) internStringIndex(length int) (int, error) {
switch length {
case 1:
c, err := d.s.ReadByte()
if err != nil {
return 0, err
}
return int(c), nil
case 2:
b, err := d.readN(2)
if err != nil {
return 0, err
}
n := binary.BigEndian.Uint16(b)
return int(n), nil
case 4:
b, err := d.readN(4)
if err != nil {
return 0, err
}
n := binary.BigEndian.Uint32(b)
return int(n), nil
}
err := fmt.Errorf("msgpack: unsupported intern string index length=%d", length)
return 0, err
}
func (d *Decoder) internStringAtIndex(idx int) (string, error) {
if idx >= len(d.intern) {
err := fmt.Errorf("msgpack: intern string with index=%d does not exist", idx)
return "", err
}
return d.intern[idx], nil
}
func (d *Decoder) internStringWithLen(n int) (string, error) {
if n <= 0 {
return "", nil
}
s, err := d.stringWithLen(n)
if err != nil {
return "", err
}
d.intern = append(d.intern, s)
return s, nil
}

View File

@ -1,17 +0,0 @@
package msgpack
type Marshaler interface {
MarshalMsgpack() ([]byte, error)
}
type Unmarshaler interface {
UnmarshalMsgpack([]byte) error
}
type CustomEncoder interface {
EncodeMsgpack(*Encoder) error
}
type CustomDecoder interface {
DecodeMsgpack(*Decoder) error
}

4
vendor/github.com/vmihailenco/msgpack/v5/.prettierrc generated vendored Normal file
View File

@ -0,0 +1,4 @@
semi: false
singleQuote: true
proseWrap: always
printWidth: 100

View File

@ -2,10 +2,8 @@ sudo: false
language: go
go:
- 1.11.x
- 1.12.x
- 1.13.x
- 1.14.x
- 1.15.x
- 1.16.x
- tip
matrix:
@ -18,4 +16,5 @@ env:
go_import_path: github.com/vmihailenco/msgpack
before_install:
- curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s -- -b $(go env GOPATH)/bin v1.21.0
- curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s -- -b $(go
env GOPATH)/bin v1.31.0

View File

@ -1,8 +1,32 @@
## [5.3.5](https://github.com/vmihailenco/msgpack/compare/v5.3.4...v5.3.5) (2021-10-22)
## v5
### Added
- `DecodeMap` is split into `DecodeMap`, `DecodeTypedMap`, and `DecodeUntypedMap`.
- New msgpack extensions API.
### Changed
- `Reset*` functions also reset flags.
- `SetMapDecodeFunc` is renamed to `SetMapDecoder`.
- `StructAsArray` is renamed to `UseArrayEncodedStructs`.
- `SortMapKeys` is renamed to `SetSortMapKeys`.
### Removed
- `UseJSONTag` is removed. Use `SetCustomStructTag("json")` instead.
## v4
- Encode, Decode, Marshal, and Unmarshal are changed to accept single argument. EncodeMulti and DecodeMulti are added as replacement.
- Encode, Decode, Marshal, and Unmarshal are changed to accept single argument. EncodeMulti and
DecodeMulti are added as replacement.
- Added EncodeInt8/16/32/64 and EncodeUint8/16/32/64.
- Encoder changed to preserve type of numbers instead of chosing most compact encoding. The old behavior can be achieved with Encoder.UseCompactEncoding.
- Encoder changed to preserve type of numbers instead of chosing most compact encoding. The old
behavior can be achieved with Encoder.UseCompactEncoding.
## v3.3
@ -16,9 +40,12 @@
- gopkg.in is not supported any more. Update import path to github.com/vmihailenco/msgpack.
- Msgpack maps are decoded into map[string]interface{} by default.
- EncodeSliceLen is removed in favor of EncodeArrayLen. DecodeSliceLen is removed in favor of DecodeArrayLen.
- EncodeSliceLen is removed in favor of EncodeArrayLen. DecodeSliceLen is removed in favor of
DecodeArrayLen.
- Embedded structs are automatically inlined where possible.
- Time is encoded using extension as described in https://github.com/msgpack/msgpack/pull/209. Old format is supported as well.
- EncodeInt8/16/32/64 is replaced with EncodeInt. EncodeUint8/16/32/64 is replaced with EncodeUint. There should be no performance differences.
- Time is encoded using extension as described in https://github.com/msgpack/msgpack/pull/209. Old
format is supported as well.
- EncodeInt8/16/32/64 is replaced with EncodeInt. EncodeUint8/16/32/64 is replaced with EncodeUint.
There should be no performance differences.
- DecodeInterface can now return int8/16/32 and uint8/16/32.
- PeekCode returns codes.Code instead of byte.

View File

@ -1,6 +1,6 @@
all:
test:
go test ./...
go test ./... -short -race
go test ./... -run=NONE -bench=. -benchmem
env GOOS=linux GOARCH=386 go test ./...
golangci-lint run
go vet

86
vendor/github.com/vmihailenco/msgpack/v5/README.md generated vendored Normal file
View File

@ -0,0 +1,86 @@
# MessagePack encoding for Golang
[![Build Status](https://travis-ci.org/vmihailenco/msgpack.svg)](https://travis-ci.org/vmihailenco/msgpack)
[![PkgGoDev](https://pkg.go.dev/badge/github.com/vmihailenco/msgpack/v5)](https://pkg.go.dev/github.com/vmihailenco/msgpack/v5)
[![Documentation](https://img.shields.io/badge/msgpack-documentation-informational)](https://msgpack.uptrace.dev/)
[![Chat](https://discordapp.com/api/guilds/752070105847955518/widget.png)](https://discord.gg/rWtp5Aj)
> :heart:
> [**Uptrace.dev** - All-in-one tool to optimize performance and monitor errors & logs](https://uptrace.dev/?utm_source=gh-msgpack&utm_campaign=gh-msgpack-var2)
- Join [Discord](https://discord.gg/rWtp5Aj) to ask questions.
- [Documentation](https://msgpack.uptrace.dev)
- [Reference](https://pkg.go.dev/github.com/vmihailenco/msgpack/v5)
- [Examples](https://pkg.go.dev/github.com/vmihailenco/msgpack/v5#pkg-examples)
Other projects you may like:
- [Bun](https://bun.uptrace.dev) - fast and simple SQL client for PostgreSQL, MySQL, and SQLite.
- [BunRouter](https://bunrouter.uptrace.dev/) - fast and flexible HTTP router for Go.
## Features
- Primitives, arrays, maps, structs, time.Time and interface{}.
- Appengine \*datastore.Key and datastore.Cursor.
- [CustomEncoder]/[CustomDecoder] interfaces for custom encoding.
- [Extensions](https://pkg.go.dev/github.com/vmihailenco/msgpack/v5#example-RegisterExt) to encode
type information.
- Renaming fields via `msgpack:"my_field_name"` and alias via `msgpack:"alias:another_name"`.
- Omitting individual empty fields via `msgpack:",omitempty"` tag or all
[empty fields in a struct](https://pkg.go.dev/github.com/vmihailenco/msgpack/v5#example-Marshal-OmitEmpty).
- [Map keys sorting](https://pkg.go.dev/github.com/vmihailenco/msgpack/v5#Encoder.SetSortMapKeys).
- Encoding/decoding all
[structs as arrays](https://pkg.go.dev/github.com/vmihailenco/msgpack/v5#Encoder.UseArrayEncodedStructs)
or
[individual structs](https://pkg.go.dev/github.com/vmihailenco/msgpack/v5#example-Marshal-AsArray).
- [Encoder.SetCustomStructTag] with [Decoder.SetCustomStructTag] can turn msgpack into drop-in
replacement for any tag.
- Simple but very fast and efficient
[queries](https://pkg.go.dev/github.com/vmihailenco/msgpack/v5#example-Decoder.Query).
[customencoder]: https://pkg.go.dev/github.com/vmihailenco/msgpack/v5#CustomEncoder
[customdecoder]: https://pkg.go.dev/github.com/vmihailenco/msgpack/v5#CustomDecoder
[encoder.setcustomstructtag]:
https://pkg.go.dev/github.com/vmihailenco/msgpack/v5#Encoder.SetCustomStructTag
[decoder.setcustomstructtag]:
https://pkg.go.dev/github.com/vmihailenco/msgpack/v5#Decoder.SetCustomStructTag
## Installation
msgpack supports 2 last Go versions and requires support for
[Go modules](https://github.com/golang/go/wiki/Modules). So make sure to initialize a Go module:
```shell
go mod init github.com/my/repo
```
And then install msgpack/v5 (note _v5_ in the import; omitting it is a popular mistake):
```shell
go get github.com/vmihailenco/msgpack/v5
```
## Quickstart
```go
import "github.com/vmihailenco/msgpack/v5"
func ExampleMarshal() {
type Item struct {
Foo string
}
b, err := msgpack.Marshal(&Item{Foo: "bar"})
if err != nil {
panic(err)
}
var item Item
err = msgpack.Unmarshal(b, &item)
if err != nil {
panic(err)
}
fmt.Println(item.Foo)
// Output: bar
}
```

View File

@ -0,0 +1 @@
module.exports = { extends: ['@commitlint/config-conventional'] }

View File

@ -10,12 +10,11 @@ import (
"sync"
"time"
"github.com/vmihailenco/msgpack/v4/codes"
"github.com/vmihailenco/msgpack/v5/msgpcode"
)
const (
looseIfaceFlag uint32 = 1 << iota
decodeUsingJSONFlag
looseInterfaceDecodingFlag uint32 = 1 << iota
disallowUnknownFieldsFlag
)
@ -38,19 +37,27 @@ var decPool = sync.Pool{
},
}
func GetDecoder() *Decoder {
return decPool.Get().(*Decoder)
}
func PutDecoder(dec *Decoder) {
dec.r = nil
dec.s = nil
decPool.Put(dec)
}
//------------------------------------------------------------------------------
// Unmarshal decodes the MessagePack-encoded data and stores the result
// in the value pointed to by v.
func Unmarshal(data []byte, v interface{}) error {
dec := decPool.Get().(*Decoder)
dec := GetDecoder()
if r, ok := dec.r.(*bytes.Reader); ok {
r.Reset(data)
} else {
dec.Reset(bytes.NewReader(data))
}
dec.Reset(bytes.NewReader(data))
err := dec.Decode(v)
decPool.Put(dec)
PutDecoder(dec)
return err
}
@ -61,18 +68,18 @@ type Decoder struct {
s io.ByteScanner
buf []byte
extLen int
rec []byte // accumulates read data if not nil
rec []byte // accumulates read data if not nil
intern []string
flags uint32
decodeMapFunc func(*Decoder) (interface{}, error)
dict []string
flags uint32
structTag string
mapDecoder func(*Decoder) (interface{}, error)
}
// NewDecoder returns a new decoder that reads from r.
//
// The decoder introduces its own buffering and may read data from r
// beyond the MessagePack values requested. Buffering can be disabled
// beyond the requested msgpack values. Buffering can be disabled
// by passing a reader that implements io.ByteScanner interface.
func NewDecoder(r io.Reader) *Decoder {
d := new(Decoder)
@ -83,65 +90,77 @@ func NewDecoder(r io.Reader) *Decoder {
// Reset discards any buffered data, resets all state, and switches the buffered
// reader to read from r.
func (d *Decoder) Reset(r io.Reader) {
d.ResetDict(r, nil)
}
// ResetDict is like Reset, but also resets the dict.
func (d *Decoder) ResetDict(r io.Reader, dict []string) {
d.resetReader(r)
d.flags = 0
d.structTag = ""
d.mapDecoder = nil
d.dict = dict
}
func (d *Decoder) WithDict(dict []string, fn func(*Decoder) error) error {
oldDict := d.dict
d.dict = dict
err := fn(d)
d.dict = oldDict
return err
}
func (d *Decoder) resetReader(r io.Reader) {
if br, ok := r.(bufReader); ok {
d.r = br
d.s = br
} else if br, ok := d.r.(*bufio.Reader); ok {
br.Reset(r)
} else {
br := bufio.NewReader(r)
d.r = br
d.s = br
}
if d.intern != nil {
d.intern = d.intern[:0]
}
//TODO:
//d.useLoose = false
//d.useJSONTag = false
//d.disallowUnknownFields = false
//d.decodeMapFunc = nil
}
func (d *Decoder) SetDecodeMapFunc(fn func(*Decoder) (interface{}, error)) {
d.decodeMapFunc = fn
func (d *Decoder) SetMapDecoder(fn func(*Decoder) (interface{}, error)) {
d.mapDecoder = fn
}
// UseDecodeInterfaceLoose causes decoder to use DecodeInterfaceLoose
// UseLooseInterfaceDecoding causes decoder to use DecodeInterfaceLoose
// to decode msgpack value into Go interface{}.
func (d *Decoder) UseDecodeInterfaceLoose(on bool) *Decoder {
func (d *Decoder) UseLooseInterfaceDecoding(on bool) {
if on {
d.flags |= looseIfaceFlag
d.flags |= looseInterfaceDecodingFlag
} else {
d.flags &= ^looseIfaceFlag
d.flags &= ^looseInterfaceDecodingFlag
}
return d
}
// UseJSONTag causes the Decoder to use json struct tag as fallback option
// SetCustomStructTag causes the decoder to use the supplied tag as a fallback option
// if there is no msgpack tag.
func (d *Decoder) UseJSONTag(on bool) *Decoder {
if on {
d.flags |= decodeUsingJSONFlag
} else {
d.flags &= ^decodeUsingJSONFlag
}
return d
func (d *Decoder) SetCustomStructTag(tag string) {
d.structTag = tag
}
// DisallowUnknownFields causes the Decoder to return an error when the destination
// is a struct and the input contains object keys which do not match any
// non-ignored, exported fields in the destination.
func (d *Decoder) DisallowUnknownFields() {
if true {
func (d *Decoder) DisallowUnknownFields(on bool) {
if on {
d.flags |= disallowUnknownFieldsFlag
} else {
d.flags &= ^disallowUnknownFieldsFlag
}
}
// UseInternedStrings enables support for decoding interned strings.
func (d *Decoder) UseInternedStrings(on bool) {
if on {
d.flags |= useInternedStringsFlag
} else {
d.flags &= ^useInternedStringsFlag
}
}
// Buffered returns a reader of the data remaining in the Decoder's buffer.
// The reader is valid until the next call to Decode.
func (d *Decoder) Buffered() io.Reader {
@ -250,12 +269,22 @@ func (d *Decoder) Decode(v interface{}) error {
return errors.New("msgpack: Decode(nil)")
}
if vv.Kind() != reflect.Ptr {
return fmt.Errorf("msgpack: Decode(nonsettable %T)", v)
return fmt.Errorf("msgpack: Decode(non-pointer %T)", v)
}
if vv.IsNil() {
return fmt.Errorf("msgpack: Decode(non-settable %T)", v)
}
vv = vv.Elem()
if !vv.IsValid() {
return fmt.Errorf("msgpack: Decode(nonsettable %T)", v)
if vv.Kind() == reflect.Interface {
if !vv.IsNil() {
vv = vv.Elem()
if vv.Kind() != reflect.Ptr {
return fmt.Errorf("msgpack: Decode(non-pointer %s)", vv.Type().String())
}
}
}
return d.DecodeValue(vv)
}
@ -269,7 +298,7 @@ func (d *Decoder) DecodeMulti(v ...interface{}) error {
}
func (d *Decoder) decodeInterfaceCond() (interface{}, error) {
if d.flags&looseIfaceFlag != 0 {
if d.flags&looseInterfaceDecodingFlag != 0 {
return d.DecodeInterfaceLoose()
}
return d.DecodeInterface()
@ -285,7 +314,7 @@ func (d *Decoder) DecodeNil() error {
if err != nil {
return err
}
if c != codes.Nil {
if c != msgpcode.Nil {
return fmt.Errorf("msgpack: invalid code=%x decoding nil", c)
}
return nil
@ -311,11 +340,14 @@ func (d *Decoder) DecodeBool() (bool, error) {
return d.bool(c)
}
func (d *Decoder) bool(c codes.Code) (bool, error) {
if c == codes.False {
func (d *Decoder) bool(c byte) (bool, error) {
if c == msgpcode.Nil {
return false, nil
}
if c == codes.True {
if c == msgpcode.False {
return false, nil
}
if c == msgpcode.True {
return true, nil
}
return false, fmt.Errorf("msgpack: invalid code=%x decoding bool", c)
@ -349,63 +381,63 @@ func (d *Decoder) DecodeInterface() (interface{}, error) {
return nil, err
}
if codes.IsFixedNum(c) {
if msgpcode.IsFixedNum(c) {
return int8(c), nil
}
if codes.IsFixedMap(c) {
if msgpcode.IsFixedMap(c) {
err = d.s.UnreadByte()
if err != nil {
return nil, err
}
return d.DecodeMap()
return d.decodeMapDefault()
}
if codes.IsFixedArray(c) {
if msgpcode.IsFixedArray(c) {
return d.decodeSlice(c)
}
if codes.IsFixedString(c) {
if msgpcode.IsFixedString(c) {
return d.string(c)
}
switch c {
case codes.Nil:
case msgpcode.Nil:
return nil, nil
case codes.False, codes.True:
case msgpcode.False, msgpcode.True:
return d.bool(c)
case codes.Float:
case msgpcode.Float:
return d.float32(c)
case codes.Double:
case msgpcode.Double:
return d.float64(c)
case codes.Uint8:
case msgpcode.Uint8:
return d.uint8()
case codes.Uint16:
case msgpcode.Uint16:
return d.uint16()
case codes.Uint32:
case msgpcode.Uint32:
return d.uint32()
case codes.Uint64:
case msgpcode.Uint64:
return d.uint64()
case codes.Int8:
case msgpcode.Int8:
return d.int8()
case codes.Int16:
case msgpcode.Int16:
return d.int16()
case codes.Int32:
case msgpcode.Int32:
return d.int32()
case codes.Int64:
case msgpcode.Int64:
return d.int64()
case codes.Bin8, codes.Bin16, codes.Bin32:
case msgpcode.Bin8, msgpcode.Bin16, msgpcode.Bin32:
return d.bytes(c, nil)
case codes.Str8, codes.Str16, codes.Str32:
case msgpcode.Str8, msgpcode.Str16, msgpcode.Str32:
return d.string(c)
case codes.Array16, codes.Array32:
case msgpcode.Array16, msgpcode.Array32:
return d.decodeSlice(c)
case codes.Map16, codes.Map32:
case msgpcode.Map16, msgpcode.Map32:
err = d.s.UnreadByte()
if err != nil {
return nil, err
}
return d.DecodeMap()
case codes.FixExt1, codes.FixExt2, codes.FixExt4, codes.FixExt8, codes.FixExt16,
codes.Ext8, codes.Ext16, codes.Ext32:
return d.extInterface(c)
return d.decodeMapDefault()
case msgpcode.FixExt1, msgpcode.FixExt2, msgpcode.FixExt4, msgpcode.FixExt8, msgpcode.FixExt16,
msgpcode.Ext8, msgpcode.Ext16, msgpcode.Ext32:
return d.decodeInterfaceExt(c)
}
return 0, fmt.Errorf("msgpack: unknown code %x decoding interface{}", c)
@ -415,55 +447,55 @@ func (d *Decoder) DecodeInterface() (interface{}, error) {
// - int8, int16, and int32 are converted to int64,
// - uint8, uint16, and uint32 are converted to uint64,
// - float32 is converted to float64.
// - []byte is converted to string.
func (d *Decoder) DecodeInterfaceLoose() (interface{}, error) {
c, err := d.readCode()
if err != nil {
return nil, err
}
if codes.IsFixedNum(c) {
if msgpcode.IsFixedNum(c) {
return int64(int8(c)), nil
}
if codes.IsFixedMap(c) {
if msgpcode.IsFixedMap(c) {
err = d.s.UnreadByte()
if err != nil {
return nil, err
}
return d.DecodeMap()
return d.decodeMapDefault()
}
if codes.IsFixedArray(c) {
if msgpcode.IsFixedArray(c) {
return d.decodeSlice(c)
}
if codes.IsFixedString(c) {
if msgpcode.IsFixedString(c) {
return d.string(c)
}
switch c {
case codes.Nil:
case msgpcode.Nil:
return nil, nil
case codes.False, codes.True:
case msgpcode.False, msgpcode.True:
return d.bool(c)
case codes.Float, codes.Double:
case msgpcode.Float, msgpcode.Double:
return d.float64(c)
case codes.Uint8, codes.Uint16, codes.Uint32, codes.Uint64:
case msgpcode.Uint8, msgpcode.Uint16, msgpcode.Uint32, msgpcode.Uint64:
return d.uint(c)
case codes.Int8, codes.Int16, codes.Int32, codes.Int64:
case msgpcode.Int8, msgpcode.Int16, msgpcode.Int32, msgpcode.Int64:
return d.int(c)
case codes.Bin8, codes.Bin16, codes.Bin32:
return d.bytes(c, nil)
case codes.Str8, codes.Str16, codes.Str32:
case msgpcode.Str8, msgpcode.Str16, msgpcode.Str32,
msgpcode.Bin8, msgpcode.Bin16, msgpcode.Bin32:
return d.string(c)
case codes.Array16, codes.Array32:
case msgpcode.Array16, msgpcode.Array32:
return d.decodeSlice(c)
case codes.Map16, codes.Map32:
case msgpcode.Map16, msgpcode.Map32:
err = d.s.UnreadByte()
if err != nil {
return nil, err
}
return d.DecodeMap()
case codes.FixExt1, codes.FixExt2, codes.FixExt4, codes.FixExt8, codes.FixExt16,
codes.Ext8, codes.Ext16, codes.Ext32:
return d.extInterface(c)
return d.decodeMapDefault()
case msgpcode.FixExt1, msgpcode.FixExt2, msgpcode.FixExt4, msgpcode.FixExt8, msgpcode.FixExt16,
msgpcode.Ext8, msgpcode.Ext16, msgpcode.Ext32:
return d.decodeInterfaceExt(c)
}
return 0, fmt.Errorf("msgpack: unknown code %x decoding interface{}", c)
@ -476,63 +508,78 @@ func (d *Decoder) Skip() error {
return err
}
if codes.IsFixedNum(c) {
if msgpcode.IsFixedNum(c) {
return nil
}
if codes.IsFixedMap(c) {
if msgpcode.IsFixedMap(c) {
return d.skipMap(c)
}
if codes.IsFixedArray(c) {
if msgpcode.IsFixedArray(c) {
return d.skipSlice(c)
}
if codes.IsFixedString(c) {
if msgpcode.IsFixedString(c) {
return d.skipBytes(c)
}
switch c {
case codes.Nil, codes.False, codes.True:
case msgpcode.Nil, msgpcode.False, msgpcode.True:
return nil
case codes.Uint8, codes.Int8:
case msgpcode.Uint8, msgpcode.Int8:
return d.skipN(1)
case codes.Uint16, codes.Int16:
case msgpcode.Uint16, msgpcode.Int16:
return d.skipN(2)
case codes.Uint32, codes.Int32, codes.Float:
case msgpcode.Uint32, msgpcode.Int32, msgpcode.Float:
return d.skipN(4)
case codes.Uint64, codes.Int64, codes.Double:
case msgpcode.Uint64, msgpcode.Int64, msgpcode.Double:
return d.skipN(8)
case codes.Bin8, codes.Bin16, codes.Bin32:
case msgpcode.Bin8, msgpcode.Bin16, msgpcode.Bin32:
return d.skipBytes(c)
case codes.Str8, codes.Str16, codes.Str32:
case msgpcode.Str8, msgpcode.Str16, msgpcode.Str32:
return d.skipBytes(c)
case codes.Array16, codes.Array32:
case msgpcode.Array16, msgpcode.Array32:
return d.skipSlice(c)
case codes.Map16, codes.Map32:
case msgpcode.Map16, msgpcode.Map32:
return d.skipMap(c)
case codes.FixExt1, codes.FixExt2, codes.FixExt4, codes.FixExt8, codes.FixExt16,
codes.Ext8, codes.Ext16, codes.Ext32:
case msgpcode.FixExt1, msgpcode.FixExt2, msgpcode.FixExt4, msgpcode.FixExt8, msgpcode.FixExt16,
msgpcode.Ext8, msgpcode.Ext16, msgpcode.Ext32:
return d.skipExt(c)
}
return fmt.Errorf("msgpack: unknown code %x", c)
}
func (d *Decoder) DecodeRaw() (RawMessage, error) {
d.rec = make([]byte, 0)
if err := d.Skip(); err != nil {
return nil, err
}
msg := RawMessage(d.rec)
d.rec = nil
return msg, nil
}
// PeekCode returns the next MessagePack code without advancing the reader.
// Subpackage msgpack/codes contains list of available codes.
func (d *Decoder) PeekCode() (codes.Code, error) {
// Subpackage msgpack/codes defines the list of available msgpcode.
func (d *Decoder) PeekCode() (byte, error) {
c, err := d.s.ReadByte()
if err != nil {
return 0, err
}
return codes.Code(c), d.s.UnreadByte()
return c, d.s.UnreadByte()
}
// ReadFull reads exactly len(buf) bytes into the buf.
func (d *Decoder) ReadFull(buf []byte) error {
_, err := readN(d.r, buf, len(buf))
return err
}
func (d *Decoder) hasNilCode() bool {
code, err := d.PeekCode()
return err == nil && code == codes.Nil
return err == nil && code == msgpcode.Nil
}
func (d *Decoder) readCode() (codes.Code, error) {
d.extLen = 0
func (d *Decoder) readCode() (byte, error) {
c, err := d.s.ReadByte()
if err != nil {
return 0, err
@ -540,7 +587,7 @@ func (d *Decoder) readCode() (codes.Code, error) {
if d.rec != nil {
d.rec = append(d.rec, c)
}
return codes.Code(c), nil
return c, nil
}
func (d *Decoder) readFull(b []byte) error {
@ -549,7 +596,6 @@ func (d *Decoder) readFull(b []byte) error {
return err
}
if d.rec != nil {
//TODO: read directly into d.rec?
d.rec = append(d.rec, b...)
}
return nil
@ -562,7 +608,7 @@ func (d *Decoder) readN(n int) ([]byte, error) {
return nil, err
}
if d.rec != nil {
//TODO: read directly into d.rec?
// TODO: read directly into d.rec?
d.rec = append(d.rec, d.buf...)
}
return d.buf, nil

View File

@ -5,9 +5,11 @@ import (
"fmt"
"reflect"
"github.com/vmihailenco/msgpack/v4/codes"
"github.com/vmihailenco/msgpack/v5/msgpcode"
)
var errArrayStruct = errors.New("msgpack: number of fields in array-encoded struct has changed")
var (
mapStringStringPtrType = reflect.TypeOf((*map[string]string)(nil))
mapStringStringType = mapStringStringPtrType.Elem()
@ -19,13 +21,13 @@ var (
)
func decodeMapValue(d *Decoder, v reflect.Value) error {
size, err := d.DecodeMapLen()
n, err := d.DecodeMapLen()
if err != nil {
return err
}
typ := v.Type()
if size == -1 {
if n == -1 {
v.Set(reflect.Zero(typ))
return nil
}
@ -33,33 +35,18 @@ func decodeMapValue(d *Decoder, v reflect.Value) error {
if v.IsNil() {
v.Set(reflect.MakeMap(typ))
}
if size == 0 {
if n == 0 {
return nil
}
return decodeMapValueSize(d, v, size)
return d.decodeTypedMapValue(v, n)
}
func decodeMapValueSize(d *Decoder, v reflect.Value, size int) error {
typ := v.Type()
keyType := typ.Key()
valueType := typ.Elem()
for i := 0; i < size; i++ {
mk := reflect.New(keyType).Elem()
if err := d.DecodeValue(mk); err != nil {
return err
}
mv := reflect.New(valueType).Elem()
if err := d.DecodeValue(mv); err != nil {
return err
}
v.SetMapIndex(mk, mv)
func (d *Decoder) decodeMapDefault() (interface{}, error) {
if d.mapDecoder != nil {
return d.mapDecoder(d)
}
return nil
return d.DecodeMap()
}
// DecodeMapLen decodes map length. Length is -1 when map is nil.
@ -69,7 +56,7 @@ func (d *Decoder) DecodeMapLen() (int, error) {
return 0, err
}
if codes.IsExt(c) {
if msgpcode.IsExt(c) {
if err = d.skipExtHeader(c); err != nil {
return 0, err
}
@ -82,37 +69,22 @@ func (d *Decoder) DecodeMapLen() (int, error) {
return d.mapLen(c)
}
func (d *Decoder) mapLen(c codes.Code) (int, error) {
size, err := d._mapLen(c)
err = expandInvalidCodeMapLenError(c, err)
return size, err
}
func (d *Decoder) _mapLen(c codes.Code) (int, error) {
if c == codes.Nil {
func (d *Decoder) mapLen(c byte) (int, error) {
if c == msgpcode.Nil {
return -1, nil
}
if c >= codes.FixedMapLow && c <= codes.FixedMapHigh {
return int(c & codes.FixedMapMask), nil
if c >= msgpcode.FixedMapLow && c <= msgpcode.FixedMapHigh {
return int(c & msgpcode.FixedMapMask), nil
}
if c == codes.Map16 {
if c == msgpcode.Map16 {
size, err := d.uint16()
return int(size), err
}
if c == codes.Map32 {
if c == msgpcode.Map32 {
size, err := d.uint32()
return int(size), err
}
return 0, errInvalidCode
}
var errInvalidCode = errors.New("invalid code")
func expandInvalidCodeMapLenError(c codes.Code, err error) error {
if err == errInvalidCode {
return fmt.Errorf("msgpack: invalid code=%x decoding map length", c)
}
return err
return 0, unexpectedCodeError{code: c, hint: "map length"}
}
func decodeMapStringStringValue(d *Decoder, v reflect.Value) error {
@ -157,61 +129,79 @@ func decodeMapStringInterfaceValue(d *Decoder, v reflect.Value) error {
}
func (d *Decoder) decodeMapStringInterfacePtr(ptr *map[string]interface{}) error {
n, err := d.DecodeMapLen()
m, err := d.DecodeMap()
if err != nil {
return err
}
if n == -1 {
*ptr = nil
return nil
*ptr = m
return nil
}
func (d *Decoder) DecodeMap() (map[string]interface{}, error) {
n, err := d.DecodeMapLen()
if err != nil {
return nil, err
}
m := *ptr
if m == nil {
*ptr = make(map[string]interface{}, min(n, maxMapSize))
m = *ptr
if n == -1 {
return nil, nil
}
m := make(map[string]interface{}, min(n, maxMapSize))
for i := 0; i < n; i++ {
mk, err := d.DecodeString()
if err != nil {
return err
return nil, err
}
mv, err := d.decodeInterfaceCond()
if err != nil {
return err
return nil, err
}
m[mk] = mv
}
return nil
return m, nil
}
var errUnsupportedMapKey = errors.New("msgpack: unsupported map key")
func (d *Decoder) DecodeMap() (interface{}, error) {
if d.decodeMapFunc != nil {
return d.decodeMapFunc(d)
}
size, err := d.DecodeMapLen()
func (d *Decoder) DecodeUntypedMap() (map[interface{}]interface{}, error) {
n, err := d.DecodeMapLen()
if err != nil {
return nil, err
}
if size == -1 {
if n == -1 {
return nil, nil
}
if size == 0 {
return make(map[string]interface{}), nil
m := make(map[interface{}]interface{}, min(n, maxMapSize))
for i := 0; i < n; i++ {
mk, err := d.decodeInterfaceCond()
if err != nil {
return nil, err
}
mv, err := d.decodeInterfaceCond()
if err != nil {
return nil, err
}
m[mk] = mv
}
code, err := d.PeekCode()
return m, nil
}
// DecodeTypedMap decodes a typed map. Typed map is a map that has a fixed type for keys and values.
// Key and value types may be different.
func (d *Decoder) DecodeTypedMap() (interface{}, error) {
n, err := d.DecodeMapLen()
if err != nil {
return nil, err
}
if codes.IsString(code) || codes.IsBin(code) {
return d.decodeMapStringInterfaceSize(size)
if n <= 0 {
return nil, nil
}
key, err := d.decodeInterfaceCond()
@ -228,40 +218,44 @@ func (d *Decoder) DecodeMap() (interface{}, error) {
valueType := reflect.TypeOf(value)
if !keyType.Comparable() {
return nil, errUnsupportedMapKey
return nil, fmt.Errorf("msgpack: unsupported map key: %s", keyType.String())
}
mapType := reflect.MapOf(keyType, valueType)
mapValue := reflect.MakeMap(mapType)
mapValue.SetMapIndex(reflect.ValueOf(key), reflect.ValueOf(value))
size--
err = decodeMapValueSize(d, mapValue, size)
if err != nil {
n--
if err := d.decodeTypedMapValue(mapValue, n); err != nil {
return nil, err
}
return mapValue.Interface(), nil
}
func (d *Decoder) decodeMapStringInterfaceSize(size int) (map[string]interface{}, error) {
m := make(map[string]interface{}, min(size, maxMapSize))
for i := 0; i < size; i++ {
mk, err := d.DecodeString()
if err != nil {
return nil, err
func (d *Decoder) decodeTypedMapValue(v reflect.Value, n int) error {
typ := v.Type()
keyType := typ.Key()
valueType := typ.Elem()
for i := 0; i < n; i++ {
mk := reflect.New(keyType).Elem()
if err := d.DecodeValue(mk); err != nil {
return err
}
mv, err := d.decodeInterfaceCond()
if err != nil {
return nil, err
mv := reflect.New(valueType).Elem()
if err := d.DecodeValue(mv); err != nil {
return err
}
m[mk] = mv
v.SetMapIndex(mk, mv)
}
return m, nil
return nil
}
func (d *Decoder) skipMap(c codes.Code) error {
func (d *Decoder) skipMap(c byte) error {
n, err := d.mapLen(c)
if err != nil {
return err
@ -283,54 +277,45 @@ func decodeStructValue(d *Decoder, v reflect.Value) error {
return err
}
var isArray bool
n, err := d._mapLen(c)
if err != nil {
var err2 error
n, err2 = d.arrayLen(c)
if err2 != nil {
return expandInvalidCodeMapLenError(c, err)
}
isArray = true
n, err := d.mapLen(c)
if err == nil {
return d.decodeStruct(v, n)
}
if n == -1 {
if err = mustSet(v); err != nil {
return err
}
var err2 error
n, err2 = d.arrayLen(c)
if err2 != nil {
return err
}
if n <= 0 {
v.Set(reflect.Zero(v.Type()))
return nil
}
var fields *fields
if d.flags&decodeUsingJSONFlag != 0 {
fields = jsonStructs.Fields(v.Type())
} else {
fields = structs.Fields(v.Type())
fields := structs.Fields(v.Type(), d.structTag)
if n != len(fields.List) {
return errArrayStruct
}
if isArray {
for i, f := range fields.List {
if i >= n {
break
}
if err := f.DecodeValue(d, v); err != nil {
return err
}
for _, f := range fields.List {
if err := f.DecodeValue(d, v); err != nil {
return err
}
}
// Skip extra values.
for i := len(fields.List); i < n; i++ {
if err := d.Skip(); err != nil {
return err
}
}
return nil
}
func (d *Decoder) decodeStruct(v reflect.Value, n int) error {
if n == -1 {
v.Set(reflect.Zero(v.Type()))
return nil
}
fields := structs.Fields(v.Type(), d.structTag)
for i := 0; i < n; i++ {
name, err := d.DecodeString()
name, err := d.decodeStringTemp()
if err != nil {
return err
}
@ -339,9 +324,13 @@ func decodeStructValue(d *Decoder, v reflect.Value) error {
if err := f.DecodeValue(d, v); err != nil {
return err
}
} else if d.flags&disallowUnknownFieldsFlag != 0 {
continue
}
if d.flags&disallowUnknownFieldsFlag != 0 {
return fmt.Errorf("msgpack: unknown field %q", name)
} else if err := d.Skip(); err != nil {
}
if err := d.Skip(); err != nil {
return err
}
}

View File

@ -5,7 +5,7 @@ import (
"math"
"reflect"
"github.com/vmihailenco/msgpack/v4/codes"
"github.com/vmihailenco/msgpack/v5/msgpcode"
)
func (d *Decoder) skipN(n int) error {
@ -18,7 +18,7 @@ func (d *Decoder) uint8() (uint8, error) {
if err != nil {
return 0, err
}
return uint8(c), nil
return c, nil
}
func (d *Decoder) int8() (int8, error) {
@ -87,33 +87,33 @@ func (d *Decoder) DecodeUint64() (uint64, error) {
return d.uint(c)
}
func (d *Decoder) uint(c codes.Code) (uint64, error) {
if c == codes.Nil {
func (d *Decoder) uint(c byte) (uint64, error) {
if c == msgpcode.Nil {
return 0, nil
}
if codes.IsFixedNum(c) {
if msgpcode.IsFixedNum(c) {
return uint64(int8(c)), nil
}
switch c {
case codes.Uint8:
case msgpcode.Uint8:
n, err := d.uint8()
return uint64(n), err
case codes.Int8:
case msgpcode.Int8:
n, err := d.int8()
return uint64(n), err
case codes.Uint16:
case msgpcode.Uint16:
n, err := d.uint16()
return uint64(n), err
case codes.Int16:
case msgpcode.Int16:
n, err := d.int16()
return uint64(n), err
case codes.Uint32:
case msgpcode.Uint32:
n, err := d.uint32()
return uint64(n), err
case codes.Int32:
case msgpcode.Int32:
n, err := d.int32()
return uint64(n), err
case codes.Uint64, codes.Int64:
case msgpcode.Uint64, msgpcode.Int64:
return d.uint64()
}
return 0, fmt.Errorf("msgpack: invalid code=%x decoding uint64", c)
@ -129,33 +129,33 @@ func (d *Decoder) DecodeInt64() (int64, error) {
return d.int(c)
}
func (d *Decoder) int(c codes.Code) (int64, error) {
if c == codes.Nil {
func (d *Decoder) int(c byte) (int64, error) {
if c == msgpcode.Nil {
return 0, nil
}
if codes.IsFixedNum(c) {
if msgpcode.IsFixedNum(c) {
return int64(int8(c)), nil
}
switch c {
case codes.Uint8:
case msgpcode.Uint8:
n, err := d.uint8()
return int64(n), err
case codes.Int8:
case msgpcode.Int8:
n, err := d.uint8()
return int64(int8(n)), err
case codes.Uint16:
case msgpcode.Uint16:
n, err := d.uint16()
return int64(n), err
case codes.Int16:
case msgpcode.Int16:
n, err := d.uint16()
return int64(int16(n)), err
case codes.Uint32:
case msgpcode.Uint32:
n, err := d.uint32()
return int64(n), err
case codes.Int32:
case msgpcode.Int32:
n, err := d.uint32()
return int64(int32(n)), err
case codes.Uint64, codes.Int64:
case msgpcode.Uint64, msgpcode.Int64:
n, err := d.uint64()
return int64(n), err
}
@ -170,8 +170,8 @@ func (d *Decoder) DecodeFloat32() (float32, error) {
return d.float32(c)
}
func (d *Decoder) float32(c codes.Code) (float32, error) {
if c == codes.Float {
func (d *Decoder) float32(c byte) (float32, error) {
if c == msgpcode.Float {
n, err := d.uint32()
if err != nil {
return 0, err
@ -195,15 +195,15 @@ func (d *Decoder) DecodeFloat64() (float64, error) {
return d.float64(c)
}
func (d *Decoder) float64(c codes.Code) (float64, error) {
func (d *Decoder) float64(c byte) (float64, error) {
switch c {
case codes.Float:
case msgpcode.Float:
n, err := d.float32(c)
if err != nil {
return 0, err
}
return float64(n), nil
case codes.Double:
case msgpcode.Double:
n, err := d.uint64()
if err != nil {
return 0, err
@ -263,9 +263,6 @@ func decodeFloat32Value(d *Decoder, v reflect.Value) error {
if err != nil {
return err
}
if err = mustSet(v); err != nil {
return err
}
v.SetFloat(float64(f))
return nil
}
@ -275,9 +272,6 @@ func decodeFloat64Value(d *Decoder, v reflect.Value) error {
if err != nil {
return err
}
if err = mustSet(v); err != nil {
return err
}
v.SetFloat(f)
return nil
}
@ -287,9 +281,6 @@ func decodeInt64Value(d *Decoder, v reflect.Value) error {
if err != nil {
return err
}
if err = mustSet(v); err != nil {
return err
}
v.SetInt(n)
return nil
}
@ -299,9 +290,6 @@ func decodeUint64Value(d *Decoder, v reflect.Value) error {
if err != nil {
return err
}
if err = mustSet(v); err != nil {
return err
}
v.SetUint(n)
return nil
}

View File

@ -5,7 +5,7 @@ import (
"strconv"
"strings"
"github.com/vmihailenco/msgpack/v4/codes"
"github.com/vmihailenco/msgpack/v5/msgpcode"
)
type queryResult struct {
@ -57,9 +57,9 @@ func (d *Decoder) query(q *queryResult) error {
}
switch {
case code == codes.Map16 || code == codes.Map32 || codes.IsFixedMap(code):
case code == msgpcode.Map16 || code == msgpcode.Map32 || msgpcode.IsFixedMap(code):
err = d.queryMapKey(q)
case code == codes.Array16 || code == codes.Array32 || codes.IsFixedArray(code):
case code == msgpcode.Array16 || code == msgpcode.Array32 || msgpcode.IsFixedArray(code):
err = d.queryArrayIndex(q)
default:
err = fmt.Errorf("msgpack: unsupported code=%x decoding key=%q", code, q.key)
@ -77,12 +77,12 @@ func (d *Decoder) queryMapKey(q *queryResult) error {
}
for i := 0; i < n; i++ {
k, err := d.bytesNoCopy()
key, err := d.decodeStringTemp()
if err != nil {
return err
}
if string(k) == q.key {
if key == q.key {
if err := d.query(q); err != nil {
return err
}

View File

@ -4,7 +4,7 @@ import (
"fmt"
"reflect"
"github.com/vmihailenco/msgpack/v4/codes"
"github.com/vmihailenco/msgpack/v5/msgpcode"
)
var sliceStringPtrType = reflect.TypeOf((*[]string)(nil))
@ -18,17 +18,17 @@ func (d *Decoder) DecodeArrayLen() (int, error) {
return d.arrayLen(c)
}
func (d *Decoder) arrayLen(c codes.Code) (int, error) {
if c == codes.Nil {
func (d *Decoder) arrayLen(c byte) (int, error) {
if c == msgpcode.Nil {
return -1, nil
} else if c >= codes.FixedArrayLow && c <= codes.FixedArrayHigh {
return int(c & codes.FixedArrayMask), nil
} else if c >= msgpcode.FixedArrayLow && c <= msgpcode.FixedArrayHigh {
return int(c & msgpcode.FixedArrayMask), nil
}
switch c {
case codes.Array16:
case msgpcode.Array16:
n, err := d.uint16()
return int(n), err
case codes.Array32:
case msgpcode.Array32:
n, err := d.uint32()
return int(n), err
}
@ -154,7 +154,7 @@ func (d *Decoder) DecodeSlice() ([]interface{}, error) {
return d.decodeSlice(c)
}
func (d *Decoder) decodeSlice(c codes.Code) ([]interface{}, error) {
func (d *Decoder) decodeSlice(c byte) ([]interface{}, error) {
n, err := d.arrayLen(c)
if err != nil {
return nil, err
@ -175,7 +175,7 @@ func (d *Decoder) decodeSlice(c codes.Code) ([]interface{}, error) {
return s, nil
}
func (d *Decoder) skipSlice(c codes.Code) error {
func (d *Decoder) skipSlice(c byte) error {
n, err := d.arrayLen(c)
if err != nil {
return err

View File

@ -4,34 +4,38 @@ import (
"fmt"
"reflect"
"github.com/vmihailenco/msgpack/v4/codes"
"github.com/vmihailenco/msgpack/v5/msgpcode"
)
func (d *Decoder) bytesLen(c codes.Code) (int, error) {
if c == codes.Nil {
func (d *Decoder) bytesLen(c byte) (int, error) {
if c == msgpcode.Nil {
return -1, nil
}
if codes.IsFixedString(c) {
return int(c & codes.FixedStrMask), nil
if msgpcode.IsFixedString(c) {
return int(c & msgpcode.FixedStrMask), nil
}
switch c {
case codes.Str8, codes.Bin8:
case msgpcode.Str8, msgpcode.Bin8:
n, err := d.uint8()
return int(n), err
case codes.Str16, codes.Bin16:
case msgpcode.Str16, msgpcode.Bin16:
n, err := d.uint16()
return int(n), err
case codes.Str32, codes.Bin32:
case msgpcode.Str32, msgpcode.Bin32:
n, err := d.uint32()
return int(n), err
}
return 0, fmt.Errorf("msgpack: invalid code=%x decoding bytes length", c)
return 0, fmt.Errorf("msgpack: invalid code=%x decoding string/bytes length", c)
}
func (d *Decoder) DecodeString() (string, error) {
if intern := d.flags&useInternedStringsFlag != 0; intern || len(d.dict) > 0 {
return d.decodeInternedString(intern)
}
c, err := d.readCode()
if err != nil {
return "", err
@ -39,7 +43,7 @@ func (d *Decoder) DecodeString() (string, error) {
return d.string(c)
}
func (d *Decoder) string(c codes.Code) (string, error) {
func (d *Decoder) string(c byte) (string, error) {
n, err := d.bytesLen(c)
if err != nil {
return "", err
@ -56,15 +60,10 @@ func (d *Decoder) stringWithLen(n int) (string, error) {
}
func decodeStringValue(d *Decoder, v reflect.Value) error {
if err := mustSet(v); err != nil {
return err
}
s, err := d.DecodeString()
if err != nil {
return err
}
v.SetString(s)
return nil
}
@ -85,7 +84,7 @@ func (d *Decoder) DecodeBytes() ([]byte, error) {
return d.bytes(c, nil)
}
func (d *Decoder) bytes(c codes.Code, b []byte) ([]byte, error) {
func (d *Decoder) bytes(c byte, b []byte) ([]byte, error) {
n, err := d.bytesLen(c)
if err != nil {
return nil, err
@ -96,19 +95,30 @@ func (d *Decoder) bytes(c codes.Code, b []byte) ([]byte, error) {
return readN(d.r, b, n)
}
func (d *Decoder) bytesNoCopy() ([]byte, error) {
func (d *Decoder) decodeStringTemp() (string, error) {
if intern := d.flags&useInternedStringsFlag != 0; intern || len(d.dict) > 0 {
return d.decodeInternedString(intern)
}
c, err := d.readCode()
if err != nil {
return nil, err
return "", err
}
n, err := d.bytesLen(c)
if err != nil {
return nil, err
return "", err
}
if n == -1 {
return nil, nil
return "", nil
}
return d.readN(n)
b, err := d.readN(n)
if err != nil {
return "", err
}
return bytesToString(b), nil
}
func (d *Decoder) decodeBytesPtr(ptr *[]byte) error {
@ -119,7 +129,7 @@ func (d *Decoder) decodeBytesPtr(ptr *[]byte) error {
return d.bytesPtr(c, ptr)
}
func (d *Decoder) bytesPtr(c codes.Code, ptr *[]byte) error {
func (d *Decoder) bytesPtr(c byte, ptr *[]byte) error {
n, err := d.bytesLen(c)
if err != nil {
return err
@ -133,7 +143,7 @@ func (d *Decoder) bytesPtr(c codes.Code, ptr *[]byte) error {
return err
}
func (d *Decoder) skipBytes(c codes.Code) error {
func (d *Decoder) skipBytes(c byte) error {
n, err := d.bytesLen(c)
if err != nil {
return err
@ -145,10 +155,6 @@ func (d *Decoder) skipBytes(c codes.Code) error {
}
func decodeBytesValue(d *Decoder, v reflect.Value) error {
if err := mustSet(v); err != nil {
return err
}
c, err := d.readCode()
if err != nil {
return err

View File

@ -7,8 +7,10 @@ import (
"reflect"
)
var interfaceType = reflect.TypeOf((*interface{})(nil)).Elem()
var stringType = reflect.TypeOf((*string)(nil)).Elem()
var (
interfaceType = reflect.TypeOf((*interface{})(nil)).Elem()
stringType = reflect.TypeOf((*string)(nil)).Elem()
)
var valueDecoders []decoderFunc
@ -43,13 +45,6 @@ func init() {
}
}
func mustSet(v reflect.Value) error {
if !v.CanSet() {
return fmt.Errorf("msgpack: Decode(nonsettable %s)", v.Type())
}
return nil
}
func getDecoder(typ reflect.Type) decoderFunc {
if v, ok := typeDecMap.Load(typ); ok {
return v.(decoderFunc)
@ -62,33 +57,45 @@ func getDecoder(typ reflect.Type) decoderFunc {
func _getDecoder(typ reflect.Type) decoderFunc {
kind := typ.Kind()
if kind == reflect.Ptr {
if _, ok := typeDecMap.Load(typ.Elem()); ok {
return ptrValueDecoder(typ)
}
}
if typ.Implements(customDecoderType) {
return decodeCustomValue
return nilAwareDecoder(typ, decodeCustomValue)
}
if typ.Implements(unmarshalerType) {
return unmarshalValue
return nilAwareDecoder(typ, unmarshalValue)
}
if typ.Implements(binaryUnmarshalerType) {
return unmarshalBinaryValue
return nilAwareDecoder(typ, unmarshalBinaryValue)
}
if typ.Implements(textUnmarshalerType) {
return nilAwareDecoder(typ, unmarshalTextValue)
}
// Addressable struct field value.
if kind != reflect.Ptr {
ptr := reflect.PtrTo(typ)
if ptr.Implements(customDecoderType) {
return decodeCustomValueAddr
return addrDecoder(nilAwareDecoder(typ, decodeCustomValue))
}
if ptr.Implements(unmarshalerType) {
return unmarshalValueAddr
return addrDecoder(nilAwareDecoder(typ, unmarshalValue))
}
if ptr.Implements(binaryUnmarshalerType) {
return unmarshalBinaryValueAddr
return addrDecoder(nilAwareDecoder(typ, unmarshalBinaryValue))
}
if ptr.Implements(textUnmarshalerType) {
return addrDecoder(nilAwareDecoder(typ, unmarshalTextValue))
}
}
switch kind {
case reflect.Ptr:
return ptrDecoderFunc(typ)
return ptrValueDecoder(typ)
case reflect.Slice:
elem := typ.Elem()
if elem.Kind() == reflect.Uint8 {
@ -115,85 +122,50 @@ func _getDecoder(typ reflect.Type) decoderFunc {
return valueDecoders[kind]
}
func ptrDecoderFunc(typ reflect.Type) decoderFunc {
func ptrValueDecoder(typ reflect.Type) decoderFunc {
decoder := getDecoder(typ.Elem())
return func(d *Decoder, v reflect.Value) error {
if d.hasNilCode() {
if err := mustSet(v); err != nil {
return err
}
if !v.IsNil() {
v.Set(reflect.Zero(v.Type()))
}
return d.DecodeNil()
}
if v.IsNil() {
if err := mustSet(v); err != nil {
return err
}
v.Set(reflect.New(v.Type().Elem()))
}
return decoder(d, v.Elem())
}
}
func decodeCustomValueAddr(d *Decoder, v reflect.Value) error {
if !v.CanAddr() {
return fmt.Errorf("msgpack: Decode(nonaddressable %T)", v.Interface())
func addrDecoder(fn decoderFunc) decoderFunc {
return func(d *Decoder, v reflect.Value) error {
if !v.CanAddr() {
return fmt.Errorf("msgpack: Decode(nonaddressable %T)", v.Interface())
}
return fn(d, v.Addr())
}
return decodeCustomValue(d, v.Addr())
}
func decodeCustomValue(d *Decoder, v reflect.Value) error {
if d.hasNilCode() {
return d.decodeNilValue(v)
func nilAwareDecoder(typ reflect.Type, fn decoderFunc) decoderFunc {
if nilable(typ.Kind()) {
return func(d *Decoder, v reflect.Value) error {
if d.hasNilCode() {
return d.decodeNilValue(v)
}
if v.IsNil() {
v.Set(reflect.New(v.Type().Elem()))
}
return fn(d, v)
}
}
if v.IsNil() {
v.Set(reflect.New(v.Type().Elem()))
}
decoder := v.Interface().(CustomDecoder)
return decoder.DecodeMsgpack(d)
}
func unmarshalValueAddr(d *Decoder, v reflect.Value) error {
if !v.CanAddr() {
return fmt.Errorf("msgpack: Decode(nonaddressable %T)", v.Interface())
}
return unmarshalValue(d, v.Addr())
}
func unmarshalValue(d *Decoder, v reflect.Value) error {
if d.extLen == 0 || d.extLen == 1 {
return func(d *Decoder, v reflect.Value) error {
if d.hasNilCode() {
return d.decodeNilValue(v)
}
return fn(d, v)
}
if v.IsNil() {
v.Set(reflect.New(v.Type().Elem()))
}
var b []byte
if d.extLen != 0 {
var err error
b, err = d.readN(d.extLen)
if err != nil {
return err
}
} else {
d.rec = make([]byte, 0, 64)
if err := d.Skip(); err != nil {
return err
}
b = d.rec
d.rec = nil
}
unmarshaler := v.Interface().(Unmarshaler)
return unmarshaler.UnmarshalMsgpack(b)
}
func decodeBoolValue(d *Decoder, v reflect.Value) error {
@ -201,9 +173,6 @@ func decodeBoolValue(d *Decoder, v reflect.Value) error {
if err != nil {
return err
}
if err = mustSet(v); err != nil {
return err
}
v.SetBool(flag)
return nil
}
@ -212,16 +181,7 @@ func decodeInterfaceValue(d *Decoder, v reflect.Value) error {
if v.IsNil() {
return d.interfaceValue(v)
}
elem := v.Elem()
if !elem.CanAddr() {
if d.hasNilCode() {
v.Set(reflect.Zero(v.Type()))
return d.DecodeNil()
}
}
return d.DecodeValue(elem)
return d.DecodeValue(v.Elem())
}
func (d *Decoder) interfaceValue(v reflect.Value) error {
@ -250,22 +210,26 @@ func decodeUnsupportedValue(d *Decoder, v reflect.Value) error {
//------------------------------------------------------------------------------
func unmarshalBinaryValueAddr(d *Decoder, v reflect.Value) error {
if !v.CanAddr() {
return fmt.Errorf("msgpack: Decode(nonaddressable %T)", v.Interface())
func decodeCustomValue(d *Decoder, v reflect.Value) error {
decoder := v.Interface().(CustomDecoder)
return decoder.DecodeMsgpack(d)
}
func unmarshalValue(d *Decoder, v reflect.Value) error {
var b []byte
d.rec = make([]byte, 0, 64)
if err := d.Skip(); err != nil {
return err
}
return unmarshalBinaryValue(d, v.Addr())
b = d.rec
d.rec = nil
unmarshaler := v.Interface().(Unmarshaler)
return unmarshaler.UnmarshalMsgpack(b)
}
func unmarshalBinaryValue(d *Decoder, v reflect.Value) error {
if d.hasNilCode() {
return d.decodeNilValue(v)
}
if v.IsNil() {
v.Set(reflect.New(v.Type().Elem()))
}
data, err := d.DecodeBytes()
if err != nil {
return err
@ -274,3 +238,13 @@ func unmarshalBinaryValue(d *Decoder, v reflect.Value) error {
unmarshaler := v.Interface().(encoding.BinaryUnmarshaler)
return unmarshaler.UnmarshalBinary(data)
}
func unmarshalTextValue(d *Decoder, v reflect.Value) error {
data, err := d.DecodeBytes()
if err != nil {
return err
}
unmarshaler := v.Interface().(encoding.TextUnmarshaler)
return unmarshaler.UnmarshalText(data)
}

View File

@ -7,15 +7,16 @@ import (
"sync"
"time"
"github.com/vmihailenco/msgpack/v4/codes"
"github.com/vmihailenco/msgpack/v5/msgpcode"
)
const (
sortMapKeysFlag uint32 = 1 << iota
structAsArrayFlag
encodeUsingJSONFlag
arrayEncodedStructsFlag
useCompactIntsFlag
useCompactFloatsFlag
useInternedStringsFlag
omitEmptyFlag
)
type writer interface {
@ -25,23 +26,16 @@ type writer interface {
type byteWriter struct {
io.Writer
buf [1]byte
}
func newByteWriter(w io.Writer) *byteWriter {
bw := new(byteWriter)
bw.Reset(w)
return bw
func newByteWriter(w io.Writer) byteWriter {
return byteWriter{
Writer: w,
}
}
func (bw *byteWriter) Reset(w io.Writer) {
bw.Writer = w
}
func (bw *byteWriter) WriteByte(c byte) error {
bw.buf[0] = c
_, err := bw.Write(bw.buf[:])
func (bw byteWriter) WriteByte(c byte) error {
_, err := bw.Write([]byte{c})
return err
}
@ -53,9 +47,18 @@ var encPool = sync.Pool{
},
}
func GetEncoder() *Encoder {
return encPool.Get().(*Encoder)
}
func PutEncoder(enc *Encoder) {
enc.w = nil
encPool.Put(enc)
}
// Marshal returns the MessagePack encoding of v.
func Marshal(v interface{}) ([]byte, error) {
enc := encPool.Get().(*Encoder)
enc := GetEncoder()
var buf bytes.Buffer
enc.Reset(&buf)
@ -63,7 +66,7 @@ func Marshal(v interface{}) ([]byte, error) {
err := enc.Encode(v)
b := buf.Bytes()
encPool.Put(enc)
PutEncoder(enc)
if err != nil {
return nil, err
@ -74,49 +77,63 @@ func Marshal(v interface{}) ([]byte, error) {
type Encoder struct {
w writer
buf []byte
timeBuf []byte
bootstrap [9 + 12]byte
buf []byte
timeBuf []byte
intern map[string]int
dict map[string]int
flags uint32
flags uint32
structTag string
}
// NewEncoder returns a new encoder that writes to w.
func NewEncoder(w io.Writer) *Encoder {
e := new(Encoder)
e.buf = e.bootstrap[:9]
e.timeBuf = e.bootstrap[9 : 9+12]
e := &Encoder{
buf: make([]byte, 9),
}
e.Reset(w)
return e
}
// Writer returns the Encoder's writer.
func (e *Encoder) Writer() io.Writer {
return e.w
}
// Reset discards any buffered data, resets all state, and switches the writer to write to w.
func (e *Encoder) Reset(w io.Writer) {
e.ResetDict(w, nil)
}
// ResetDict is like Reset, but also resets the dict.
func (e *Encoder) ResetDict(w io.Writer, dict map[string]int) {
e.resetWriter(w)
e.flags = 0
e.structTag = ""
e.dict = dict
}
func (e *Encoder) WithDict(dict map[string]int, fn func(*Encoder) error) error {
oldDict := e.dict
e.dict = dict
err := fn(e)
e.dict = oldDict
return err
}
func (e *Encoder) resetWriter(w io.Writer) {
if bw, ok := w.(writer); ok {
e.w = bw
} else if bw, ok := e.w.(*byteWriter); ok {
bw.Reset(w)
} else {
e.w = newByteWriter(w)
}
for k := range e.intern {
delete(e.intern, k)
}
//TODO:
//e.sortMapKeys = false
//e.structAsArray = false
//e.useJSONTag = false
//e.useCompact = false
}
// SortMapKeys causes the Encoder to encode map keys in increasing order.
// SetSortMapKeys causes the Encoder to encode map keys in increasing order.
// Supported map types are:
// - map[string]string
// - map[string]interface{}
func (e *Encoder) SortMapKeys(on bool) *Encoder {
func (e *Encoder) SetSortMapKeys(on bool) *Encoder {
if on {
e.flags |= sortMapKeysFlag
} else {
@ -125,36 +142,38 @@ func (e *Encoder) SortMapKeys(on bool) *Encoder {
return e
}
// StructAsArray causes the Encoder to encode Go structs as msgpack arrays.
func (e *Encoder) StructAsArray(on bool) *Encoder {
if on {
e.flags |= structAsArrayFlag
} else {
e.flags &= ^structAsArrayFlag
}
return e
// SetCustomStructTag causes the Encoder to use a custom struct tag as
// fallback option if there is no msgpack tag.
func (e *Encoder) SetCustomStructTag(tag string) {
e.structTag = tag
}
// UseJSONTag causes the Encoder to use json struct tag as fallback option
// if there is no msgpack tag.
func (e *Encoder) UseJSONTag(on bool) *Encoder {
// SetOmitEmpty causes the Encoder to omit empty values by default.
func (e *Encoder) SetOmitEmpty(on bool) {
if on {
e.flags |= encodeUsingJSONFlag
e.flags |= omitEmptyFlag
} else {
e.flags &= ^encodeUsingJSONFlag
e.flags &= ^omitEmptyFlag
}
}
// UseArrayEncodedStructs causes the Encoder to encode Go structs as msgpack arrays.
func (e *Encoder) UseArrayEncodedStructs(on bool) {
if on {
e.flags |= arrayEncodedStructsFlag
} else {
e.flags &= ^arrayEncodedStructsFlag
}
return e
}
// UseCompactEncoding causes the Encoder to chose the most compact encoding.
// For example, it allows to encode small Go int64 as msgpack int8 saving 7 bytes.
func (e *Encoder) UseCompactEncoding(on bool) *Encoder {
func (e *Encoder) UseCompactInts(on bool) {
if on {
e.flags |= useCompactIntsFlag
} else {
e.flags &= ^useCompactIntsFlag
}
return e
}
// UseCompactFloats causes the Encoder to chose a compact integer encoding
@ -167,6 +186,15 @@ func (e *Encoder) UseCompactFloats(on bool) {
}
}
// UseInternedStrings causes the Encoder to intern strings.
func (e *Encoder) UseInternedStrings(on bool) {
if on {
e.flags |= useInternedStringsFlag
} else {
e.flags &= ^useInternedStringsFlag
}
}
func (e *Encoder) Encode(v interface{}) error {
switch v := v.(type) {
case nil:
@ -176,11 +204,11 @@ func (e *Encoder) Encode(v interface{}) error {
case []byte:
return e.EncodeBytes(v)
case int:
return e.encodeInt64Cond(int64(v))
return e.EncodeInt(int64(v))
case int64:
return e.encodeInt64Cond(v)
case uint:
return e.encodeUint64Cond(uint64(v))
return e.EncodeUint(uint64(v))
case uint64:
return e.encodeUint64Cond(v)
case bool:
@ -212,22 +240,22 @@ func (e *Encoder) EncodeValue(v reflect.Value) error {
}
func (e *Encoder) EncodeNil() error {
return e.writeCode(codes.Nil)
return e.writeCode(msgpcode.Nil)
}
func (e *Encoder) EncodeBool(value bool) error {
if value {
return e.writeCode(codes.True)
return e.writeCode(msgpcode.True)
}
return e.writeCode(codes.False)
return e.writeCode(msgpcode.False)
}
func (e *Encoder) EncodeDuration(d time.Duration) error {
return e.EncodeInt(int64(d))
}
func (e *Encoder) writeCode(c codes.Code) error {
return e.w.WriteByte(byte(c))
func (e *Encoder) writeCode(c byte) error {
return e.w.WriteByte(c)
}
func (e *Encoder) write(b []byte) error {

View File

@ -1,10 +1,11 @@
package msgpack
import (
"math"
"reflect"
"sort"
"github.com/vmihailenco/msgpack/v4/codes"
"github.com/vmihailenco/msgpack/v5/msgpcode"
)
func encodeMapValue(e *Encoder, v reflect.Value) error {
@ -16,11 +17,12 @@ func encodeMapValue(e *Encoder, v reflect.Value) error {
return err
}
for _, key := range v.MapKeys() {
if err := e.EncodeValue(key); err != nil {
iter := v.MapRange()
for iter.Next() {
if err := e.EncodeValue(iter.Key()); err != nil {
return err
}
if err := e.EncodeValue(v.MapIndex(key)); err != nil {
if err := e.EncodeValue(iter.Value()); err != nil {
return err
}
}
@ -58,16 +60,20 @@ func encodeMapStringInterfaceValue(e *Encoder, v reflect.Value) error {
if v.IsNil() {
return e.EncodeNil()
}
if err := e.EncodeMapLen(v.Len()); err != nil {
return err
}
m := v.Convert(mapStringInterfaceType).Interface().(map[string]interface{})
if e.flags&sortMapKeysFlag != 0 {
return e.encodeSortedMapStringInterface(m)
return e.EncodeMapSorted(m)
}
return e.EncodeMap(m)
}
func (e *Encoder) EncodeMap(m map[string]interface{}) error {
if m == nil {
return e.EncodeNil()
}
if err := e.EncodeMapLen(len(m)); err != nil {
return err
}
for mk, mv := range m {
if err := e.EncodeString(mk); err != nil {
return err
@ -76,6 +82,33 @@ func encodeMapStringInterfaceValue(e *Encoder, v reflect.Value) error {
return err
}
}
return nil
}
func (e *Encoder) EncodeMapSorted(m map[string]interface{}) error {
if m == nil {
return e.EncodeNil()
}
if err := e.EncodeMapLen(len(m)); err != nil {
return err
}
keys := make([]string, 0, len(m))
for k := range m {
keys = append(keys, k)
}
sort.Strings(keys)
for _, k := range keys {
if err := e.EncodeString(k); err != nil {
return err
}
if err := e.Encode(m[k]); err != nil {
return err
}
}
return nil
}
@ -100,48 +133,22 @@ func (e *Encoder) encodeSortedMapStringString(m map[string]string) error {
return nil
}
func (e *Encoder) encodeSortedMapStringInterface(m map[string]interface{}) error {
keys := make([]string, 0, len(m))
for k := range m {
keys = append(keys, k)
}
sort.Strings(keys)
for _, k := range keys {
err := e.EncodeString(k)
if err != nil {
return err
}
if err = e.Encode(m[k]); err != nil {
return err
}
}
return nil
}
func (e *Encoder) EncodeMapLen(l int) error {
if l < 16 {
return e.writeCode(codes.FixedMapLow | codes.Code(l))
return e.writeCode(msgpcode.FixedMapLow | byte(l))
}
if l < 65536 {
return e.write2(codes.Map16, uint16(l))
if l <= math.MaxUint16 {
return e.write2(msgpcode.Map16, uint16(l))
}
return e.write4(codes.Map32, uint32(l))
return e.write4(msgpcode.Map32, uint32(l))
}
func encodeStructValue(e *Encoder, strct reflect.Value) error {
var structFields *fields
if e.flags&encodeUsingJSONFlag != 0 {
structFields = jsonStructs.Fields(strct.Type())
} else {
structFields = structs.Fields(strct.Type())
}
if e.flags&structAsArrayFlag != 0 || structFields.AsArray {
structFields := structs.Fields(strct.Type(), e.structTag)
if e.flags&arrayEncodedStructsFlag != 0 || structFields.AsArray {
return encodeStructValueAsArray(e, strct, structFields.List)
}
fields := structFields.OmitEmpty(strct)
fields := structFields.OmitEmpty(strct, e.flags&omitEmptyFlag != 0)
if err := e.EncodeMapLen(len(fields)); err != nil {
return err

View File

@ -4,12 +4,12 @@ import (
"math"
"reflect"
"github.com/vmihailenco/msgpack/v4/codes"
"github.com/vmihailenco/msgpack/v5/msgpcode"
)
// EncodeUint8 encodes an uint8 in 2 bytes preserving type of the number.
func (e *Encoder) EncodeUint8(n uint8) error {
return e.write1(codes.Uint8, n)
return e.write1(msgpcode.Uint8, n)
}
func (e *Encoder) encodeUint8Cond(n uint8) error {
@ -21,7 +21,7 @@ func (e *Encoder) encodeUint8Cond(n uint8) error {
// EncodeUint16 encodes an uint16 in 3 bytes preserving type of the number.
func (e *Encoder) EncodeUint16(n uint16) error {
return e.write2(codes.Uint16, n)
return e.write2(msgpcode.Uint16, n)
}
func (e *Encoder) encodeUint16Cond(n uint16) error {
@ -33,7 +33,7 @@ func (e *Encoder) encodeUint16Cond(n uint16) error {
// EncodeUint32 encodes an uint16 in 5 bytes preserving type of the number.
func (e *Encoder) EncodeUint32(n uint32) error {
return e.write4(codes.Uint32, n)
return e.write4(msgpcode.Uint32, n)
}
func (e *Encoder) encodeUint32Cond(n uint32) error {
@ -45,7 +45,7 @@ func (e *Encoder) encodeUint32Cond(n uint32) error {
// EncodeUint64 encodes an uint16 in 9 bytes preserving type of the number.
func (e *Encoder) EncodeUint64(n uint64) error {
return e.write8(codes.Uint64, n)
return e.write8(msgpcode.Uint64, n)
}
func (e *Encoder) encodeUint64Cond(n uint64) error {
@ -57,7 +57,7 @@ func (e *Encoder) encodeUint64Cond(n uint64) error {
// EncodeInt8 encodes an int8 in 2 bytes preserving type of the number.
func (e *Encoder) EncodeInt8(n int8) error {
return e.write1(codes.Int8, uint8(n))
return e.write1(msgpcode.Int8, uint8(n))
}
func (e *Encoder) encodeInt8Cond(n int8) error {
@ -69,7 +69,7 @@ func (e *Encoder) encodeInt8Cond(n int8) error {
// EncodeInt16 encodes an int16 in 3 bytes preserving type of the number.
func (e *Encoder) EncodeInt16(n int16) error {
return e.write2(codes.Int16, uint16(n))
return e.write2(msgpcode.Int16, uint16(n))
}
func (e *Encoder) encodeInt16Cond(n int16) error {
@ -81,7 +81,7 @@ func (e *Encoder) encodeInt16Cond(n int16) error {
// EncodeInt32 encodes an int32 in 5 bytes preserving type of the number.
func (e *Encoder) EncodeInt32(n int32) error {
return e.write4(codes.Int32, uint32(n))
return e.write4(msgpcode.Int32, uint32(n))
}
func (e *Encoder) encodeInt32Cond(n int32) error {
@ -93,7 +93,7 @@ func (e *Encoder) encodeInt32Cond(n int32) error {
// EncodeInt64 encodes an int64 in 9 bytes preserving type of the number.
func (e *Encoder) EncodeInt64(n int64) error {
return e.write8(codes.Int64, uint64(n))
return e.write8(msgpcode.Int64, uint64(n))
}
func (e *Encoder) encodeInt64Cond(n int64) error {
@ -127,7 +127,7 @@ func (e *Encoder) EncodeInt(n int64) error {
if n >= 0 {
return e.EncodeUint(uint64(n))
}
if n >= int64(int8(codes.NegFixedNumLow)) {
if n >= int64(int8(msgpcode.NegFixedNumLow)) {
return e.w.WriteByte(byte(n))
}
if n >= math.MinInt8 {
@ -148,7 +148,7 @@ func (e *Encoder) EncodeFloat32(n float32) error {
return e.EncodeInt(int64(n))
}
}
return e.write4(codes.Float, math.Float32bits(n))
return e.write4(msgpcode.Float, math.Float32bits(n))
}
func (e *Encoder) EncodeFloat64(n float64) error {
@ -161,27 +161,27 @@ func (e *Encoder) EncodeFloat64(n float64) error {
return e.EncodeInt(int64(n))
}
}
return e.write8(codes.Double, math.Float64bits(n))
return e.write8(msgpcode.Double, math.Float64bits(n))
}
func (e *Encoder) write1(code codes.Code, n uint8) error {
func (e *Encoder) write1(code byte, n uint8) error {
e.buf = e.buf[:2]
e.buf[0] = byte(code)
e.buf[0] = code
e.buf[1] = n
return e.write(e.buf)
}
func (e *Encoder) write2(code codes.Code, n uint16) error {
func (e *Encoder) write2(code byte, n uint16) error {
e.buf = e.buf[:3]
e.buf[0] = byte(code)
e.buf[0] = code
e.buf[1] = byte(n >> 8)
e.buf[2] = byte(n)
return e.write(e.buf)
}
func (e *Encoder) write4(code codes.Code, n uint32) error {
func (e *Encoder) write4(code byte, n uint32) error {
e.buf = e.buf[:5]
e.buf[0] = byte(code)
e.buf[0] = code
e.buf[1] = byte(n >> 24)
e.buf[2] = byte(n >> 16)
e.buf[3] = byte(n >> 8)
@ -189,9 +189,9 @@ func (e *Encoder) write4(code codes.Code, n uint32) error {
return e.write(e.buf)
}
func (e *Encoder) write8(code codes.Code, n uint64) error {
func (e *Encoder) write8(code byte, n uint64) error {
e.buf = e.buf[:9]
e.buf[0] = byte(code)
e.buf[0] = code
e.buf[1] = byte(n >> 56)
e.buf[2] = byte(n >> 48)
e.buf[3] = byte(n >> 40)
@ -203,6 +203,14 @@ func (e *Encoder) write8(code codes.Code, n uint64) error {
return e.write(e.buf)
}
func encodeUintValue(e *Encoder, v reflect.Value) error {
return e.EncodeUint(v.Uint())
}
func encodeIntValue(e *Encoder, v reflect.Value) error {
return e.EncodeInt(v.Int())
}
func encodeUint8CondValue(e *Encoder, v reflect.Value) error {
return e.encodeUint8Cond(uint8(v.Uint()))
}

View File

@ -1,12 +1,13 @@
package msgpack
import (
"math"
"reflect"
"github.com/vmihailenco/msgpack/v4/codes"
"github.com/vmihailenco/msgpack/v5/msgpcode"
)
var sliceStringType = reflect.TypeOf(([]string)(nil))
var stringSliceType = reflect.TypeOf(([]string)(nil))
func encodeStringValue(e *Encoder, v reflect.Value) error {
return e.EncodeString(v.String())
@ -42,29 +43,36 @@ func grow(b []byte, n int) []byte {
func (e *Encoder) EncodeBytesLen(l int) error {
if l < 256 {
return e.write1(codes.Bin8, uint8(l))
return e.write1(msgpcode.Bin8, uint8(l))
}
if l < 65536 {
return e.write2(codes.Bin16, uint16(l))
if l <= math.MaxUint16 {
return e.write2(msgpcode.Bin16, uint16(l))
}
return e.write4(codes.Bin32, uint32(l))
return e.write4(msgpcode.Bin32, uint32(l))
}
func (e *Encoder) encodeStrLen(l int) error {
func (e *Encoder) encodeStringLen(l int) error {
if l < 32 {
return e.writeCode(codes.FixedStrLow | codes.Code(l))
return e.writeCode(msgpcode.FixedStrLow | byte(l))
}
if l < 256 {
return e.write1(codes.Str8, uint8(l))
return e.write1(msgpcode.Str8, uint8(l))
}
if l < 65536 {
return e.write2(codes.Str16, uint16(l))
if l <= math.MaxUint16 {
return e.write2(msgpcode.Str16, uint16(l))
}
return e.write4(codes.Str32, uint32(l))
return e.write4(msgpcode.Str32, uint32(l))
}
func (e *Encoder) EncodeString(v string) error {
if err := e.encodeStrLen(len(v)); err != nil {
if intern := e.flags&useInternedStringsFlag != 0; intern || len(e.dict) > 0 {
return e.encodeInternedString(v, intern)
}
return e.encodeNormalString(v)
}
func (e *Encoder) encodeNormalString(v string) error {
if err := e.encodeStringLen(len(v)); err != nil {
return err
}
return e.writeString(v)
@ -82,16 +90,16 @@ func (e *Encoder) EncodeBytes(v []byte) error {
func (e *Encoder) EncodeArrayLen(l int) error {
if l < 16 {
return e.writeCode(codes.FixedArrayLow | codes.Code(l))
return e.writeCode(msgpcode.FixedArrayLow | byte(l))
}
if l < 65536 {
return e.write2(codes.Array16, uint16(l))
if l <= math.MaxUint16 {
return e.write2(msgpcode.Array16, uint16(l))
}
return e.write4(codes.Array32, uint32(l))
return e.write4(msgpcode.Array32, uint32(l))
}
func encodeStringSliceValue(e *Encoder, v reflect.Value) error {
ss := v.Convert(sliceStringType).Interface().([]string)
ss := v.Convert(stringSliceType).Interface().([]string)
return e.encodeStringSlice(ss)
}

View File

@ -12,12 +12,12 @@ var valueEncoders []encoderFunc
func init() {
valueEncoders = []encoderFunc{
reflect.Bool: encodeBoolValue,
reflect.Int: encodeInt64CondValue,
reflect.Int: encodeIntValue,
reflect.Int8: encodeInt8CondValue,
reflect.Int16: encodeInt16CondValue,
reflect.Int32: encodeInt32CondValue,
reflect.Int64: encodeInt64CondValue,
reflect.Uint: encodeUint64CondValue,
reflect.Uint: encodeUintValue,
reflect.Uint8: encodeUint8CondValue,
reflect.Uint16: encodeUint16CondValue,
reflect.Uint32: encodeUint32CondValue,
@ -66,6 +66,9 @@ func _getEncoder(typ reflect.Type) encoderFunc {
if typ.Implements(binaryMarshalerType) {
return marshalBinaryValue
}
if typ.Implements(textMarshalerType) {
return marshalTextValue
}
// Addressable struct field value.
if kind != reflect.Ptr {
@ -77,7 +80,10 @@ func _getEncoder(typ reflect.Type) encoderFunc {
return marshalValuePtr
}
if ptr.Implements(binaryMarshalerType) {
return marshalBinaryValuePtr
return marshalBinaryValueAddr
}
if ptr.Implements(textMarshalerType) {
return marshalTextValueAddr
}
}
@ -133,7 +139,7 @@ func encodeCustomValuePtr(e *Encoder, v reflect.Value) error {
}
func encodeCustomValue(e *Encoder, v reflect.Value) error {
if nilable(v) && v.IsNil() {
if nilable(v.Kind()) && v.IsNil() {
return e.EncodeNil()
}
@ -149,7 +155,7 @@ func marshalValuePtr(e *Encoder, v reflect.Value) error {
}
func marshalValue(e *Encoder, v reflect.Value) error {
if nilable(v) && v.IsNil() {
if nilable(v.Kind()) && v.IsNil() {
return e.EncodeNil()
}
@ -184,8 +190,8 @@ func encodeUnsupportedValue(e *Encoder, v reflect.Value) error {
return fmt.Errorf("msgpack: Encode(unsupported %s)", v.Type())
}
func nilable(v reflect.Value) bool {
switch v.Kind() {
func nilable(kind reflect.Kind) bool {
switch kind {
case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
return true
}
@ -194,7 +200,7 @@ func nilable(v reflect.Value) bool {
//------------------------------------------------------------------------------
func marshalBinaryValuePtr(e *Encoder, v reflect.Value) error {
func marshalBinaryValueAddr(e *Encoder, v reflect.Value) error {
if !v.CanAddr() {
return fmt.Errorf("msgpack: Encode(non-addressable %T)", v.Interface())
}
@ -202,7 +208,7 @@ func marshalBinaryValuePtr(e *Encoder, v reflect.Value) error {
}
func marshalBinaryValue(e *Encoder, v reflect.Value) error {
if nilable(v) && v.IsNil() {
if nilable(v.Kind()) && v.IsNil() {
return e.EncodeNil()
}
@ -214,3 +220,26 @@ func marshalBinaryValue(e *Encoder, v reflect.Value) error {
return e.EncodeBytes(data)
}
//------------------------------------------------------------------------------
func marshalTextValueAddr(e *Encoder, v reflect.Value) error {
if !v.CanAddr() {
return fmt.Errorf("msgpack: Encode(non-addressable %T)", v.Interface())
}
return marshalTextValue(e, v.Addr())
}
func marshalTextValue(e *Encoder, v reflect.Value) error {
if nilable(v.Kind()) && v.IsNil() {
return e.EncodeNil()
}
marshaler := v.Interface().(encoding.TextMarshaler)
data, err := marshaler.MarshalText()
if err != nil {
return err
}
return e.EncodeBytes(data)
}

303
vendor/github.com/vmihailenco/msgpack/v5/ext.go generated vendored Normal file
View File

@ -0,0 +1,303 @@
package msgpack
import (
"fmt"
"math"
"reflect"
"github.com/vmihailenco/msgpack/v5/msgpcode"
)
type extInfo struct {
Type reflect.Type
Decoder func(d *Decoder, v reflect.Value, extLen int) error
}
var extTypes = make(map[int8]*extInfo)
type MarshalerUnmarshaler interface {
Marshaler
Unmarshaler
}
func RegisterExt(extID int8, value MarshalerUnmarshaler) {
RegisterExtEncoder(extID, value, func(e *Encoder, v reflect.Value) ([]byte, error) {
marshaler := v.Interface().(Marshaler)
return marshaler.MarshalMsgpack()
})
RegisterExtDecoder(extID, value, func(d *Decoder, v reflect.Value, extLen int) error {
b, err := d.readN(extLen)
if err != nil {
return err
}
return v.Interface().(Unmarshaler).UnmarshalMsgpack(b)
})
}
func UnregisterExt(extID int8) {
unregisterExtEncoder(extID)
unregisterExtDecoder(extID)
}
func RegisterExtEncoder(
extID int8,
value interface{},
encoder func(enc *Encoder, v reflect.Value) ([]byte, error),
) {
unregisterExtEncoder(extID)
typ := reflect.TypeOf(value)
extEncoder := makeExtEncoder(extID, typ, encoder)
typeEncMap.Store(extID, typ)
typeEncMap.Store(typ, extEncoder)
if typ.Kind() == reflect.Ptr {
typeEncMap.Store(typ.Elem(), makeExtEncoderAddr(extEncoder))
}
}
func unregisterExtEncoder(extID int8) {
t, ok := typeEncMap.Load(extID)
if !ok {
return
}
typeEncMap.Delete(extID)
typ := t.(reflect.Type)
typeEncMap.Delete(typ)
if typ.Kind() == reflect.Ptr {
typeEncMap.Delete(typ.Elem())
}
}
func makeExtEncoder(
extID int8,
typ reflect.Type,
encoder func(enc *Encoder, v reflect.Value) ([]byte, error),
) encoderFunc {
nilable := typ.Kind() == reflect.Ptr
return func(e *Encoder, v reflect.Value) error {
if nilable && v.IsNil() {
return e.EncodeNil()
}
b, err := encoder(e, v)
if err != nil {
return err
}
if err := e.EncodeExtHeader(extID, len(b)); err != nil {
return err
}
return e.write(b)
}
}
func makeExtEncoderAddr(extEncoder encoderFunc) encoderFunc {
return func(e *Encoder, v reflect.Value) error {
if !v.CanAddr() {
return fmt.Errorf("msgpack: Decode(nonaddressable %T)", v.Interface())
}
return extEncoder(e, v.Addr())
}
}
func RegisterExtDecoder(
extID int8,
value interface{},
decoder func(dec *Decoder, v reflect.Value, extLen int) error,
) {
unregisterExtDecoder(extID)
typ := reflect.TypeOf(value)
extDecoder := makeExtDecoder(extID, typ, decoder)
extTypes[extID] = &extInfo{
Type: typ,
Decoder: decoder,
}
typeDecMap.Store(extID, typ)
typeDecMap.Store(typ, extDecoder)
if typ.Kind() == reflect.Ptr {
typeDecMap.Store(typ.Elem(), makeExtDecoderAddr(extDecoder))
}
}
func unregisterExtDecoder(extID int8) {
t, ok := typeDecMap.Load(extID)
if !ok {
return
}
typeDecMap.Delete(extID)
delete(extTypes, extID)
typ := t.(reflect.Type)
typeDecMap.Delete(typ)
if typ.Kind() == reflect.Ptr {
typeDecMap.Delete(typ.Elem())
}
}
func makeExtDecoder(
wantedExtID int8,
typ reflect.Type,
decoder func(d *Decoder, v reflect.Value, extLen int) error,
) decoderFunc {
return nilAwareDecoder(typ, func(d *Decoder, v reflect.Value) error {
extID, extLen, err := d.DecodeExtHeader()
if err != nil {
return err
}
if extID != wantedExtID {
return fmt.Errorf("msgpack: got ext type=%d, wanted %d", extID, wantedExtID)
}
return decoder(d, v, extLen)
})
}
func makeExtDecoderAddr(extDecoder decoderFunc) decoderFunc {
return func(d *Decoder, v reflect.Value) error {
if !v.CanAddr() {
return fmt.Errorf("msgpack: Decode(nonaddressable %T)", v.Interface())
}
return extDecoder(d, v.Addr())
}
}
func (e *Encoder) EncodeExtHeader(extID int8, extLen int) error {
if err := e.encodeExtLen(extLen); err != nil {
return err
}
if err := e.w.WriteByte(byte(extID)); err != nil {
return err
}
return nil
}
func (e *Encoder) encodeExtLen(l int) error {
switch l {
case 1:
return e.writeCode(msgpcode.FixExt1)
case 2:
return e.writeCode(msgpcode.FixExt2)
case 4:
return e.writeCode(msgpcode.FixExt4)
case 8:
return e.writeCode(msgpcode.FixExt8)
case 16:
return e.writeCode(msgpcode.FixExt16)
}
if l <= math.MaxUint8 {
return e.write1(msgpcode.Ext8, uint8(l))
}
if l <= math.MaxUint16 {
return e.write2(msgpcode.Ext16, uint16(l))
}
return e.write4(msgpcode.Ext32, uint32(l))
}
func (d *Decoder) DecodeExtHeader() (extID int8, extLen int, err error) {
c, err := d.readCode()
if err != nil {
return
}
return d.extHeader(c)
}
func (d *Decoder) extHeader(c byte) (int8, int, error) {
extLen, err := d.parseExtLen(c)
if err != nil {
return 0, 0, err
}
extID, err := d.readCode()
if err != nil {
return 0, 0, err
}
return int8(extID), extLen, nil
}
func (d *Decoder) parseExtLen(c byte) (int, error) {
switch c {
case msgpcode.FixExt1:
return 1, nil
case msgpcode.FixExt2:
return 2, nil
case msgpcode.FixExt4:
return 4, nil
case msgpcode.FixExt8:
return 8, nil
case msgpcode.FixExt16:
return 16, nil
case msgpcode.Ext8:
n, err := d.uint8()
return int(n), err
case msgpcode.Ext16:
n, err := d.uint16()
return int(n), err
case msgpcode.Ext32:
n, err := d.uint32()
return int(n), err
default:
return 0, fmt.Errorf("msgpack: invalid code=%x decoding ext len", c)
}
}
func (d *Decoder) decodeInterfaceExt(c byte) (interface{}, error) {
extID, extLen, err := d.extHeader(c)
if err != nil {
return nil, err
}
info, ok := extTypes[extID]
if !ok {
return nil, fmt.Errorf("msgpack: unknown ext id=%d", extID)
}
v := reflect.New(info.Type).Elem()
if nilable(v.Kind()) && v.IsNil() {
v.Set(reflect.New(info.Type.Elem()))
}
if err := info.Decoder(d, v, extLen); err != nil {
return nil, err
}
return v.Interface(), nil
}
func (d *Decoder) skipExt(c byte) error {
n, err := d.parseExtLen(c)
if err != nil {
return err
}
return d.skipN(n + 1)
}
func (d *Decoder) skipExtHeader(c byte) error {
// Read ext type.
_, err := d.readCode()
if err != nil {
return err
}
// Read ext body len.
for i := 0; i < extHeaderLen(c); i++ {
_, err := d.readCode()
if err != nil {
return err
}
}
return nil
}
func extHeaderLen(c byte) int {
switch c {
case msgpcode.Ext8:
return 1
case msgpcode.Ext16:
return 2
case msgpcode.Ext32:
return 4
}
return 0
}

238
vendor/github.com/vmihailenco/msgpack/v5/intern.go generated vendored Normal file
View File

@ -0,0 +1,238 @@
package msgpack
import (
"fmt"
"math"
"reflect"
"github.com/vmihailenco/msgpack/v5/msgpcode"
)
const (
minInternedStringLen = 3
maxDictLen = math.MaxUint16
)
var internedStringExtID = int8(math.MinInt8)
func init() {
extTypes[internedStringExtID] = &extInfo{
Type: stringType,
Decoder: decodeInternedStringExt,
}
}
func decodeInternedStringExt(d *Decoder, v reflect.Value, extLen int) error {
idx, err := d.decodeInternedStringIndex(extLen)
if err != nil {
return err
}
s, err := d.internedStringAtIndex(idx)
if err != nil {
return err
}
v.SetString(s)
return nil
}
//------------------------------------------------------------------------------
func encodeInternedInterfaceValue(e *Encoder, v reflect.Value) error {
if v.IsNil() {
return e.EncodeNil()
}
v = v.Elem()
if v.Kind() == reflect.String {
return e.encodeInternedString(v.String(), true)
}
return e.EncodeValue(v)
}
func encodeInternedStringValue(e *Encoder, v reflect.Value) error {
return e.encodeInternedString(v.String(), true)
}
func (e *Encoder) encodeInternedString(s string, intern bool) error {
// Interned string takes at least 3 bytes. Plain string 1 byte + string len.
if len(s) >= minInternedStringLen {
if idx, ok := e.dict[s]; ok {
return e.encodeInternedStringIndex(idx)
}
if intern && len(e.dict) < maxDictLen {
if e.dict == nil {
e.dict = make(map[string]int)
}
idx := len(e.dict)
e.dict[s] = idx
}
}
return e.encodeNormalString(s)
}
func (e *Encoder) encodeInternedStringIndex(idx int) error {
if idx <= math.MaxUint8 {
if err := e.writeCode(msgpcode.FixExt1); err != nil {
return err
}
return e.write1(byte(internedStringExtID), uint8(idx))
}
if idx <= math.MaxUint16 {
if err := e.writeCode(msgpcode.FixExt2); err != nil {
return err
}
return e.write2(byte(internedStringExtID), uint16(idx))
}
if uint64(idx) <= math.MaxUint32 {
if err := e.writeCode(msgpcode.FixExt4); err != nil {
return err
}
return e.write4(byte(internedStringExtID), uint32(idx))
}
return fmt.Errorf("msgpack: interned string index=%d is too large", idx)
}
//------------------------------------------------------------------------------
func decodeInternedInterfaceValue(d *Decoder, v reflect.Value) error {
s, err := d.decodeInternedString(true)
if err == nil {
v.Set(reflect.ValueOf(s))
return nil
}
if err != nil {
if _, ok := err.(unexpectedCodeError); !ok {
return err
}
}
if err := d.s.UnreadByte(); err != nil {
return err
}
return decodeInterfaceValue(d, v)
}
func decodeInternedStringValue(d *Decoder, v reflect.Value) error {
s, err := d.decodeInternedString(true)
if err != nil {
return err
}
v.SetString(s)
return nil
}
func (d *Decoder) decodeInternedString(intern bool) (string, error) {
c, err := d.readCode()
if err != nil {
return "", err
}
if msgpcode.IsFixedString(c) {
n := int(c & msgpcode.FixedStrMask)
return d.decodeInternedStringWithLen(n, intern)
}
switch c {
case msgpcode.Nil:
return "", nil
case msgpcode.FixExt1, msgpcode.FixExt2, msgpcode.FixExt4:
typeID, extLen, err := d.extHeader(c)
if err != nil {
return "", err
}
if typeID != internedStringExtID {
err := fmt.Errorf("msgpack: got ext type=%d, wanted %d",
typeID, internedStringExtID)
return "", err
}
idx, err := d.decodeInternedStringIndex(extLen)
if err != nil {
return "", err
}
return d.internedStringAtIndex(idx)
case msgpcode.Str8, msgpcode.Bin8:
n, err := d.uint8()
if err != nil {
return "", err
}
return d.decodeInternedStringWithLen(int(n), intern)
case msgpcode.Str16, msgpcode.Bin16:
n, err := d.uint16()
if err != nil {
return "", err
}
return d.decodeInternedStringWithLen(int(n), intern)
case msgpcode.Str32, msgpcode.Bin32:
n, err := d.uint32()
if err != nil {
return "", err
}
return d.decodeInternedStringWithLen(int(n), intern)
}
return "", unexpectedCodeError{
code: c,
hint: "interned string",
}
}
func (d *Decoder) decodeInternedStringIndex(extLen int) (int, error) {
switch extLen {
case 1:
n, err := d.uint8()
if err != nil {
return 0, err
}
return int(n), nil
case 2:
n, err := d.uint16()
if err != nil {
return 0, err
}
return int(n), nil
case 4:
n, err := d.uint32()
if err != nil {
return 0, err
}
return int(n), nil
}
err := fmt.Errorf("msgpack: unsupported ext len=%d decoding interned string", extLen)
return 0, err
}
func (d *Decoder) internedStringAtIndex(idx int) (string, error) {
if idx >= len(d.dict) {
err := fmt.Errorf("msgpack: interned string at index=%d does not exist", idx)
return "", err
}
return d.dict[idx], nil
}
func (d *Decoder) decodeInternedStringWithLen(n int, intern bool) (string, error) {
if n <= 0 {
return "", nil
}
s, err := d.stringWithLen(n)
if err != nil {
return "", err
}
if intern && len(s) >= minInternedStringLen && len(d.dict) < maxDictLen {
d.dict = append(d.dict, s)
}
return s, nil
}

52
vendor/github.com/vmihailenco/msgpack/v5/msgpack.go generated vendored Normal file
View File

@ -0,0 +1,52 @@
package msgpack
import "fmt"
type Marshaler interface {
MarshalMsgpack() ([]byte, error)
}
type Unmarshaler interface {
UnmarshalMsgpack([]byte) error
}
type CustomEncoder interface {
EncodeMsgpack(*Encoder) error
}
type CustomDecoder interface {
DecodeMsgpack(*Decoder) error
}
//------------------------------------------------------------------------------
type RawMessage []byte
var (
_ CustomEncoder = (RawMessage)(nil)
_ CustomDecoder = (*RawMessage)(nil)
)
func (m RawMessage) EncodeMsgpack(enc *Encoder) error {
return enc.write(m)
}
func (m *RawMessage) DecodeMsgpack(dec *Decoder) error {
msg, err := dec.DecodeRaw()
if err != nil {
return err
}
*m = msg
return nil
}
//------------------------------------------------------------------------------
type unexpectedCodeError struct {
code byte
hint string
}
func (err unexpectedCodeError) Error() string {
return fmt.Sprintf("msgpack: unexpected code=%x decoding %s", err.code, err.hint)
}

View File

@ -0,0 +1,88 @@
package msgpcode
var (
PosFixedNumHigh byte = 0x7f
NegFixedNumLow byte = 0xe0
Nil byte = 0xc0
False byte = 0xc2
True byte = 0xc3
Float byte = 0xca
Double byte = 0xcb
Uint8 byte = 0xcc
Uint16 byte = 0xcd
Uint32 byte = 0xce
Uint64 byte = 0xcf
Int8 byte = 0xd0
Int16 byte = 0xd1
Int32 byte = 0xd2
Int64 byte = 0xd3
FixedStrLow byte = 0xa0
FixedStrHigh byte = 0xbf
FixedStrMask byte = 0x1f
Str8 byte = 0xd9
Str16 byte = 0xda
Str32 byte = 0xdb
Bin8 byte = 0xc4
Bin16 byte = 0xc5
Bin32 byte = 0xc6
FixedArrayLow byte = 0x90
FixedArrayHigh byte = 0x9f
FixedArrayMask byte = 0xf
Array16 byte = 0xdc
Array32 byte = 0xdd
FixedMapLow byte = 0x80
FixedMapHigh byte = 0x8f
FixedMapMask byte = 0xf
Map16 byte = 0xde
Map32 byte = 0xdf
FixExt1 byte = 0xd4
FixExt2 byte = 0xd5
FixExt4 byte = 0xd6
FixExt8 byte = 0xd7
FixExt16 byte = 0xd8
Ext8 byte = 0xc7
Ext16 byte = 0xc8
Ext32 byte = 0xc9
)
func IsFixedNum(c byte) bool {
return c <= PosFixedNumHigh || c >= NegFixedNumLow
}
func IsFixedMap(c byte) bool {
return c >= FixedMapLow && c <= FixedMapHigh
}
func IsFixedArray(c byte) bool {
return c >= FixedArrayLow && c <= FixedArrayHigh
}
func IsFixedString(c byte) bool {
return c >= FixedStrLow && c <= FixedStrHigh
}
func IsString(c byte) bool {
return IsFixedString(c) || c == Str8 || c == Str16 || c == Str32
}
func IsBin(c byte) bool {
return c == Bin8 || c == Bin16 || c == Bin32
}
func IsFixedExt(c byte) bool {
return c >= FixExt1 && c <= FixExt16
}
func IsExt(c byte) bool {
return IsFixedExt(c) || c == Ext8 || c == Ext16 || c == Ext32
}

View File

@ -0,0 +1,4 @@
{
"name": "msgpack",
"version": "5.3.5"
}

View File

@ -6,16 +6,30 @@ import (
"reflect"
"time"
"github.com/vmihailenco/msgpack/v4/codes"
"github.com/vmihailenco/msgpack/v5/msgpcode"
)
var timeExtID int8 = -1
var timePtrType = reflect.TypeOf((*time.Time)(nil))
//nolint:gochecknoinits
func init() {
registerExt(timeExtID, timePtrType.Elem(), encodeTimeValue, decodeTimeValue)
RegisterExtEncoder(timeExtID, time.Time{}, timeEncoder)
RegisterExtDecoder(timeExtID, time.Time{}, timeDecoder)
}
func timeEncoder(e *Encoder, v reflect.Value) ([]byte, error) {
return e.encodeTime(v.Interface().(time.Time)), nil
}
func timeDecoder(d *Decoder, v reflect.Value, extLen int) error {
tm, err := d.decodeTime(extLen)
if err != nil {
return err
}
ptr := v.Addr().Interface().(*time.Time)
*ptr = tm
return nil
}
func (e *Encoder) EncodeTime(tm time.Time) error {
@ -30,14 +44,20 @@ func (e *Encoder) EncodeTime(tm time.Time) error {
}
func (e *Encoder) encodeTime(tm time.Time) []byte {
if e.timeBuf == nil {
e.timeBuf = make([]byte, 12)
}
secs := uint64(tm.Unix())
if secs>>34 == 0 {
data := uint64(tm.Nanosecond())<<34 | secs
if data&0xffffffff00000000 == 0 {
b := e.timeBuf[:4]
binary.BigEndian.PutUint32(b, uint32(data))
return b
}
b := e.timeBuf[:8]
binary.BigEndian.PutUint64(b, data)
return b
@ -50,62 +70,56 @@ func (e *Encoder) encodeTime(tm time.Time) []byte {
}
func (d *Decoder) DecodeTime() (time.Time, error) {
tm, err := d.decodeTime()
c, err := d.readCode()
if err != nil {
return time.Time{}, err
}
// Legacy format.
if c == msgpcode.FixedArrayLow|2 {
sec, err := d.DecodeInt64()
if err != nil {
return time.Time{}, err
}
nsec, err := d.DecodeInt64()
if err != nil {
return time.Time{}, err
}
return time.Unix(sec, nsec), nil
}
if msgpcode.IsString(c) {
s, err := d.string(c)
if err != nil {
return time.Time{}, err
}
return time.Parse(time.RFC3339Nano, s)
}
extID, extLen, err := d.extHeader(c)
if err != nil {
return time.Time{}, err
}
if extID != timeExtID {
return time.Time{}, fmt.Errorf("msgpack: invalid time ext id=%d", extID)
}
tm, err := d.decodeTime(extLen)
if err != nil {
return tm, err
}
if tm.IsZero() {
// Assume that zero time does not have timezone information.
// Zero time does not have timezone information.
return tm.UTC(), nil
}
return tm, nil
}
func (d *Decoder) decodeTime() (time.Time, error) {
extLen := d.extLen
d.extLen = 0
if extLen == 0 {
c, err := d.readCode()
if err != nil {
return time.Time{}, err
}
// Legacy format.
if c == codes.FixedArrayLow|2 {
sec, err := d.DecodeInt64()
if err != nil {
return time.Time{}, err
}
nsec, err := d.DecodeInt64()
if err != nil {
return time.Time{}, err
}
return time.Unix(sec, nsec), nil
}
if codes.IsString(c) {
s, err := d.string(c)
if err != nil {
return time.Time{}, err
}
return time.Parse(time.RFC3339Nano, s)
}
extLen, err = d.parseExtLen(c)
if err != nil {
return time.Time{}, err
}
// Skip ext id.
_, err = d.s.ReadByte()
if err != nil {
return time.Time{}, nil
}
}
func (d *Decoder) decodeTime(extLen int) (time.Time, error) {
b, err := d.readN(extLen)
if err != nil {
return time.Time{}, err
@ -129,21 +143,3 @@ func (d *Decoder) decodeTime() (time.Time, error) {
return time.Time{}, err
}
}
func encodeTimeValue(e *Encoder, v reflect.Value) error {
tm := v.Interface().(time.Time)
b := e.encodeTime(tm)
return e.write(b)
}
func decodeTimeValue(d *Decoder, v reflect.Value) error {
tm, err := d.DecodeTime()
if err != nil {
return err
}
ptr := v.Addr().Interface().(*time.Time)
*ptr = tm
return nil
}

View File

@ -7,7 +7,7 @@ import (
"reflect"
"sync"
"github.com/vmihailenco/tagparser"
"github.com/vmihailenco/tagparser/v2"
)
var errorType = reflect.TypeOf((*error)(nil)).Elem()
@ -27,6 +27,11 @@ var (
binaryUnmarshalerType = reflect.TypeOf((*encoding.BinaryUnmarshaler)(nil)).Elem()
)
var (
textMarshalerType = reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem()
textUnmarshalerType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem()
)
type (
encoderFunc func(*Encoder, reflect.Value) error
decoderFunc func(*Decoder, reflect.Value) error
@ -39,7 +44,7 @@ var (
// Register registers encoder and decoder functions for a value.
// This is low level API and in most cases you should prefer implementing
// Marshaler/CustomEncoder and Unmarshaler/CustomDecoder interfaces.
// CustomEncoder/CustomDecoder or Marshaler/Unmarshaler interfaces.
func Register(value interface{}, enc encoderFunc, dec decoderFunc) {
typ := reflect.TypeOf(value)
if enc != nil {
@ -52,30 +57,33 @@ func Register(value interface{}, enc encoderFunc, dec decoderFunc) {
//------------------------------------------------------------------------------
var (
structs = newStructCache(false)
jsonStructs = newStructCache(true)
)
const defaultStructTag = "msgpack"
var structs = newStructCache()
type structCache struct {
m sync.Map
useJSONTag bool
}
func newStructCache(useJSONTag bool) *structCache {
return &structCache{
useJSONTag: useJSONTag,
}
type structCacheKey struct {
tag string
typ reflect.Type
}
func (m *structCache) Fields(typ reflect.Type) *fields {
if v, ok := m.m.Load(typ); ok {
func newStructCache() *structCache {
return new(structCache)
}
func (m *structCache) Fields(typ reflect.Type, tag string) *fields {
key := structCacheKey{tag: tag, typ: typ}
if v, ok := m.m.Load(key); ok {
return v.(*fields)
}
fs := getFields(typ, m.useJSONTag)
m.m.Store(typ, fs)
fs := getFields(typ, tag)
m.m.Store(key, fs)
return fs
}
@ -89,17 +97,17 @@ type field struct {
decoder decoderFunc
}
func (f *field) Omit(strct reflect.Value) bool {
v, isNil := fieldByIndex(strct, f.index)
if isNil {
func (f *field) Omit(strct reflect.Value, forced bool) bool {
v, ok := fieldByIndex(strct, f.index)
if !ok {
return true
}
return f.omitEmpty && isEmptyValue(v)
return (f.omitEmpty || forced) && isEmptyValue(v)
}
func (f *field) EncodeValue(e *Encoder, strct reflect.Value) error {
v, isNil := fieldByIndex(strct, f.index)
if isNil {
v, ok := fieldByIndex(strct, f.index)
if !ok {
return e.EncodeNil()
}
return f.encoder(e, v)
@ -144,15 +152,15 @@ func (fs *fields) warnIfFieldExists(name string) {
}
}
func (fs *fields) OmitEmpty(strct reflect.Value) []*field {
if !fs.hasOmitEmpty {
func (fs *fields) OmitEmpty(strct reflect.Value, forced bool) []*field {
if !fs.hasOmitEmpty && !forced {
return fs.List
}
fields := make([]*field, 0, len(fs.List))
for _, f := range fs.List {
if !f.Omit(strct) {
if !f.Omit(strct, forced) {
fields = append(fields, f)
}
}
@ -160,16 +168,16 @@ func (fs *fields) OmitEmpty(strct reflect.Value) []*field {
return fields
}
func getFields(typ reflect.Type, useJSONTag bool) *fields {
func getFields(typ reflect.Type, fallbackTag string) *fields {
fs := newFields(typ)
var omitEmpty bool
for i := 0; i < typ.NumField(); i++ {
f := typ.Field(i)
tagStr := f.Tag.Get("msgpack")
if useJSONTag && tagStr == "" {
tagStr = f.Tag.Get("json")
tagStr := f.Tag.Get(defaultStructTag)
if tagStr == "" && fallbackTag != "" {
tagStr = f.Tag.Get(fallbackTag)
}
tag := tagparser.Parse(tagStr)
@ -178,9 +186,7 @@ func getFields(typ reflect.Type, useJSONTag bool) *fields {
}
if f.Name == "_msgpack" {
if tag.HasOption("asArray") {
fs.AsArray = true
}
fs.AsArray = tag.HasOption("as_array") || tag.HasOption("asArray")
if tag.HasOption("omitempty") {
omitEmpty = true
}
@ -199,11 +205,11 @@ func getFields(typ reflect.Type, useJSONTag bool) *fields {
if tag.HasOption("intern") {
switch f.Type.Kind() {
case reflect.Interface:
field.encoder = encodeInternInterfaceValue
field.decoder = decodeInternInterfaceValue
field.encoder = encodeInternedInterfaceValue
field.decoder = decodeInternedInterfaceValue
case reflect.String:
field.encoder = encodeInternStringValue
field.decoder = decodeInternStringValue
field.encoder = encodeInternedStringValue
field.decoder = decodeInternedStringValue
default:
err := fmt.Errorf("msgpack: intern strings are not supported on %s", f.Type)
panic(err)
@ -220,9 +226,9 @@ func getFields(typ reflect.Type, useJSONTag bool) *fields {
if f.Anonymous && !tag.HasOption("noinline") {
inline := tag.HasOption("inline")
if inline {
inlineFields(fs, f.Type, field, useJSONTag)
inlineFields(fs, f.Type, field, fallbackTag)
} else {
inline = shouldInline(fs, f.Type, field, useJSONTag)
inline = shouldInline(fs, f.Type, field, fallbackTag)
}
if inline {
@ -255,8 +261,8 @@ func init() {
decodeStructValuePtr = reflect.ValueOf(decodeStructValue).Pointer()
}
func inlineFields(fs *fields, typ reflect.Type, f *field, useJSONTag bool) {
inlinedFields := getFields(typ, useJSONTag).List
func inlineFields(fs *fields, typ reflect.Type, f *field, tag string) {
inlinedFields := getFields(typ, tag).List
for _, field := range inlinedFields {
if _, ok := fs.Map[field.name]; ok {
// Don't inline shadowed fields.
@ -267,7 +273,7 @@ func inlineFields(fs *fields, typ reflect.Type, f *field, useJSONTag bool) {
}
}
func shouldInline(fs *fields, typ reflect.Type, f *field, useJSONTag bool) bool {
func shouldInline(fs *fields, typ reflect.Type, f *field, tag string) bool {
var encoder encoderFunc
var decoder decoderFunc
@ -292,7 +298,7 @@ func shouldInline(fs *fields, typ reflect.Type, f *field, useJSONTag bool) bool
return false
}
inlinedFields := getFields(typ, useJSONTag).List
inlinedFields := getFields(typ, tag).List
for _, field := range inlinedFields {
if _, ok := fs.Map[field.name]; ok {
// Don't auto inline if there are shadowed fields.
@ -307,8 +313,26 @@ func shouldInline(fs *fields, typ reflect.Type, f *field, useJSONTag bool) bool
return true
}
type isZeroer interface {
IsZero() bool
}
func isEmptyValue(v reflect.Value) bool {
switch v.Kind() {
kind := v.Kind()
for kind == reflect.Interface {
if v.IsNil() {
return true
}
v = v.Elem()
kind = v.Kind()
}
if z, ok := v.Interface().(isZeroer); ok {
return nilable(kind) && v.IsNil() || z.IsZero()
}
switch kind {
case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
return v.Len() == 0
case reflect.Bool:
@ -319,22 +343,23 @@ func isEmptyValue(v reflect.Value) bool {
return v.Uint() == 0
case reflect.Float32, reflect.Float64:
return v.Float() == 0
case reflect.Interface, reflect.Ptr:
case reflect.Ptr:
return v.IsNil()
default:
return false
}
return false
}
func fieldByIndex(v reflect.Value, index []int) (_ reflect.Value, isNil bool) {
func fieldByIndex(v reflect.Value, index []int) (_ reflect.Value, ok bool) {
if len(index) == 1 {
return v.Field(index[0]), false
return v.Field(index[0]), true
}
for i, idx := range index {
if i > 0 {
if v.Kind() == reflect.Ptr {
if v.IsNil() {
return v, true
return v, false
}
v = v.Elem()
}
@ -342,7 +367,7 @@ func fieldByIndex(v reflect.Value, index []int) (_ reflect.Value, isNil bool) {
v = v.Field(idx)
}
return v, false
return v, true
}
func fieldByIndexAlloc(v reflect.Value, index []int) reflect.Value {
@ -353,7 +378,7 @@ func fieldByIndexAlloc(v reflect.Value, index []int) reflect.Value {
for i, idx := range index {
if i > 0 {
var ok bool
v, ok = indirectNew(v)
v, ok = indirectNil(v)
if !ok {
return v
}
@ -364,7 +389,7 @@ func fieldByIndexAlloc(v reflect.Value, index []int) reflect.Value {
return v
}
func indirectNew(v reflect.Value) (reflect.Value, bool) {
func indirectNil(v reflect.Value) (reflect.Value, bool) {
if v.Kind() == reflect.Ptr {
if v.IsNil() {
if !v.CanSet() {

View File

@ -7,7 +7,7 @@ import (
)
// bytesToString converts byte slice to string.
func bytesToString(b []byte) string { //nolint:deadcode,unused
func bytesToString(b []byte) string {
return *(*string)(unsafe.Pointer(&b))
}

6
vendor/github.com/vmihailenco/msgpack/v5/version.go generated vendored Normal file
View File

@ -0,0 +1,6 @@
package msgpack
// Version is the current release version.
func Version() string {
return "5.3.5"
}