MM-25710: Use an efficient cache serialization algorithm (#14826)
* MM-25710: Use an efficient cache serialization algorithm We investigate 3 packages for selecting a suitable replacement for gob encoding. The algorithm chosen was msgpack which gives a decent boost over the standard gob encoding. Any external schema dependent algorithms like protobuf, flatbuffers, avro, capn'proto were not considered as that would entail converting the model structs into separate schema objects and then code generating the Go structs. It could be done theoretically at a later stage specifically for structs which are in the hot path. This is a general solution for now. The packages considered were: - github.com/tinylib/msgp - github.com/ugorji/go/codec - github.com/vmihailenco/msgpack/v5 msgp uses code generation to generate encoding/decoding code without the reflection overhead. Theoretically, therefore this is supposed to give the fastest performance. However, a major flaw in that package is that it works only at a file/directory level, not at a package level. Therefore, for structs which are spread across multiple files, it becomes near to impossible to chase down all transitive dependencies to generate the code. Even if that's done, it fails on some complex type like xml.Name and time.Time. (See: https://github.com/tinylib/msgp/issues/274#issuecomment-643654611) Therefore, we are left with 2 choices. Both of them use the same underlying algorithm. But msgpack/v5 wraps the encoders/decoders in a sync.Pool. To make a perfect apples-apples comparison, I wrote a sync.Pool for ugorji/go/codec too and compared performance. msgpack/v5 came out to be the fastest by a small margin. benchstat master.txt ugorji.txt name old time/op new time/op delta LRU/simple=new-8 5.62µs ± 3% 3.68µs ± 2% -34.64% (p=0.000 n=10+10) LRU/complex=new-8 38.4µs ± 2% 9.1µs ± 2% -76.38% (p=0.000 n=9+9) LRU/User=new-8 75.8µs ± 2% 23.5µs ± 2% -69.01% (p=0.000 n=10+10) LRU/Post=new-8 125µs ± 2% 21µs ± 3% -82.92% (p=0.000 n=9+10) LRU/Status=new-8 27.6µs ± 1% 5.4µs ± 4% -80.34% (p=0.000 n=10+10) name old alloc/op new alloc/op delta LRU/simple=new-8 3.20kB ± 0% 1.60kB ± 0% -49.97% (p=0.000 n=10+10) LRU/complex=new-8 15.7kB ± 0% 4.4kB ± 0% -71.89% (p=0.000 n=9+10) LRU/User=new-8 33.5kB ± 0% 9.2kB ± 0% -72.48% (p=0.000 n=10+8) LRU/Post=new-8 38.7kB ± 0% 4.8kB ± 0% -87.48% (p=0.000 n=10+10) LRU/Status=new-8 10.6kB ± 0% 1.7kB ± 0% -83.50% (p=0.000 n=10+10) name old allocs/op new allocs/op delta LRU/simple=new-8 46.0 ± 0% 20.0 ± 0% -56.52% (p=0.000 n=10+10) LRU/complex=new-8 324 ± 0% 48 ± 0% -85.19% (p=0.000 n=10+10) LRU/User=new-8 622 ± 0% 108 ± 0% -82.64% (p=0.000 n=10+10) LRU/Post=new-8 902 ± 0% 74 ± 0% -91.80% (p=0.000 n=10+10) LRU/Status=new-8 242 ± 0% 22 ± 0% -90.91% (p=0.000 n=10+10) 11:31:48-~/mattermost/mattermost-server/services/cache2$benchstat master.txt vmi.txt name old time/op new time/op delta LRU/simple=new-8 5.62µs ± 3% 3.68µs ± 3% -34.59% (p=0.000 n=10+10) LRU/complex=new-8 38.4µs ± 2% 8.7µs ± 3% -77.45% (p=0.000 n=9+10) LRU/User=new-8 75.8µs ± 2% 20.9µs ± 1% -72.45% (p=0.000 n=10+10) LRU/Post=new-8 125µs ± 2% 21µs ± 2% -83.08% (p=0.000 n=9+10) LRU/Status=new-8 27.6µs ± 1% 5.1µs ± 3% -81.66% (p=0.000 n=10+10) name old alloc/op new alloc/op delta LRU/simple=new-8 3.20kB ± 0% 1.60kB ± 0% -49.89% (p=0.000 n=10+10) LRU/complex=new-8 15.7kB ± 0% 4.6kB ± 0% -70.87% (p=0.000 n=9+8) LRU/User=new-8 33.5kB ± 0% 10.3kB ± 0% -69.40% (p=0.000 n=10+9) LRU/Post=new-8 38.7kB ± 0% 6.0kB ± 0% -84.62% (p=0.000 n=10+10) LRU/Status=new-8 10.6kB ± 0% 1.9kB ± 0% -82.41% (p=0.000 n=10+10) name old allocs/op new allocs/op delta LRU/simple=new-8 46.0 ± 0% 20.0 ± 0% -56.52% (p=0.000 n=10+10) LRU/complex=new-8 324 ± 0% 46 ± 0% -85.80% (p=0.000 n=10+10) LRU/User=new-8 622 ± 0% 106 ± 0% -82.96% (p=0.000 n=10+10) LRU/Post=new-8 902 ± 0% 89 ± 0% -90.13% (p=0.000 n=10+10) LRU/Status=new-8 242 ± 0% 23 ± 0% -90.50% (p=0.000 n=10+10) In general, we can see that the time to marshal/unmarshal pays off as the size of the struct increases. We can see that msgpack/v5 is faster for CPU but very slightly heavier on memory. Since we are interested in fastest speed, we choose msgpack/v5. As a future optimization, we can use a mix of msgpack and msgp for hot structs. To do that, we would need to shuffle around some code so that for the hot struct, all its dependencies are in the same file. Let's use this in production for some time, watch grafana graphs for the hottest caches and come back to optimizing this more once we have more data. Side note: we have to do with micro-benchmarks for the time being, because all the caches aren't migrated to cache2 interface yet. Once that's in, we can actually run some load tests and do comparisons. * Bring back missing import * Fix tests
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
085ab2c60a
Коммит
ef85001523
12
vendor/github.com/vmihailenco/msgpack/v5/.golangci.yml
сгенерированный
поставляемый
Обычный файл
12
vendor/github.com/vmihailenco/msgpack/v5/.golangci.yml
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,12 @@
|
||||
run:
|
||||
concurrency: 8
|
||||
deadline: 5m
|
||||
tests: false
|
||||
linters:
|
||||
enable-all: true
|
||||
disable:
|
||||
- gochecknoglobals
|
||||
- gocognit
|
||||
- godox
|
||||
- wsl
|
||||
- funlen
|
||||
4
vendor/github.com/vmihailenco/msgpack/v5/.prettierrc
сгенерированный
поставляемый
Обычный файл
4
vendor/github.com/vmihailenco/msgpack/v5/.prettierrc
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,4 @@
|
||||
semi: false
|
||||
singleQuote: true
|
||||
proseWrap: always
|
||||
printWidth: 80
|
||||
21
vendor/github.com/vmihailenco/msgpack/v5/.travis.yml
сгенерированный
поставляемый
Обычный файл
21
vendor/github.com/vmihailenco/msgpack/v5/.travis.yml
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,21 @@
|
||||
sudo: false
|
||||
language: go
|
||||
|
||||
go:
|
||||
- 1.11.x
|
||||
- 1.12.x
|
||||
- 1.13.x
|
||||
- 1.14.x
|
||||
- tip
|
||||
|
||||
matrix:
|
||||
allow_failures:
|
||||
- go: tip
|
||||
|
||||
env:
|
||||
- GO111MODULE=on
|
||||
|
||||
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
|
||||
24
vendor/github.com/vmihailenco/msgpack/v5/CHANGELOG.md
сгенерированный
поставляемый
Обычный файл
24
vendor/github.com/vmihailenco/msgpack/v5/CHANGELOG.md
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,24 @@
|
||||
## v4
|
||||
|
||||
- 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.
|
||||
|
||||
## v3.3
|
||||
|
||||
- `msgpack:",inline"` tag is restored to force inlining structs.
|
||||
|
||||
## v3.2
|
||||
|
||||
- Decoding extension types returns pointer to the value instead of the value. Fixes #153
|
||||
|
||||
## v3
|
||||
|
||||
- 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.
|
||||
- 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.
|
||||
- DecodeInterface can now return int8/16/32 and uint8/16/32.
|
||||
- PeekCode returns codes.Code instead of byte.
|
||||
25
vendor/github.com/vmihailenco/msgpack/v5/LICENSE
сгенерированный
поставляемый
Обычный файл
25
vendor/github.com/vmihailenco/msgpack/v5/LICENSE
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,25 @@
|
||||
Copyright (c) 2013 The github.com/vmihailenco/msgpack Authors.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
6
vendor/github.com/vmihailenco/msgpack/v5/Makefile
сгенерированный
поставляемый
Обычный файл
6
vendor/github.com/vmihailenco/msgpack/v5/Makefile
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,6 @@
|
||||
all:
|
||||
go test ./...
|
||||
go test ./... -short -race
|
||||
go test ./... -run=NONE -bench=. -benchmem
|
||||
env GOOS=linux GOARCH=386 go test ./...
|
||||
golangci-lint run
|
||||
92
vendor/github.com/vmihailenco/msgpack/v5/README.md
сгенерированный
поставляемый
Обычный файл
92
vendor/github.com/vmihailenco/msgpack/v5/README.md
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,92 @@
|
||||
# MessagePack encoding for Golang
|
||||
|
||||
[](https://travis-ci.org/vmihailenco/msgpack)
|
||||
[](https://pkg.go.dev/github.com/vmihailenco/msgpack/v5?tab=doc)
|
||||
|
||||
## Sponsors
|
||||
|
||||
- [**Uptrace.dev** - distributed traces and metrics](https://uptrace.dev)
|
||||
|
||||
## Features
|
||||
|
||||
- Primitives, arrays, maps, structs, time.Time and interface{}.
|
||||
- Appengine \*datastore.Key and datastore.Cursor.
|
||||
- [CustomEncoder](https://pkg.go.dev/github.com/vmihailenco/msgpack/v5?tab=doc#example-CustomEncoder)/CustomDecoder
|
||||
interfaces for custom encoding.
|
||||
- [Extensions](https://pkg.go.dev/github.com/vmihailenco/msgpack/v5?tab=doc#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?tab=doc#example-Marshal--OmitEmpty).
|
||||
- [Map keys sorting](https://pkg.go.dev/github.com/vmihailenco/msgpack/v5?tab=doc#Encoder.SortMapKeys).
|
||||
- Encoding/decoding all
|
||||
[structs as arrays](https://pkg.go.dev/github.com/vmihailenco/msgpack/v5?tab=doc#Encoder.UseArrayForStructs)
|
||||
or
|
||||
[individual structs](https://pkg.go.dev/github.com/vmihailenco/msgpack/v5?tab=doc#example-Marshal--AsArray).
|
||||
- [Encoder.UseJSONTag](https://pkg.go.dev/github.com/vmihailenco/msgpack/v5?tab=doc#Encoder.UseJSONTag)
|
||||
with
|
||||
[Decoder.UseJSONTag](https://pkg.go.dev/github.com/vmihailenco/msgpack/v5?tab=doc#Decoder.UseJSONTag)
|
||||
can turn msgpack into drop-in replacement for JSON.
|
||||
- Simple but very fast and efficient
|
||||
[queries](https://pkg.go.dev/github.com/vmihailenco/msgpack/v5?tab=doc#example-Decoder-Query).
|
||||
|
||||
API docs: https://pkg.go.dev/github.com/vmihailenco/msgpack/v5?tab=doc.
|
||||
Examples:
|
||||
https://pkg.go.dev/github.com/vmihailenco/msgpack/v5?tab=doc#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/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
|
||||
}
|
||||
```
|
||||
|
||||
## 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://pkg.go.dev/github.com/vmihailenco/msgpack/v5?tab=doc#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)
|
||||
64
vendor/github.com/vmihailenco/msgpack/v5/appengine.go
сгенерированный
поставляемый
Обычный файл
64
vendor/github.com/vmihailenco/msgpack/v5/appengine.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,64 @@
|
||||
// +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
|
||||
}
|
||||
90
vendor/github.com/vmihailenco/msgpack/v5/codes/codes.go
сгенерированный
поставляемый
Обычный файл
90
vendor/github.com/vmihailenco/msgpack/v5/codes/codes.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,90 @@
|
||||
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
|
||||
}
|
||||
663
vendor/github.com/vmihailenco/msgpack/v5/decode.go
сгенерированный
поставляемый
Обычный файл
663
vendor/github.com/vmihailenco/msgpack/v5/decode.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,663 @@
|
||||
package msgpack
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"reflect"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/vmihailenco/msgpack/v5/codes"
|
||||
)
|
||||
|
||||
const (
|
||||
looseIfaceFlag uint32 = 1 << iota
|
||||
disallowUnknownFieldsFlag
|
||||
)
|
||||
|
||||
const (
|
||||
bytesAllocLimit = 1e6 // 1mb
|
||||
sliceAllocLimit = 1e4
|
||||
maxMapSize = 1e6
|
||||
)
|
||||
|
||||
type bufReader interface {
|
||||
io.Reader
|
||||
io.ByteScanner
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
var decPool = sync.Pool{
|
||||
New: func() interface{} {
|
||||
return NewDecoder(nil)
|
||||
},
|
||||
}
|
||||
|
||||
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 := GetDecoder()
|
||||
|
||||
dec.ResetBytes(data)
|
||||
err := dec.Decode(v)
|
||||
|
||||
PutDecoder(dec)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// A Decoder reads and decodes MessagePack values from an input stream.
|
||||
type Decoder struct {
|
||||
r io.Reader
|
||||
s io.ByteScanner
|
||||
buf []byte
|
||||
|
||||
extLen int
|
||||
rec []byte // accumulates read data if not nil
|
||||
|
||||
intern []string
|
||||
flags uint32
|
||||
structTag string
|
||||
decodeMapFunc 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
|
||||
// by passing a reader that implements io.ByteScanner interface.
|
||||
func NewDecoder(r io.Reader) *Decoder {
|
||||
d := new(Decoder)
|
||||
d.Reset(r)
|
||||
return d
|
||||
}
|
||||
|
||||
type resetter interface {
|
||||
Reset([]byte)
|
||||
}
|
||||
|
||||
func (d *Decoder) ResetBytes(data []byte) {
|
||||
if r, ok := d.r.(resetter); ok {
|
||||
r.Reset(data)
|
||||
} else {
|
||||
d.Reset(bytes.NewReader(data))
|
||||
}
|
||||
}
|
||||
|
||||
// Reset discards any buffered data, resets all state, and switches the buffered
|
||||
// reader to read from r.
|
||||
func (d *Decoder) Reset(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]
|
||||
}
|
||||
|
||||
d.flags = 0
|
||||
d.decodeMapFunc = nil
|
||||
}
|
||||
|
||||
func (d *Decoder) SetDecodeMapFunc(fn func(*Decoder) (interface{}, error)) {
|
||||
d.decodeMapFunc = fn
|
||||
}
|
||||
|
||||
// UseDecodeInterfaceLoose causes decoder to use DecodeInterfaceLoose
|
||||
// to decode msgpack value into Go interface{}.
|
||||
func (d *Decoder) UseDecodeInterfaceLoose(on bool) {
|
||||
if on {
|
||||
d.flags |= looseIfaceFlag
|
||||
} else {
|
||||
d.flags &= ^looseIfaceFlag
|
||||
}
|
||||
}
|
||||
|
||||
// UseJSONTag causes the Decoder to use json struct tag as fallback option
|
||||
// if there is no msgpack tag.
|
||||
func (d *Decoder) UseJSONTag(on bool) {
|
||||
if on {
|
||||
d.UseCustomStructTag("json")
|
||||
} else {
|
||||
d.UseCustomStructTag("")
|
||||
}
|
||||
}
|
||||
|
||||
// UseCustomStructTag causes the decoder to use the supplied tag as a fallback option
|
||||
// if there is no msgpack tag.
|
||||
func (d *Decoder) UseCustomStructTag(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(on bool) {
|
||||
if on {
|
||||
d.flags |= disallowUnknownFieldsFlag
|
||||
} else {
|
||||
d.flags &= ^disallowUnknownFieldsFlag
|
||||
}
|
||||
}
|
||||
|
||||
// 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 {
|
||||
return d.r
|
||||
}
|
||||
|
||||
//nolint:gocyclo
|
||||
func (d *Decoder) Decode(v interface{}) error {
|
||||
var err error
|
||||
switch v := v.(type) {
|
||||
case *string:
|
||||
if v != nil {
|
||||
*v, err = d.DecodeString()
|
||||
return err
|
||||
}
|
||||
case *[]byte:
|
||||
if v != nil {
|
||||
return d.decodeBytesPtr(v)
|
||||
}
|
||||
case *int:
|
||||
if v != nil {
|
||||
*v, err = d.DecodeInt()
|
||||
return err
|
||||
}
|
||||
case *int8:
|
||||
if v != nil {
|
||||
*v, err = d.DecodeInt8()
|
||||
return err
|
||||
}
|
||||
case *int16:
|
||||
if v != nil {
|
||||
*v, err = d.DecodeInt16()
|
||||
return err
|
||||
}
|
||||
case *int32:
|
||||
if v != nil {
|
||||
*v, err = d.DecodeInt32()
|
||||
return err
|
||||
}
|
||||
case *int64:
|
||||
if v != nil {
|
||||
*v, err = d.DecodeInt64()
|
||||
return err
|
||||
}
|
||||
case *uint:
|
||||
if v != nil {
|
||||
*v, err = d.DecodeUint()
|
||||
return err
|
||||
}
|
||||
case *uint8:
|
||||
if v != nil {
|
||||
*v, err = d.DecodeUint8()
|
||||
return err
|
||||
}
|
||||
case *uint16:
|
||||
if v != nil {
|
||||
*v, err = d.DecodeUint16()
|
||||
return err
|
||||
}
|
||||
case *uint32:
|
||||
if v != nil {
|
||||
*v, err = d.DecodeUint32()
|
||||
return err
|
||||
}
|
||||
case *uint64:
|
||||
if v != nil {
|
||||
*v, err = d.DecodeUint64()
|
||||
return err
|
||||
}
|
||||
case *bool:
|
||||
if v != nil {
|
||||
*v, err = d.DecodeBool()
|
||||
return err
|
||||
}
|
||||
case *float32:
|
||||
if v != nil {
|
||||
*v, err = d.DecodeFloat32()
|
||||
return err
|
||||
}
|
||||
case *float64:
|
||||
if v != nil {
|
||||
*v, err = d.DecodeFloat64()
|
||||
return err
|
||||
}
|
||||
case *[]string:
|
||||
return d.decodeStringSlicePtr(v)
|
||||
case *map[string]string:
|
||||
return d.decodeMapStringStringPtr(v)
|
||||
case *map[string]interface{}:
|
||||
return d.decodeMapStringInterfacePtr(v)
|
||||
case *time.Duration:
|
||||
if v != nil {
|
||||
vv, err := d.DecodeInt64()
|
||||
*v = time.Duration(vv)
|
||||
return err
|
||||
}
|
||||
case *time.Time:
|
||||
if v != nil {
|
||||
*v, err = d.DecodeTime()
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
vv := reflect.ValueOf(v)
|
||||
if !vv.IsValid() {
|
||||
return errors.New("msgpack: Decode(nil)")
|
||||
}
|
||||
if vv.Kind() != reflect.Ptr {
|
||||
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.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)
|
||||
}
|
||||
|
||||
func (d *Decoder) DecodeMulti(v ...interface{}) error {
|
||||
for _, vv := range v {
|
||||
if err := d.Decode(vv); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Decoder) decodeInterfaceCond() (interface{}, error) {
|
||||
if d.flags&looseIfaceFlag != 0 {
|
||||
return d.DecodeInterfaceLoose()
|
||||
}
|
||||
return d.DecodeInterface()
|
||||
}
|
||||
|
||||
func (d *Decoder) DecodeValue(v reflect.Value) error {
|
||||
decode := getDecoder(v.Type())
|
||||
return decode(d, v)
|
||||
}
|
||||
|
||||
func (d *Decoder) DecodeNil() error {
|
||||
c, err := d.readCode()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if c != codes.Nil {
|
||||
return fmt.Errorf("msgpack: invalid code=%x decoding nil", c)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Decoder) decodeNilValue(v reflect.Value) error {
|
||||
err := d.DecodeNil()
|
||||
if v.IsNil() {
|
||||
return err
|
||||
}
|
||||
if v.Kind() == reflect.Ptr {
|
||||
v = v.Elem()
|
||||
}
|
||||
v.Set(reflect.Zero(v.Type()))
|
||||
return err
|
||||
}
|
||||
|
||||
func (d *Decoder) DecodeBool() (bool, error) {
|
||||
c, err := d.readCode()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return d.bool(c)
|
||||
}
|
||||
|
||||
func (d *Decoder) bool(c codes.Code) (bool, error) {
|
||||
if c == codes.False {
|
||||
return false, nil
|
||||
}
|
||||
if c == codes.True {
|
||||
return true, nil
|
||||
}
|
||||
return false, fmt.Errorf("msgpack: invalid code=%x decoding bool", c)
|
||||
}
|
||||
|
||||
func (d *Decoder) DecodeDuration() (time.Duration, error) {
|
||||
n, err := d.DecodeInt64()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return time.Duration(n), nil
|
||||
}
|
||||
|
||||
// DecodeInterface decodes value into interface. It returns following types:
|
||||
// - nil,
|
||||
// - bool,
|
||||
// - int8, int16, int32, int64,
|
||||
// - uint8, uint16, uint32, uint64,
|
||||
// - float32 and float64,
|
||||
// - string,
|
||||
// - []byte,
|
||||
// - slices of any of the above,
|
||||
// - maps of any of the above.
|
||||
//
|
||||
// DecodeInterface should be used only when you don't know the type of value
|
||||
// you are decoding. For example, if you are decoding number it is better to use
|
||||
// DecodeInt64 for negative numbers and DecodeUint64 for positive numbers.
|
||||
func (d *Decoder) DecodeInterface() (interface{}, error) {
|
||||
c, err := d.readCode()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if codes.IsFixedNum(c) {
|
||||
return int8(c), nil
|
||||
}
|
||||
if codes.IsFixedMap(c) {
|
||||
err = d.s.UnreadByte()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return d.DecodeMap()
|
||||
}
|
||||
if codes.IsFixedArray(c) {
|
||||
return d.decodeSlice(c)
|
||||
}
|
||||
if codes.IsFixedString(c) {
|
||||
return d.string(c)
|
||||
}
|
||||
|
||||
switch c {
|
||||
case codes.Nil:
|
||||
return nil, nil
|
||||
case codes.False, codes.True:
|
||||
return d.bool(c)
|
||||
case codes.Float:
|
||||
return d.float32(c)
|
||||
case codes.Double:
|
||||
return d.float64(c)
|
||||
case codes.Uint8:
|
||||
return d.uint8()
|
||||
case codes.Uint16:
|
||||
return d.uint16()
|
||||
case codes.Uint32:
|
||||
return d.uint32()
|
||||
case codes.Uint64:
|
||||
return d.uint64()
|
||||
case codes.Int8:
|
||||
return d.int8()
|
||||
case codes.Int16:
|
||||
return d.int16()
|
||||
case codes.Int32:
|
||||
return d.int32()
|
||||
case codes.Int64:
|
||||
return d.int64()
|
||||
case codes.Bin8, codes.Bin16, codes.Bin32:
|
||||
return d.bytes(c, nil)
|
||||
case codes.Str8, codes.Str16, codes.Str32:
|
||||
return d.string(c)
|
||||
case codes.Array16, codes.Array32:
|
||||
return d.decodeSlice(c)
|
||||
case codes.Map16, codes.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 0, fmt.Errorf("msgpack: unknown code %x decoding interface{}", c)
|
||||
}
|
||||
|
||||
// DecodeInterfaceLoose is like DecodeInterface except that:
|
||||
// - int8, int16, and int32 are converted to int64,
|
||||
// - uint8, uint16, and uint32 are converted to uint64,
|
||||
// - float32 is converted to float64.
|
||||
func (d *Decoder) DecodeInterfaceLoose() (interface{}, error) {
|
||||
c, err := d.readCode()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if codes.IsFixedNum(c) {
|
||||
return int64(int8(c)), nil
|
||||
}
|
||||
if codes.IsFixedMap(c) {
|
||||
err = d.s.UnreadByte()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return d.DecodeMap()
|
||||
}
|
||||
if codes.IsFixedArray(c) {
|
||||
return d.decodeSlice(c)
|
||||
}
|
||||
if codes.IsFixedString(c) {
|
||||
return d.string(c)
|
||||
}
|
||||
|
||||
switch c {
|
||||
case codes.Nil:
|
||||
return nil, nil
|
||||
case codes.False, codes.True:
|
||||
return d.bool(c)
|
||||
case codes.Float, codes.Double:
|
||||
return d.float64(c)
|
||||
case codes.Uint8, codes.Uint16, codes.Uint32, codes.Uint64:
|
||||
return d.uint(c)
|
||||
case codes.Int8, codes.Int16, codes.Int32, codes.Int64:
|
||||
return d.int(c)
|
||||
case codes.Bin8, codes.Bin16, codes.Bin32:
|
||||
return d.bytes(c, nil)
|
||||
case codes.Str8, codes.Str16, codes.Str32:
|
||||
return d.string(c)
|
||||
case codes.Array16, codes.Array32:
|
||||
return d.decodeSlice(c)
|
||||
case codes.Map16, codes.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 0, fmt.Errorf("msgpack: unknown code %x decoding interface{}", c)
|
||||
}
|
||||
|
||||
// Skip skips next value.
|
||||
func (d *Decoder) Skip() error {
|
||||
c, err := d.readCode()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if codes.IsFixedNum(c) {
|
||||
return nil
|
||||
}
|
||||
if codes.IsFixedMap(c) {
|
||||
return d.skipMap(c)
|
||||
}
|
||||
if codes.IsFixedArray(c) {
|
||||
return d.skipSlice(c)
|
||||
}
|
||||
if codes.IsFixedString(c) {
|
||||
return d.skipBytes(c)
|
||||
}
|
||||
|
||||
switch c {
|
||||
case codes.Nil, codes.False, codes.True:
|
||||
return nil
|
||||
case codes.Uint8, codes.Int8:
|
||||
return d.skipN(1)
|
||||
case codes.Uint16, codes.Int16:
|
||||
return d.skipN(2)
|
||||
case codes.Uint32, codes.Int32, codes.Float:
|
||||
return d.skipN(4)
|
||||
case codes.Uint64, codes.Int64, codes.Double:
|
||||
return d.skipN(8)
|
||||
case codes.Bin8, codes.Bin16, codes.Bin32:
|
||||
return d.skipBytes(c)
|
||||
case codes.Str8, codes.Str16, codes.Str32:
|
||||
return d.skipBytes(c)
|
||||
case codes.Array16, codes.Array32:
|
||||
return d.skipSlice(c)
|
||||
case codes.Map16, codes.Map32:
|
||||
return d.skipMap(c)
|
||||
case codes.FixExt1, codes.FixExt2, codes.FixExt4, codes.FixExt8, codes.FixExt16,
|
||||
codes.Ext8, codes.Ext16, codes.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 defines list of available codes.
|
||||
func (d *Decoder) PeekCode() (codes.Code, error) {
|
||||
c, err := d.s.ReadByte()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return codes.Code(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
|
||||
}
|
||||
|
||||
func (d *Decoder) readCode() (codes.Code, error) {
|
||||
d.extLen = 0
|
||||
c, err := d.s.ReadByte()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if d.rec != nil {
|
||||
d.rec = append(d.rec, c)
|
||||
}
|
||||
return codes.Code(c), nil
|
||||
}
|
||||
|
||||
func (d *Decoder) readFull(b []byte) error {
|
||||
_, err := io.ReadFull(d.r, b)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if d.rec != nil {
|
||||
d.rec = append(d.rec, b...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Decoder) readN(n int) ([]byte, error) {
|
||||
var err error
|
||||
d.buf, err = readN(d.r, d.buf, n)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if d.rec != nil {
|
||||
//TODO: read directly into d.rec?
|
||||
d.rec = append(d.rec, d.buf...)
|
||||
}
|
||||
return d.buf, nil
|
||||
}
|
||||
|
||||
func readN(r io.Reader, b []byte, n int) ([]byte, error) {
|
||||
if b == nil {
|
||||
if n == 0 {
|
||||
return make([]byte, 0), nil
|
||||
}
|
||||
switch {
|
||||
case n < 64:
|
||||
b = make([]byte, 0, 64)
|
||||
case n <= bytesAllocLimit:
|
||||
b = make([]byte, 0, n)
|
||||
default:
|
||||
b = make([]byte, 0, bytesAllocLimit)
|
||||
}
|
||||
}
|
||||
|
||||
if n <= cap(b) {
|
||||
b = b[:n]
|
||||
_, err := io.ReadFull(r, b)
|
||||
return b, err
|
||||
}
|
||||
b = b[:cap(b)]
|
||||
|
||||
var pos int
|
||||
for {
|
||||
alloc := min(n-len(b), bytesAllocLimit)
|
||||
b = append(b, make([]byte, alloc)...)
|
||||
|
||||
_, err := io.ReadFull(r, b[pos:])
|
||||
if err != nil {
|
||||
return b, err
|
||||
}
|
||||
|
||||
if len(b) == n {
|
||||
break
|
||||
}
|
||||
pos = len(b)
|
||||
}
|
||||
|
||||
return b, nil
|
||||
}
|
||||
|
||||
func min(a, b int) int { //nolint:unparam
|
||||
if a <= b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
335
vendor/github.com/vmihailenco/msgpack/v5/decode_map.go
сгенерированный
поставляемый
Обычный файл
335
vendor/github.com/vmihailenco/msgpack/v5/decode_map.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,335 @@
|
||||
package msgpack
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"github.com/vmihailenco/msgpack/v5/codes"
|
||||
)
|
||||
|
||||
var (
|
||||
mapStringStringPtrType = reflect.TypeOf((*map[string]string)(nil))
|
||||
mapStringStringType = mapStringStringPtrType.Elem()
|
||||
)
|
||||
|
||||
var (
|
||||
mapStringInterfacePtrType = reflect.TypeOf((*map[string]interface{})(nil))
|
||||
mapStringInterfaceType = mapStringInterfacePtrType.Elem()
|
||||
)
|
||||
|
||||
func decodeMapValue(d *Decoder, v reflect.Value) error {
|
||||
size, err := d.DecodeMapLen()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
typ := v.Type()
|
||||
if size == -1 {
|
||||
v.Set(reflect.Zero(typ))
|
||||
return nil
|
||||
}
|
||||
|
||||
if v.IsNil() {
|
||||
v.Set(reflect.MakeMap(typ))
|
||||
}
|
||||
if size == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
return decodeMapValueSize(d, v, size)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// DecodeMapLen decodes map length. Length is -1 when map is nil.
|
||||
func (d *Decoder) DecodeMapLen() (int, error) {
|
||||
c, err := d.readCode()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
if codes.IsExt(c) {
|
||||
if err = d.skipExtHeader(c); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
c, err = d.readCode()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
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 {
|
||||
return -1, nil
|
||||
}
|
||||
if c >= codes.FixedMapLow && c <= codes.FixedMapHigh {
|
||||
return int(c & codes.FixedMapMask), nil
|
||||
}
|
||||
if c == codes.Map16 {
|
||||
size, err := d.uint16()
|
||||
return int(size), err
|
||||
}
|
||||
if c == codes.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
|
||||
}
|
||||
|
||||
func decodeMapStringStringValue(d *Decoder, v reflect.Value) error {
|
||||
mptr := v.Addr().Convert(mapStringStringPtrType).Interface().(*map[string]string)
|
||||
return d.decodeMapStringStringPtr(mptr)
|
||||
}
|
||||
|
||||
func (d *Decoder) decodeMapStringStringPtr(ptr *map[string]string) error {
|
||||
size, err := d.DecodeMapLen()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if size == -1 {
|
||||
*ptr = nil
|
||||
return nil
|
||||
}
|
||||
|
||||
m := *ptr
|
||||
if m == nil {
|
||||
*ptr = make(map[string]string, min(size, maxMapSize))
|
||||
m = *ptr
|
||||
}
|
||||
|
||||
for i := 0; i < size; i++ {
|
||||
mk, err := d.DecodeString()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
mv, err := d.DecodeString()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
m[mk] = mv
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func decodeMapStringInterfaceValue(d *Decoder, v reflect.Value) error {
|
||||
ptr := v.Addr().Convert(mapStringInterfacePtrType).Interface().(*map[string]interface{})
|
||||
return d.decodeMapStringInterfacePtr(ptr)
|
||||
}
|
||||
|
||||
func (d *Decoder) decodeMapStringInterfacePtr(ptr *map[string]interface{}) error {
|
||||
n, err := d.DecodeMapLen()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if n == -1 {
|
||||
*ptr = nil
|
||||
return nil
|
||||
}
|
||||
|
||||
m := *ptr
|
||||
if m == nil {
|
||||
*ptr = make(map[string]interface{}, min(n, maxMapSize))
|
||||
m = *ptr
|
||||
}
|
||||
|
||||
for i := 0; i < n; i++ {
|
||||
mk, err := d.DecodeString()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
mv, err := d.decodeInterfaceCond()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
m[mk] = mv
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Decoder) DecodeMap() (interface{}, error) {
|
||||
if d.decodeMapFunc != nil {
|
||||
return d.decodeMapFunc(d)
|
||||
}
|
||||
|
||||
size, err := d.DecodeMapLen()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if size == -1 {
|
||||
return nil, nil
|
||||
}
|
||||
if size == 0 {
|
||||
return make(map[string]interface{}), nil
|
||||
}
|
||||
|
||||
code, err := d.PeekCode()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if codes.IsString(code) || codes.IsBin(code) {
|
||||
return d.decodeMapStringInterfaceSize(size)
|
||||
}
|
||||
|
||||
key, err := d.decodeInterfaceCond()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
value, err := d.decodeInterfaceCond()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
keyType := reflect.TypeOf(key)
|
||||
valueType := reflect.TypeOf(value)
|
||||
|
||||
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 {
|
||||
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
|
||||
}
|
||||
mv, err := d.decodeInterfaceCond()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
m[mk] = mv
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func (d *Decoder) skipMap(c codes.Code) error {
|
||||
n, err := d.mapLen(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for i := 0; i < n; i++ {
|
||||
if err := d.Skip(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := d.Skip(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func decodeStructValue(d *Decoder, v reflect.Value) error {
|
||||
c, err := d.readCode()
|
||||
if err != nil {
|
||||
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
|
||||
}
|
||||
if n == -1 {
|
||||
v.Set(reflect.Zero(v.Type()))
|
||||
return nil
|
||||
}
|
||||
|
||||
fields := structs.Fields(v.Type(), d.structTag)
|
||||
if isArray {
|
||||
for i, f := range fields.List {
|
||||
if i >= n {
|
||||
break
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
for i := 0; i < n; i++ {
|
||||
name, err := d.bytesTemp()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if f := fields.Map[string(name)]; f != nil {
|
||||
if err := f.DecodeValue(d, v); err != nil {
|
||||
return err
|
||||
}
|
||||
} else if d.flags&disallowUnknownFieldsFlag != 0 {
|
||||
return fmt.Errorf("msgpack: unknown field %q", name)
|
||||
} else if err := d.Skip(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
295
vendor/github.com/vmihailenco/msgpack/v5/decode_number.go
сгенерированный
поставляемый
Обычный файл
295
vendor/github.com/vmihailenco/msgpack/v5/decode_number.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,295 @@
|
||||
package msgpack
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"reflect"
|
||||
|
||||
"github.com/vmihailenco/msgpack/v5/codes"
|
||||
)
|
||||
|
||||
func (d *Decoder) skipN(n int) error {
|
||||
_, err := d.readN(n)
|
||||
return err
|
||||
}
|
||||
|
||||
func (d *Decoder) uint8() (uint8, error) {
|
||||
c, err := d.readCode()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return uint8(c), nil
|
||||
}
|
||||
|
||||
func (d *Decoder) int8() (int8, error) {
|
||||
n, err := d.uint8()
|
||||
return int8(n), err
|
||||
}
|
||||
|
||||
func (d *Decoder) uint16() (uint16, error) {
|
||||
b, err := d.readN(2)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return (uint16(b[0]) << 8) | uint16(b[1]), nil
|
||||
}
|
||||
|
||||
func (d *Decoder) int16() (int16, error) {
|
||||
n, err := d.uint16()
|
||||
return int16(n), err
|
||||
}
|
||||
|
||||
func (d *Decoder) uint32() (uint32, error) {
|
||||
b, err := d.readN(4)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
n := (uint32(b[0]) << 24) |
|
||||
(uint32(b[1]) << 16) |
|
||||
(uint32(b[2]) << 8) |
|
||||
uint32(b[3])
|
||||
return n, nil
|
||||
}
|
||||
|
||||
func (d *Decoder) int32() (int32, error) {
|
||||
n, err := d.uint32()
|
||||
return int32(n), err
|
||||
}
|
||||
|
||||
func (d *Decoder) uint64() (uint64, error) {
|
||||
b, err := d.readN(8)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
n := (uint64(b[0]) << 56) |
|
||||
(uint64(b[1]) << 48) |
|
||||
(uint64(b[2]) << 40) |
|
||||
(uint64(b[3]) << 32) |
|
||||
(uint64(b[4]) << 24) |
|
||||
(uint64(b[5]) << 16) |
|
||||
(uint64(b[6]) << 8) |
|
||||
uint64(b[7])
|
||||
return n, nil
|
||||
}
|
||||
|
||||
func (d *Decoder) int64() (int64, error) {
|
||||
n, err := d.uint64()
|
||||
return int64(n), err
|
||||
}
|
||||
|
||||
// DecodeUint64 decodes msgpack int8/16/32/64 and uint8/16/32/64
|
||||
// into Go uint64.
|
||||
func (d *Decoder) DecodeUint64() (uint64, error) {
|
||||
c, err := d.readCode()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return d.uint(c)
|
||||
}
|
||||
|
||||
func (d *Decoder) uint(c codes.Code) (uint64, error) {
|
||||
if c == codes.Nil {
|
||||
return 0, nil
|
||||
}
|
||||
if codes.IsFixedNum(c) {
|
||||
return uint64(int8(c)), nil
|
||||
}
|
||||
switch c {
|
||||
case codes.Uint8:
|
||||
n, err := d.uint8()
|
||||
return uint64(n), err
|
||||
case codes.Int8:
|
||||
n, err := d.int8()
|
||||
return uint64(n), err
|
||||
case codes.Uint16:
|
||||
n, err := d.uint16()
|
||||
return uint64(n), err
|
||||
case codes.Int16:
|
||||
n, err := d.int16()
|
||||
return uint64(n), err
|
||||
case codes.Uint32:
|
||||
n, err := d.uint32()
|
||||
return uint64(n), err
|
||||
case codes.Int32:
|
||||
n, err := d.int32()
|
||||
return uint64(n), err
|
||||
case codes.Uint64, codes.Int64:
|
||||
return d.uint64()
|
||||
}
|
||||
return 0, fmt.Errorf("msgpack: invalid code=%x decoding uint64", c)
|
||||
}
|
||||
|
||||
// DecodeInt64 decodes msgpack int8/16/32/64 and uint8/16/32/64
|
||||
// into Go int64.
|
||||
func (d *Decoder) DecodeInt64() (int64, error) {
|
||||
c, err := d.readCode()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return d.int(c)
|
||||
}
|
||||
|
||||
func (d *Decoder) int(c codes.Code) (int64, error) {
|
||||
if c == codes.Nil {
|
||||
return 0, nil
|
||||
}
|
||||
if codes.IsFixedNum(c) {
|
||||
return int64(int8(c)), nil
|
||||
}
|
||||
switch c {
|
||||
case codes.Uint8:
|
||||
n, err := d.uint8()
|
||||
return int64(n), err
|
||||
case codes.Int8:
|
||||
n, err := d.uint8()
|
||||
return int64(int8(n)), err
|
||||
case codes.Uint16:
|
||||
n, err := d.uint16()
|
||||
return int64(n), err
|
||||
case codes.Int16:
|
||||
n, err := d.uint16()
|
||||
return int64(int16(n)), err
|
||||
case codes.Uint32:
|
||||
n, err := d.uint32()
|
||||
return int64(n), err
|
||||
case codes.Int32:
|
||||
n, err := d.uint32()
|
||||
return int64(int32(n)), err
|
||||
case codes.Uint64, codes.Int64:
|
||||
n, err := d.uint64()
|
||||
return int64(n), err
|
||||
}
|
||||
return 0, fmt.Errorf("msgpack: invalid code=%x decoding int64", c)
|
||||
}
|
||||
|
||||
func (d *Decoder) DecodeFloat32() (float32, error) {
|
||||
c, err := d.readCode()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return d.float32(c)
|
||||
}
|
||||
|
||||
func (d *Decoder) float32(c codes.Code) (float32, error) {
|
||||
if c == codes.Float {
|
||||
n, err := d.uint32()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return math.Float32frombits(n), nil
|
||||
}
|
||||
|
||||
n, err := d.int(c)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("msgpack: invalid code=%x decoding float32", c)
|
||||
}
|
||||
return float32(n), nil
|
||||
}
|
||||
|
||||
// DecodeFloat64 decodes msgpack float32/64 into Go float64.
|
||||
func (d *Decoder) DecodeFloat64() (float64, error) {
|
||||
c, err := d.readCode()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return d.float64(c)
|
||||
}
|
||||
|
||||
func (d *Decoder) float64(c codes.Code) (float64, error) {
|
||||
switch c {
|
||||
case codes.Float:
|
||||
n, err := d.float32(c)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return float64(n), nil
|
||||
case codes.Double:
|
||||
n, err := d.uint64()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return math.Float64frombits(n), nil
|
||||
}
|
||||
|
||||
n, err := d.int(c)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("msgpack: invalid code=%x decoding float32", c)
|
||||
}
|
||||
return float64(n), nil
|
||||
}
|
||||
|
||||
func (d *Decoder) DecodeUint() (uint, error) {
|
||||
n, err := d.DecodeUint64()
|
||||
return uint(n), err
|
||||
}
|
||||
|
||||
func (d *Decoder) DecodeUint8() (uint8, error) {
|
||||
n, err := d.DecodeUint64()
|
||||
return uint8(n), err
|
||||
}
|
||||
|
||||
func (d *Decoder) DecodeUint16() (uint16, error) {
|
||||
n, err := d.DecodeUint64()
|
||||
return uint16(n), err
|
||||
}
|
||||
|
||||
func (d *Decoder) DecodeUint32() (uint32, error) {
|
||||
n, err := d.DecodeUint64()
|
||||
return uint32(n), err
|
||||
}
|
||||
|
||||
func (d *Decoder) DecodeInt() (int, error) {
|
||||
n, err := d.DecodeInt64()
|
||||
return int(n), err
|
||||
}
|
||||
|
||||
func (d *Decoder) DecodeInt8() (int8, error) {
|
||||
n, err := d.DecodeInt64()
|
||||
return int8(n), err
|
||||
}
|
||||
|
||||
func (d *Decoder) DecodeInt16() (int16, error) {
|
||||
n, err := d.DecodeInt64()
|
||||
return int16(n), err
|
||||
}
|
||||
|
||||
func (d *Decoder) DecodeInt32() (int32, error) {
|
||||
n, err := d.DecodeInt64()
|
||||
return int32(n), err
|
||||
}
|
||||
|
||||
func decodeFloat32Value(d *Decoder, v reflect.Value) error {
|
||||
f, err := d.DecodeFloat32()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
v.SetFloat(float64(f))
|
||||
return nil
|
||||
}
|
||||
|
||||
func decodeFloat64Value(d *Decoder, v reflect.Value) error {
|
||||
f, err := d.DecodeFloat64()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
v.SetFloat(f)
|
||||
return nil
|
||||
}
|
||||
|
||||
func decodeInt64Value(d *Decoder, v reflect.Value) error {
|
||||
n, err := d.DecodeInt64()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
v.SetInt(n)
|
||||
return nil
|
||||
}
|
||||
|
||||
func decodeUint64Value(d *Decoder, v reflect.Value) error {
|
||||
n, err := d.DecodeUint64()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
v.SetUint(n)
|
||||
return nil
|
||||
}
|
||||
158
vendor/github.com/vmihailenco/msgpack/v5/decode_query.go
сгенерированный
поставляемый
Обычный файл
158
vendor/github.com/vmihailenco/msgpack/v5/decode_query.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,158 @@
|
||||
package msgpack
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/vmihailenco/msgpack/v5/codes"
|
||||
)
|
||||
|
||||
type queryResult struct {
|
||||
query string
|
||||
key string
|
||||
hasAsterisk bool
|
||||
|
||||
values []interface{}
|
||||
}
|
||||
|
||||
func (q *queryResult) nextKey() {
|
||||
ind := strings.IndexByte(q.query, '.')
|
||||
if ind == -1 {
|
||||
q.key = q.query
|
||||
q.query = ""
|
||||
return
|
||||
}
|
||||
q.key = q.query[:ind]
|
||||
q.query = q.query[ind+1:]
|
||||
}
|
||||
|
||||
// Query extracts data specified by the query from the msgpack stream skipping
|
||||
// any other data. Query consists of map keys and array indexes separated with dot,
|
||||
// e.g. key1.0.key2.
|
||||
func (d *Decoder) Query(query string) ([]interface{}, error) {
|
||||
res := queryResult{
|
||||
query: query,
|
||||
}
|
||||
if err := d.query(&res); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return res.values, nil
|
||||
}
|
||||
|
||||
func (d *Decoder) query(q *queryResult) error {
|
||||
q.nextKey()
|
||||
if q.key == "" {
|
||||
v, err := d.decodeInterfaceCond()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
q.values = append(q.values, v)
|
||||
return nil
|
||||
}
|
||||
|
||||
code, err := d.PeekCode()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch {
|
||||
case code == codes.Map16 || code == codes.Map32 || codes.IsFixedMap(code):
|
||||
err = d.queryMapKey(q)
|
||||
case code == codes.Array16 || code == codes.Array32 || codes.IsFixedArray(code):
|
||||
err = d.queryArrayIndex(q)
|
||||
default:
|
||||
err = fmt.Errorf("msgpack: unsupported code=%x decoding key=%q", code, q.key)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (d *Decoder) queryMapKey(q *queryResult) error {
|
||||
n, err := d.DecodeMapLen()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if n == -1 {
|
||||
return nil
|
||||
}
|
||||
|
||||
for i := 0; i < n; i++ {
|
||||
key, err := d.bytesTemp()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if string(key) == q.key {
|
||||
if err := d.query(q); err != nil {
|
||||
return err
|
||||
}
|
||||
if q.hasAsterisk {
|
||||
return d.skipNext((n - i - 1) * 2)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := d.Skip(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Decoder) queryArrayIndex(q *queryResult) error {
|
||||
n, err := d.DecodeArrayLen()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if n == -1 {
|
||||
return nil
|
||||
}
|
||||
|
||||
if q.key == "*" {
|
||||
q.hasAsterisk = true
|
||||
|
||||
query := q.query
|
||||
for i := 0; i < n; i++ {
|
||||
q.query = query
|
||||
if err := d.query(q); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
q.hasAsterisk = false
|
||||
return nil
|
||||
}
|
||||
|
||||
ind, err := strconv.Atoi(q.key)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for i := 0; i < n; i++ {
|
||||
if i == ind {
|
||||
if err := d.query(q); err != nil {
|
||||
return err
|
||||
}
|
||||
if q.hasAsterisk {
|
||||
return d.skipNext(n - i - 1)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := d.Skip(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Decoder) skipNext(n int) error {
|
||||
for i := 0; i < n; i++ {
|
||||
if err := d.Skip(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
191
vendor/github.com/vmihailenco/msgpack/v5/decode_slice.go
сгенерированный
поставляемый
Обычный файл
191
vendor/github.com/vmihailenco/msgpack/v5/decode_slice.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,191 @@
|
||||
package msgpack
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"github.com/vmihailenco/msgpack/v5/codes"
|
||||
)
|
||||
|
||||
var sliceStringPtrType = reflect.TypeOf((*[]string)(nil))
|
||||
|
||||
// DecodeArrayLen decodes array length. Length is -1 when array is nil.
|
||||
func (d *Decoder) DecodeArrayLen() (int, error) {
|
||||
c, err := d.readCode()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return d.arrayLen(c)
|
||||
}
|
||||
|
||||
func (d *Decoder) arrayLen(c codes.Code) (int, error) {
|
||||
if c == codes.Nil {
|
||||
return -1, nil
|
||||
} else if c >= codes.FixedArrayLow && c <= codes.FixedArrayHigh {
|
||||
return int(c & codes.FixedArrayMask), nil
|
||||
}
|
||||
switch c {
|
||||
case codes.Array16:
|
||||
n, err := d.uint16()
|
||||
return int(n), err
|
||||
case codes.Array32:
|
||||
n, err := d.uint32()
|
||||
return int(n), err
|
||||
}
|
||||
return 0, fmt.Errorf("msgpack: invalid code=%x decoding array length", c)
|
||||
}
|
||||
|
||||
func decodeStringSliceValue(d *Decoder, v reflect.Value) error {
|
||||
ptr := v.Addr().Convert(sliceStringPtrType).Interface().(*[]string)
|
||||
return d.decodeStringSlicePtr(ptr)
|
||||
}
|
||||
|
||||
func (d *Decoder) decodeStringSlicePtr(ptr *[]string) error {
|
||||
n, err := d.DecodeArrayLen()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if n == -1 {
|
||||
return nil
|
||||
}
|
||||
|
||||
ss := makeStrings(*ptr, n)
|
||||
for i := 0; i < n; i++ {
|
||||
s, err := d.DecodeString()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ss = append(ss, s)
|
||||
}
|
||||
*ptr = ss
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func makeStrings(s []string, n int) []string {
|
||||
if n > sliceAllocLimit {
|
||||
n = sliceAllocLimit
|
||||
}
|
||||
|
||||
if s == nil {
|
||||
return make([]string, 0, n)
|
||||
}
|
||||
|
||||
if cap(s) >= n {
|
||||
return s[:0]
|
||||
}
|
||||
|
||||
s = s[:cap(s)]
|
||||
s = append(s, make([]string, n-len(s))...)
|
||||
return s[:0]
|
||||
}
|
||||
|
||||
func decodeSliceValue(d *Decoder, v reflect.Value) error {
|
||||
n, err := d.DecodeArrayLen()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if n == -1 {
|
||||
v.Set(reflect.Zero(v.Type()))
|
||||
return nil
|
||||
}
|
||||
if n == 0 && v.IsNil() {
|
||||
v.Set(reflect.MakeSlice(v.Type(), 0, 0))
|
||||
return nil
|
||||
}
|
||||
|
||||
if v.Cap() >= n {
|
||||
v.Set(v.Slice(0, n))
|
||||
} else if v.Len() < v.Cap() {
|
||||
v.Set(v.Slice(0, v.Cap()))
|
||||
}
|
||||
|
||||
for i := 0; i < n; i++ {
|
||||
if i >= v.Len() {
|
||||
v.Set(growSliceValue(v, n))
|
||||
}
|
||||
elem := v.Index(i)
|
||||
if err := d.DecodeValue(elem); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func growSliceValue(v reflect.Value, n int) reflect.Value {
|
||||
diff := n - v.Len()
|
||||
if diff > sliceAllocLimit {
|
||||
diff = sliceAllocLimit
|
||||
}
|
||||
v = reflect.AppendSlice(v, reflect.MakeSlice(v.Type(), diff, diff))
|
||||
return v
|
||||
}
|
||||
|
||||
func decodeArrayValue(d *Decoder, v reflect.Value) error {
|
||||
n, err := d.DecodeArrayLen()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if n == -1 {
|
||||
return nil
|
||||
}
|
||||
if n > v.Len() {
|
||||
return fmt.Errorf("%s len is %d, but msgpack has %d elements", v.Type(), v.Len(), n)
|
||||
}
|
||||
|
||||
for i := 0; i < n; i++ {
|
||||
sv := v.Index(i)
|
||||
if err := d.DecodeValue(sv); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Decoder) DecodeSlice() ([]interface{}, error) {
|
||||
c, err := d.readCode()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return d.decodeSlice(c)
|
||||
}
|
||||
|
||||
func (d *Decoder) decodeSlice(c codes.Code) ([]interface{}, error) {
|
||||
n, err := d.arrayLen(c)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if n == -1 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
s := make([]interface{}, 0, min(n, sliceAllocLimit))
|
||||
for i := 0; i < n; i++ {
|
||||
v, err := d.decodeInterfaceCond()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
s = append(s, v)
|
||||
}
|
||||
|
||||
return s, nil
|
||||
}
|
||||
|
||||
func (d *Decoder) skipSlice(c codes.Code) error {
|
||||
n, err := d.arrayLen(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for i := 0; i < n; i++ {
|
||||
if err := d.Skip(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
177
vendor/github.com/vmihailenco/msgpack/v5/decode_string.go
сгенерированный
поставляемый
Обычный файл
177
vendor/github.com/vmihailenco/msgpack/v5/decode_string.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,177 @@
|
||||
package msgpack
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"github.com/vmihailenco/msgpack/v5/codes"
|
||||
)
|
||||
|
||||
func (d *Decoder) bytesLen(c codes.Code) (int, error) {
|
||||
if c == codes.Nil {
|
||||
return -1, nil
|
||||
}
|
||||
|
||||
if codes.IsFixedString(c) {
|
||||
return int(c & codes.FixedStrMask), nil
|
||||
}
|
||||
|
||||
switch c {
|
||||
case codes.Str8, codes.Bin8:
|
||||
n, err := d.uint8()
|
||||
return int(n), err
|
||||
case codes.Str16, codes.Bin16:
|
||||
n, err := d.uint16()
|
||||
return int(n), err
|
||||
case codes.Str32, codes.Bin32:
|
||||
n, err := d.uint32()
|
||||
return int(n), err
|
||||
}
|
||||
|
||||
return 0, fmt.Errorf("msgpack: invalid code=%x decoding bytes length", c)
|
||||
}
|
||||
|
||||
func (d *Decoder) DecodeString() (string, error) {
|
||||
c, err := d.readCode()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return d.string(c)
|
||||
}
|
||||
|
||||
func (d *Decoder) string(c codes.Code) (string, error) {
|
||||
n, err := d.bytesLen(c)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return d.stringWithLen(n)
|
||||
}
|
||||
|
||||
func (d *Decoder) stringWithLen(n int) (string, error) {
|
||||
if n <= 0 {
|
||||
return "", nil
|
||||
}
|
||||
b, err := d.readN(n)
|
||||
return string(b), err
|
||||
}
|
||||
|
||||
func decodeStringValue(d *Decoder, v reflect.Value) error {
|
||||
s, err := d.DecodeString()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
v.SetString(s)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Decoder) DecodeBytesLen() (int, error) {
|
||||
c, err := d.readCode()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return d.bytesLen(c)
|
||||
}
|
||||
|
||||
func (d *Decoder) DecodeBytes() ([]byte, error) {
|
||||
c, err := d.readCode()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return d.bytes(c, nil)
|
||||
}
|
||||
|
||||
func (d *Decoder) bytes(c codes.Code, b []byte) ([]byte, error) {
|
||||
n, err := d.bytesLen(c)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if n == -1 {
|
||||
return nil, nil
|
||||
}
|
||||
return readN(d.r, b, n)
|
||||
}
|
||||
|
||||
func (d *Decoder) bytesTemp() ([]byte, error) {
|
||||
c, err := d.readCode()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
n, err := d.bytesLen(c)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if n == -1 {
|
||||
return nil, nil
|
||||
}
|
||||
return d.readN(n)
|
||||
}
|
||||
|
||||
func (d *Decoder) decodeBytesPtr(ptr *[]byte) error {
|
||||
c, err := d.readCode()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return d.bytesPtr(c, ptr)
|
||||
}
|
||||
|
||||
func (d *Decoder) bytesPtr(c codes.Code, ptr *[]byte) error {
|
||||
n, err := d.bytesLen(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if n == -1 {
|
||||
*ptr = nil
|
||||
return nil
|
||||
}
|
||||
|
||||
*ptr, err = readN(d.r, *ptr, n)
|
||||
return err
|
||||
}
|
||||
|
||||
func (d *Decoder) skipBytes(c codes.Code) error {
|
||||
n, err := d.bytesLen(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if n <= 0 {
|
||||
return nil
|
||||
}
|
||||
return d.skipN(n)
|
||||
}
|
||||
|
||||
func decodeBytesValue(d *Decoder, v reflect.Value) error {
|
||||
c, err := d.readCode()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
b, err := d.bytes(c, v.Bytes())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
v.SetBytes(b)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func decodeByteArrayValue(d *Decoder, v reflect.Value) error {
|
||||
c, err := d.readCode()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
n, err := d.bytesLen(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if n == -1 {
|
||||
return nil
|
||||
}
|
||||
if n > v.Len() {
|
||||
return fmt.Errorf("%s len is %d, but msgpack has %d elements", v.Type(), v.Len(), n)
|
||||
}
|
||||
|
||||
b := v.Slice(0, n).Bytes()
|
||||
return d.readFull(b)
|
||||
}
|
||||
263
vendor/github.com/vmihailenco/msgpack/v5/decode_value.go
сгенерированный
поставляемый
Обычный файл
263
vendor/github.com/vmihailenco/msgpack/v5/decode_value.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,263 @@
|
||||
package msgpack
|
||||
|
||||
import (
|
||||
"encoding"
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
var interfaceType = reflect.TypeOf((*interface{})(nil)).Elem()
|
||||
var stringType = reflect.TypeOf((*string)(nil)).Elem()
|
||||
|
||||
var valueDecoders []decoderFunc
|
||||
|
||||
//nolint:gochecknoinits
|
||||
func init() {
|
||||
valueDecoders = []decoderFunc{
|
||||
reflect.Bool: decodeBoolValue,
|
||||
reflect.Int: decodeInt64Value,
|
||||
reflect.Int8: decodeInt64Value,
|
||||
reflect.Int16: decodeInt64Value,
|
||||
reflect.Int32: decodeInt64Value,
|
||||
reflect.Int64: decodeInt64Value,
|
||||
reflect.Uint: decodeUint64Value,
|
||||
reflect.Uint8: decodeUint64Value,
|
||||
reflect.Uint16: decodeUint64Value,
|
||||
reflect.Uint32: decodeUint64Value,
|
||||
reflect.Uint64: decodeUint64Value,
|
||||
reflect.Float32: decodeFloat32Value,
|
||||
reflect.Float64: decodeFloat64Value,
|
||||
reflect.Complex64: decodeUnsupportedValue,
|
||||
reflect.Complex128: decodeUnsupportedValue,
|
||||
reflect.Array: decodeArrayValue,
|
||||
reflect.Chan: decodeUnsupportedValue,
|
||||
reflect.Func: decodeUnsupportedValue,
|
||||
reflect.Interface: decodeInterfaceValue,
|
||||
reflect.Map: decodeMapValue,
|
||||
reflect.Ptr: decodeUnsupportedValue,
|
||||
reflect.Slice: decodeSliceValue,
|
||||
reflect.String: decodeStringValue,
|
||||
reflect.Struct: decodeStructValue,
|
||||
reflect.UnsafePointer: decodeUnsupportedValue,
|
||||
}
|
||||
}
|
||||
|
||||
func getDecoder(typ reflect.Type) decoderFunc {
|
||||
if v, ok := typeDecMap.Load(typ); ok {
|
||||
return v.(decoderFunc)
|
||||
}
|
||||
fn := _getDecoder(typ)
|
||||
typeDecMap.Store(typ, fn)
|
||||
return fn
|
||||
}
|
||||
|
||||
func _getDecoder(typ reflect.Type) decoderFunc {
|
||||
kind := typ.Kind()
|
||||
|
||||
if kind == reflect.Ptr {
|
||||
if _, ok := typeDecMap.Load(typ.Elem()); ok {
|
||||
return ptrDecoderFunc(typ)
|
||||
}
|
||||
}
|
||||
|
||||
if typ.Implements(customDecoderType) {
|
||||
return decodeCustomValue
|
||||
}
|
||||
if typ.Implements(unmarshalerType) {
|
||||
return unmarshalValue
|
||||
}
|
||||
if typ.Implements(binaryUnmarshalerType) {
|
||||
return unmarshalBinaryValue
|
||||
}
|
||||
|
||||
// Addressable struct field value.
|
||||
if kind != reflect.Ptr {
|
||||
ptr := reflect.PtrTo(typ)
|
||||
if ptr.Implements(customDecoderType) {
|
||||
return decodeCustomValueAddr
|
||||
}
|
||||
if ptr.Implements(unmarshalerType) {
|
||||
return unmarshalValueAddr
|
||||
}
|
||||
if ptr.Implements(binaryUnmarshalerType) {
|
||||
return unmarshalBinaryValueAddr
|
||||
}
|
||||
}
|
||||
|
||||
switch kind {
|
||||
case reflect.Ptr:
|
||||
return ptrDecoderFunc(typ)
|
||||
case reflect.Slice:
|
||||
elem := typ.Elem()
|
||||
if elem.Kind() == reflect.Uint8 {
|
||||
return decodeBytesValue
|
||||
}
|
||||
if elem == stringType {
|
||||
return decodeStringSliceValue
|
||||
}
|
||||
case reflect.Array:
|
||||
if typ.Elem().Kind() == reflect.Uint8 {
|
||||
return decodeByteArrayValue
|
||||
}
|
||||
case reflect.Map:
|
||||
if typ.Key() == stringType {
|
||||
switch typ.Elem() {
|
||||
case stringType:
|
||||
return decodeMapStringStringValue
|
||||
case interfaceType:
|
||||
return decodeMapStringInterfaceValue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return valueDecoders[kind]
|
||||
}
|
||||
|
||||
func ptrDecoderFunc(typ reflect.Type) decoderFunc {
|
||||
decoder := getDecoder(typ.Elem())
|
||||
return func(d *Decoder, v reflect.Value) error {
|
||||
if d.hasNilCode() {
|
||||
if !v.IsNil() {
|
||||
v.Set(reflect.Zero(v.Type()))
|
||||
}
|
||||
return d.DecodeNil()
|
||||
}
|
||||
if v.IsNil() {
|
||||
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())
|
||||
}
|
||||
return decodeCustomValue(d, v.Addr())
|
||||
}
|
||||
|
||||
func decodeCustomValue(d *Decoder, v reflect.Value) error {
|
||||
if d.hasNilCode() {
|
||||
return d.decodeNilValue(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 {
|
||||
if d.hasNilCode() {
|
||||
return d.decodeNilValue(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 {
|
||||
flag, err := d.DecodeBool()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
v.SetBool(flag)
|
||||
return nil
|
||||
}
|
||||
|
||||
func decodeInterfaceValue(d *Decoder, v reflect.Value) error {
|
||||
if v.IsNil() {
|
||||
return d.interfaceValue(v)
|
||||
}
|
||||
|
||||
elem := v.Elem()
|
||||
if !elem.CanSet() {
|
||||
return d.interfaceValue(v)
|
||||
}
|
||||
|
||||
return d.DecodeValue(elem)
|
||||
}
|
||||
|
||||
func (d *Decoder) interfaceValue(v reflect.Value) error {
|
||||
vv, err := d.decodeInterfaceCond()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if vv != nil {
|
||||
if v.Type() == errorType {
|
||||
if vv, ok := vv.(string); ok {
|
||||
v.Set(reflect.ValueOf(errors.New(vv)))
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
v.Set(reflect.ValueOf(vv))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func decodeUnsupportedValue(d *Decoder, v reflect.Value) error {
|
||||
return fmt.Errorf("msgpack: Decode(unsupported %s)", v.Type())
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
func unmarshalBinaryValueAddr(d *Decoder, v reflect.Value) error {
|
||||
if !v.CanAddr() {
|
||||
return fmt.Errorf("msgpack: Decode(nonaddressable %T)", v.Interface())
|
||||
}
|
||||
return unmarshalBinaryValue(d, v.Addr())
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
unmarshaler := v.Interface().(encoding.BinaryUnmarshaler)
|
||||
return unmarshaler.UnmarshalBinary(data)
|
||||
}
|
||||
253
vendor/github.com/vmihailenco/msgpack/v5/encode.go
сгенерированный
поставляемый
Обычный файл
253
vendor/github.com/vmihailenco/msgpack/v5/encode.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,253 @@
|
||||
package msgpack
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"reflect"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/vmihailenco/msgpack/v5/codes"
|
||||
)
|
||||
|
||||
const (
|
||||
sortMapKeysFlag uint32 = 1 << iota
|
||||
structAsArrayFlag
|
||||
useCompactIntsFlag
|
||||
useCompactFloatsFlag
|
||||
)
|
||||
|
||||
type writer interface {
|
||||
io.Writer
|
||||
WriteByte(byte) error
|
||||
}
|
||||
|
||||
type byteWriter struct {
|
||||
io.Writer
|
||||
|
||||
buf [1]byte
|
||||
}
|
||||
|
||||
func newByteWriter(w io.Writer) *byteWriter {
|
||||
bw := new(byteWriter)
|
||||
bw.Reset(w)
|
||||
return bw
|
||||
}
|
||||
|
||||
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[:])
|
||||
return err
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
var encPool = sync.Pool{
|
||||
New: func() interface{} {
|
||||
return NewEncoder(nil)
|
||||
},
|
||||
}
|
||||
|
||||
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 := GetEncoder()
|
||||
|
||||
var buf bytes.Buffer
|
||||
enc.Reset(&buf)
|
||||
|
||||
err := enc.Encode(v)
|
||||
b := buf.Bytes()
|
||||
|
||||
PutEncoder(enc)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b, err
|
||||
}
|
||||
|
||||
type Encoder struct {
|
||||
w writer
|
||||
|
||||
buf []byte
|
||||
timeBuf []byte
|
||||
|
||||
intern map[string]int
|
||||
|
||||
flags uint32
|
||||
structTag string
|
||||
}
|
||||
|
||||
// NewEncoder returns a new encoder that writes to w.
|
||||
func NewEncoder(w io.Writer) *Encoder {
|
||||
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
|
||||
}
|
||||
|
||||
func (e *Encoder) Reset(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)
|
||||
}
|
||||
|
||||
e.flags = 0
|
||||
}
|
||||
|
||||
// SortMapKeys 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 {
|
||||
if on {
|
||||
e.flags |= sortMapKeysFlag
|
||||
} else {
|
||||
e.flags &= ^sortMapKeysFlag
|
||||
}
|
||||
return e
|
||||
}
|
||||
|
||||
// StructAsArray causes the Encoder to encode Go structs as msgpack arrays.
|
||||
func (e *Encoder) StructAsArray(on bool) {
|
||||
if on {
|
||||
e.flags |= structAsArrayFlag
|
||||
} else {
|
||||
e.flags &= ^structAsArrayFlag
|
||||
}
|
||||
}
|
||||
|
||||
// UseJSONTag causes the Encoder to use json struct tag as fallback option
|
||||
// if there is no msgpack tag.
|
||||
func (e *Encoder) UseJSONTag(on bool) {
|
||||
if on {
|
||||
e.UseCustomStructTag("json")
|
||||
} else {
|
||||
e.UseCustomStructTag("")
|
||||
}
|
||||
}
|
||||
|
||||
// UseCustomStructTag causes the Encoder to use a custom struct tag as
|
||||
// fallback option if there is no msgpack tag.
|
||||
func (e *Encoder) UseCustomStructTag(tag string) {
|
||||
e.structTag = tag
|
||||
}
|
||||
|
||||
// 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) UseCompactInts(on bool) {
|
||||
if on {
|
||||
e.flags |= useCompactIntsFlag
|
||||
} else {
|
||||
e.flags &= ^useCompactIntsFlag
|
||||
}
|
||||
}
|
||||
|
||||
// UseCompactFloats causes the Encoder to chose a compact integer encoding
|
||||
// for floats that can be represented as integers.
|
||||
func (e *Encoder) UseCompactFloats(on bool) {
|
||||
if on {
|
||||
e.flags |= useCompactFloatsFlag
|
||||
} else {
|
||||
e.flags &= ^useCompactFloatsFlag
|
||||
}
|
||||
}
|
||||
|
||||
func (e *Encoder) Encode(v interface{}) error {
|
||||
switch v := v.(type) {
|
||||
case nil:
|
||||
return e.EncodeNil()
|
||||
case string:
|
||||
return e.EncodeString(v)
|
||||
case []byte:
|
||||
return e.EncodeBytes(v)
|
||||
case int:
|
||||
return e.encodeInt64Cond(int64(v))
|
||||
case int64:
|
||||
return e.encodeInt64Cond(v)
|
||||
case uint:
|
||||
return e.encodeUint64Cond(uint64(v))
|
||||
case uint64:
|
||||
return e.encodeUint64Cond(v)
|
||||
case bool:
|
||||
return e.EncodeBool(v)
|
||||
case float32:
|
||||
return e.EncodeFloat32(v)
|
||||
case float64:
|
||||
return e.EncodeFloat64(v)
|
||||
case time.Duration:
|
||||
return e.encodeInt64Cond(int64(v))
|
||||
case time.Time:
|
||||
return e.EncodeTime(v)
|
||||
}
|
||||
return e.EncodeValue(reflect.ValueOf(v))
|
||||
}
|
||||
|
||||
func (e *Encoder) EncodeMulti(v ...interface{}) error {
|
||||
for _, vv := range v {
|
||||
if err := e.Encode(vv); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *Encoder) EncodeValue(v reflect.Value) error {
|
||||
fn := getEncoder(v.Type())
|
||||
return fn(e, v)
|
||||
}
|
||||
|
||||
func (e *Encoder) EncodeNil() error {
|
||||
return e.writeCode(codes.Nil)
|
||||
}
|
||||
|
||||
func (e *Encoder) EncodeBool(value bool) error {
|
||||
if value {
|
||||
return e.writeCode(codes.True)
|
||||
}
|
||||
return e.writeCode(codes.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) write(b []byte) error {
|
||||
_, err := e.w.Write(b)
|
||||
return err
|
||||
}
|
||||
|
||||
func (e *Encoder) writeString(s string) error {
|
||||
_, err := e.w.Write(stringToBytes(s))
|
||||
return err
|
||||
}
|
||||
166
vendor/github.com/vmihailenco/msgpack/v5/encode_map.go
сгенерированный
поставляемый
Обычный файл
166
vendor/github.com/vmihailenco/msgpack/v5/encode_map.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,166 @@
|
||||
package msgpack
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"sort"
|
||||
|
||||
"github.com/vmihailenco/msgpack/v5/codes"
|
||||
)
|
||||
|
||||
func encodeMapValue(e *Encoder, v reflect.Value) error {
|
||||
if v.IsNil() {
|
||||
return e.EncodeNil()
|
||||
}
|
||||
|
||||
if err := e.EncodeMapLen(v.Len()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, key := range v.MapKeys() {
|
||||
if err := e.EncodeValue(key); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := e.EncodeValue(v.MapIndex(key)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func encodeMapStringStringValue(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(mapStringStringType).Interface().(map[string]string)
|
||||
if e.flags&sortMapKeysFlag != 0 {
|
||||
return e.encodeSortedMapStringString(m)
|
||||
}
|
||||
|
||||
for mk, mv := range m {
|
||||
if err := e.EncodeString(mk); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := e.EncodeString(mv); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
for mk, mv := range m {
|
||||
if err := e.EncodeString(mk); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := e.Encode(mv); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *Encoder) encodeSortedMapStringString(m map[string]string) 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.EncodeString(m[k]); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
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))
|
||||
}
|
||||
if l < 65536 {
|
||||
return e.write2(codes.Map16, uint16(l))
|
||||
}
|
||||
return e.write4(codes.Map32, uint32(l))
|
||||
}
|
||||
|
||||
func encodeStructValue(e *Encoder, strct reflect.Value) error {
|
||||
structFields := structs.Fields(strct.Type(), e.structTag)
|
||||
if e.flags&structAsArrayFlag != 0 || structFields.AsArray {
|
||||
return encodeStructValueAsArray(e, strct, structFields.List)
|
||||
}
|
||||
fields := structFields.OmitEmpty(strct)
|
||||
|
||||
if err := e.EncodeMapLen(len(fields)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, f := range fields {
|
||||
if err := e.EncodeString(f.name); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := f.EncodeValue(e, strct); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func encodeStructValueAsArray(e *Encoder, strct reflect.Value, fields []*field) error {
|
||||
if err := e.EncodeArrayLen(len(fields)); err != nil {
|
||||
return err
|
||||
}
|
||||
for _, f := range fields {
|
||||
if err := f.EncodeValue(e, strct); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
244
vendor/github.com/vmihailenco/msgpack/v5/encode_number.go
сгенерированный
поставляемый
Обычный файл
244
vendor/github.com/vmihailenco/msgpack/v5/encode_number.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,244 @@
|
||||
package msgpack
|
||||
|
||||
import (
|
||||
"math"
|
||||
"reflect"
|
||||
|
||||
"github.com/vmihailenco/msgpack/v5/codes"
|
||||
)
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
func (e *Encoder) encodeUint8Cond(n uint8) error {
|
||||
if e.flags&useCompactIntsFlag != 0 {
|
||||
return e.EncodeUint(uint64(n))
|
||||
}
|
||||
return e.EncodeUint8(n)
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
func (e *Encoder) encodeUint16Cond(n uint16) error {
|
||||
if e.flags&useCompactIntsFlag != 0 {
|
||||
return e.EncodeUint(uint64(n))
|
||||
}
|
||||
return e.EncodeUint16(n)
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
func (e *Encoder) encodeUint32Cond(n uint32) error {
|
||||
if e.flags&useCompactIntsFlag != 0 {
|
||||
return e.EncodeUint(uint64(n))
|
||||
}
|
||||
return e.EncodeUint32(n)
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
func (e *Encoder) encodeUint64Cond(n uint64) error {
|
||||
if e.flags&useCompactIntsFlag != 0 {
|
||||
return e.EncodeUint(n)
|
||||
}
|
||||
return e.EncodeUint64(n)
|
||||
}
|
||||
|
||||
// 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))
|
||||
}
|
||||
|
||||
func (e *Encoder) encodeInt8Cond(n int8) error {
|
||||
if e.flags&useCompactIntsFlag != 0 {
|
||||
return e.EncodeInt(int64(n))
|
||||
}
|
||||
return e.EncodeInt8(n)
|
||||
}
|
||||
|
||||
// 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))
|
||||
}
|
||||
|
||||
func (e *Encoder) encodeInt16Cond(n int16) error {
|
||||
if e.flags&useCompactIntsFlag != 0 {
|
||||
return e.EncodeInt(int64(n))
|
||||
}
|
||||
return e.EncodeInt16(n)
|
||||
}
|
||||
|
||||
// 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))
|
||||
}
|
||||
|
||||
func (e *Encoder) encodeInt32Cond(n int32) error {
|
||||
if e.flags&useCompactIntsFlag != 0 {
|
||||
return e.EncodeInt(int64(n))
|
||||
}
|
||||
return e.EncodeInt32(n)
|
||||
}
|
||||
|
||||
// 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))
|
||||
}
|
||||
|
||||
func (e *Encoder) encodeInt64Cond(n int64) error {
|
||||
if e.flags&useCompactIntsFlag != 0 {
|
||||
return e.EncodeInt(n)
|
||||
}
|
||||
return e.EncodeInt64(n)
|
||||
}
|
||||
|
||||
// EncodeUnsignedNumber encodes an uint64 in 1, 2, 3, 5, or 9 bytes.
|
||||
// Type of the number is lost during encoding.
|
||||
func (e *Encoder) EncodeUint(n uint64) error {
|
||||
if n <= math.MaxInt8 {
|
||||
return e.w.WriteByte(byte(n))
|
||||
}
|
||||
if n <= math.MaxUint8 {
|
||||
return e.EncodeUint8(uint8(n))
|
||||
}
|
||||
if n <= math.MaxUint16 {
|
||||
return e.EncodeUint16(uint16(n))
|
||||
}
|
||||
if n <= math.MaxUint32 {
|
||||
return e.EncodeUint32(uint32(n))
|
||||
}
|
||||
return e.EncodeUint64(n)
|
||||
}
|
||||
|
||||
// EncodeNumber encodes an int64 in 1, 2, 3, 5, or 9 bytes.
|
||||
// Type of the number is lost during encoding.
|
||||
func (e *Encoder) EncodeInt(n int64) error {
|
||||
if n >= 0 {
|
||||
return e.EncodeUint(uint64(n))
|
||||
}
|
||||
if n >= int64(int8(codes.NegFixedNumLow)) {
|
||||
return e.w.WriteByte(byte(n))
|
||||
}
|
||||
if n >= math.MinInt8 {
|
||||
return e.EncodeInt8(int8(n))
|
||||
}
|
||||
if n >= math.MinInt16 {
|
||||
return e.EncodeInt16(int16(n))
|
||||
}
|
||||
if n >= math.MinInt32 {
|
||||
return e.EncodeInt32(int32(n))
|
||||
}
|
||||
return e.EncodeInt64(n)
|
||||
}
|
||||
|
||||
func (e *Encoder) EncodeFloat32(n float32) error {
|
||||
if e.flags&useCompactFloatsFlag != 0 {
|
||||
if float32(int64(n)) == n {
|
||||
return e.EncodeInt(int64(n))
|
||||
}
|
||||
}
|
||||
return e.write4(codes.Float, math.Float32bits(n))
|
||||
}
|
||||
|
||||
func (e *Encoder) EncodeFloat64(n float64) error {
|
||||
if e.flags&useCompactFloatsFlag != 0 {
|
||||
// Both NaN and Inf convert to int64(-0x8000000000000000)
|
||||
// If n is NaN then it never compares true with any other value
|
||||
// If n is Inf then it doesn't convert from int64 back to +/-Inf
|
||||
// In both cases the comparison works.
|
||||
if float64(int64(n)) == n {
|
||||
return e.EncodeInt(int64(n))
|
||||
}
|
||||
}
|
||||
return e.write8(codes.Double, math.Float64bits(n))
|
||||
}
|
||||
|
||||
func (e *Encoder) write1(code codes.Code, n uint8) error {
|
||||
e.buf = e.buf[:2]
|
||||
e.buf[0] = byte(code)
|
||||
e.buf[1] = n
|
||||
return e.write(e.buf)
|
||||
}
|
||||
|
||||
func (e *Encoder) write2(code codes.Code, n uint16) error {
|
||||
e.buf = e.buf[:3]
|
||||
e.buf[0] = byte(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 {
|
||||
e.buf = e.buf[:5]
|
||||
e.buf[0] = byte(code)
|
||||
e.buf[1] = byte(n >> 24)
|
||||
e.buf[2] = byte(n >> 16)
|
||||
e.buf[3] = byte(n >> 8)
|
||||
e.buf[4] = byte(n)
|
||||
return e.write(e.buf)
|
||||
}
|
||||
|
||||
func (e *Encoder) write8(code codes.Code, n uint64) error {
|
||||
e.buf = e.buf[:9]
|
||||
e.buf[0] = byte(code)
|
||||
e.buf[1] = byte(n >> 56)
|
||||
e.buf[2] = byte(n >> 48)
|
||||
e.buf[3] = byte(n >> 40)
|
||||
e.buf[4] = byte(n >> 32)
|
||||
e.buf[5] = byte(n >> 24)
|
||||
e.buf[6] = byte(n >> 16)
|
||||
e.buf[7] = byte(n >> 8)
|
||||
e.buf[8] = byte(n)
|
||||
return e.write(e.buf)
|
||||
}
|
||||
|
||||
func encodeUint8CondValue(e *Encoder, v reflect.Value) error {
|
||||
return e.encodeUint8Cond(uint8(v.Uint()))
|
||||
}
|
||||
|
||||
func encodeUint16CondValue(e *Encoder, v reflect.Value) error {
|
||||
return e.encodeUint16Cond(uint16(v.Uint()))
|
||||
}
|
||||
|
||||
func encodeUint32CondValue(e *Encoder, v reflect.Value) error {
|
||||
return e.encodeUint32Cond(uint32(v.Uint()))
|
||||
}
|
||||
|
||||
func encodeUint64CondValue(e *Encoder, v reflect.Value) error {
|
||||
return e.encodeUint64Cond(v.Uint())
|
||||
}
|
||||
|
||||
func encodeInt8CondValue(e *Encoder, v reflect.Value) error {
|
||||
return e.encodeInt8Cond(int8(v.Int()))
|
||||
}
|
||||
|
||||
func encodeInt16CondValue(e *Encoder, v reflect.Value) error {
|
||||
return e.encodeInt16Cond(int16(v.Int()))
|
||||
}
|
||||
|
||||
func encodeInt32CondValue(e *Encoder, v reflect.Value) error {
|
||||
return e.encodeInt32Cond(int32(v.Int()))
|
||||
}
|
||||
|
||||
func encodeInt64CondValue(e *Encoder, v reflect.Value) error {
|
||||
return e.encodeInt64Cond(v.Int())
|
||||
}
|
||||
|
||||
func encodeFloat32Value(e *Encoder, v reflect.Value) error {
|
||||
return e.EncodeFloat32(float32(v.Float()))
|
||||
}
|
||||
|
||||
func encodeFloat64Value(e *Encoder, v reflect.Value) error {
|
||||
return e.EncodeFloat64(v.Float())
|
||||
}
|
||||
131
vendor/github.com/vmihailenco/msgpack/v5/encode_slice.go
сгенерированный
поставляемый
Обычный файл
131
vendor/github.com/vmihailenco/msgpack/v5/encode_slice.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,131 @@
|
||||
package msgpack
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
|
||||
"github.com/vmihailenco/msgpack/v5/codes"
|
||||
)
|
||||
|
||||
var stringSliceType = reflect.TypeOf(([]string)(nil))
|
||||
|
||||
func encodeStringValue(e *Encoder, v reflect.Value) error {
|
||||
return e.EncodeString(v.String())
|
||||
}
|
||||
|
||||
func encodeByteSliceValue(e *Encoder, v reflect.Value) error {
|
||||
return e.EncodeBytes(v.Bytes())
|
||||
}
|
||||
|
||||
func encodeByteArrayValue(e *Encoder, v reflect.Value) error {
|
||||
if err := e.EncodeBytesLen(v.Len()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if v.CanAddr() {
|
||||
b := v.Slice(0, v.Len()).Bytes()
|
||||
return e.write(b)
|
||||
}
|
||||
|
||||
e.buf = grow(e.buf, v.Len())
|
||||
reflect.Copy(reflect.ValueOf(e.buf), v)
|
||||
return e.write(e.buf)
|
||||
}
|
||||
|
||||
func grow(b []byte, n int) []byte {
|
||||
if cap(b) >= n {
|
||||
return b[:n]
|
||||
}
|
||||
b = b[:cap(b)]
|
||||
b = append(b, make([]byte, n-len(b))...)
|
||||
return b
|
||||
}
|
||||
|
||||
func (e *Encoder) EncodeBytesLen(l int) error {
|
||||
if l < 256 {
|
||||
return e.write1(codes.Bin8, uint8(l))
|
||||
}
|
||||
if l < 65536 {
|
||||
return e.write2(codes.Bin16, uint16(l))
|
||||
}
|
||||
return e.write4(codes.Bin32, uint32(l))
|
||||
}
|
||||
|
||||
func (e *Encoder) encodeStrLen(l int) error {
|
||||
if l < 32 {
|
||||
return e.writeCode(codes.FixedStrLow | codes.Code(l))
|
||||
}
|
||||
if l < 256 {
|
||||
return e.write1(codes.Str8, uint8(l))
|
||||
}
|
||||
if l < 65536 {
|
||||
return e.write2(codes.Str16, uint16(l))
|
||||
}
|
||||
return e.write4(codes.Str32, uint32(l))
|
||||
}
|
||||
|
||||
func (e *Encoder) EncodeString(v string) error {
|
||||
if err := e.encodeStrLen(len(v)); err != nil {
|
||||
return err
|
||||
}
|
||||
return e.writeString(v)
|
||||
}
|
||||
|
||||
func (e *Encoder) EncodeBytes(v []byte) error {
|
||||
if v == nil {
|
||||
return e.EncodeNil()
|
||||
}
|
||||
if err := e.EncodeBytesLen(len(v)); err != nil {
|
||||
return err
|
||||
}
|
||||
return e.write(v)
|
||||
}
|
||||
|
||||
func (e *Encoder) EncodeArrayLen(l int) error {
|
||||
if l < 16 {
|
||||
return e.writeCode(codes.FixedArrayLow | codes.Code(l))
|
||||
}
|
||||
if l < 65536 {
|
||||
return e.write2(codes.Array16, uint16(l))
|
||||
}
|
||||
return e.write4(codes.Array32, uint32(l))
|
||||
}
|
||||
|
||||
func encodeStringSliceValue(e *Encoder, v reflect.Value) error {
|
||||
ss := v.Convert(stringSliceType).Interface().([]string)
|
||||
return e.encodeStringSlice(ss)
|
||||
}
|
||||
|
||||
func (e *Encoder) encodeStringSlice(s []string) error {
|
||||
if s == nil {
|
||||
return e.EncodeNil()
|
||||
}
|
||||
if err := e.EncodeArrayLen(len(s)); err != nil {
|
||||
return err
|
||||
}
|
||||
for _, v := range s {
|
||||
if err := e.EncodeString(v); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func encodeSliceValue(e *Encoder, v reflect.Value) error {
|
||||
if v.IsNil() {
|
||||
return e.EncodeNil()
|
||||
}
|
||||
return encodeArrayValue(e, v)
|
||||
}
|
||||
|
||||
func encodeArrayValue(e *Encoder, v reflect.Value) error {
|
||||
l := v.Len()
|
||||
if err := e.EncodeArrayLen(l); err != nil {
|
||||
return err
|
||||
}
|
||||
for i := 0; i < l; i++ {
|
||||
if err := e.EncodeValue(v.Index(i)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
216
vendor/github.com/vmihailenco/msgpack/v5/encode_value.go
сгенерированный
поставляемый
Обычный файл
216
vendor/github.com/vmihailenco/msgpack/v5/encode_value.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,216 @@
|
||||
package msgpack
|
||||
|
||||
import (
|
||||
"encoding"
|
||||
"fmt"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
var valueEncoders []encoderFunc
|
||||
|
||||
//nolint:gochecknoinits
|
||||
func init() {
|
||||
valueEncoders = []encoderFunc{
|
||||
reflect.Bool: encodeBoolValue,
|
||||
reflect.Int: encodeInt64CondValue,
|
||||
reflect.Int8: encodeInt8CondValue,
|
||||
reflect.Int16: encodeInt16CondValue,
|
||||
reflect.Int32: encodeInt32CondValue,
|
||||
reflect.Int64: encodeInt64CondValue,
|
||||
reflect.Uint: encodeUint64CondValue,
|
||||
reflect.Uint8: encodeUint8CondValue,
|
||||
reflect.Uint16: encodeUint16CondValue,
|
||||
reflect.Uint32: encodeUint32CondValue,
|
||||
reflect.Uint64: encodeUint64CondValue,
|
||||
reflect.Float32: encodeFloat32Value,
|
||||
reflect.Float64: encodeFloat64Value,
|
||||
reflect.Complex64: encodeUnsupportedValue,
|
||||
reflect.Complex128: encodeUnsupportedValue,
|
||||
reflect.Array: encodeArrayValue,
|
||||
reflect.Chan: encodeUnsupportedValue,
|
||||
reflect.Func: encodeUnsupportedValue,
|
||||
reflect.Interface: encodeInterfaceValue,
|
||||
reflect.Map: encodeMapValue,
|
||||
reflect.Ptr: encodeUnsupportedValue,
|
||||
reflect.Slice: encodeSliceValue,
|
||||
reflect.String: encodeStringValue,
|
||||
reflect.Struct: encodeStructValue,
|
||||
reflect.UnsafePointer: encodeUnsupportedValue,
|
||||
}
|
||||
}
|
||||
|
||||
func getEncoder(typ reflect.Type) encoderFunc {
|
||||
if v, ok := typeEncMap.Load(typ); ok {
|
||||
return v.(encoderFunc)
|
||||
}
|
||||
fn := _getEncoder(typ)
|
||||
typeEncMap.Store(typ, fn)
|
||||
return fn
|
||||
}
|
||||
|
||||
func _getEncoder(typ reflect.Type) encoderFunc {
|
||||
kind := typ.Kind()
|
||||
|
||||
if kind == reflect.Ptr {
|
||||
if _, ok := typeEncMap.Load(typ.Elem()); ok {
|
||||
return ptrEncoderFunc(typ)
|
||||
}
|
||||
}
|
||||
|
||||
if typ.Implements(customEncoderType) {
|
||||
return encodeCustomValue
|
||||
}
|
||||
if typ.Implements(marshalerType) {
|
||||
return marshalValue
|
||||
}
|
||||
if typ.Implements(binaryMarshalerType) {
|
||||
return marshalBinaryValue
|
||||
}
|
||||
|
||||
// Addressable struct field value.
|
||||
if kind != reflect.Ptr {
|
||||
ptr := reflect.PtrTo(typ)
|
||||
if ptr.Implements(customEncoderType) {
|
||||
return encodeCustomValuePtr
|
||||
}
|
||||
if ptr.Implements(marshalerType) {
|
||||
return marshalValuePtr
|
||||
}
|
||||
if ptr.Implements(binaryMarshalerType) {
|
||||
return marshalBinaryValuePtr
|
||||
}
|
||||
}
|
||||
|
||||
if typ == errorType {
|
||||
return encodeErrorValue
|
||||
}
|
||||
|
||||
switch kind {
|
||||
case reflect.Ptr:
|
||||
return ptrEncoderFunc(typ)
|
||||
case reflect.Slice:
|
||||
elem := typ.Elem()
|
||||
if elem.Kind() == reflect.Uint8 {
|
||||
return encodeByteSliceValue
|
||||
}
|
||||
if elem == stringType {
|
||||
return encodeStringSliceValue
|
||||
}
|
||||
case reflect.Array:
|
||||
if typ.Elem().Kind() == reflect.Uint8 {
|
||||
return encodeByteArrayValue
|
||||
}
|
||||
case reflect.Map:
|
||||
if typ.Key() == stringType {
|
||||
switch typ.Elem() {
|
||||
case stringType:
|
||||
return encodeMapStringStringValue
|
||||
case interfaceType:
|
||||
return encodeMapStringInterfaceValue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return valueEncoders[kind]
|
||||
}
|
||||
|
||||
func ptrEncoderFunc(typ reflect.Type) encoderFunc {
|
||||
encoder := getEncoder(typ.Elem())
|
||||
return func(e *Encoder, v reflect.Value) error {
|
||||
if v.IsNil() {
|
||||
return e.EncodeNil()
|
||||
}
|
||||
return encoder(e, v.Elem())
|
||||
}
|
||||
}
|
||||
|
||||
func encodeCustomValuePtr(e *Encoder, v reflect.Value) error {
|
||||
if !v.CanAddr() {
|
||||
return fmt.Errorf("msgpack: Encode(non-addressable %T)", v.Interface())
|
||||
}
|
||||
encoder := v.Addr().Interface().(CustomEncoder)
|
||||
return encoder.EncodeMsgpack(e)
|
||||
}
|
||||
|
||||
func encodeCustomValue(e *Encoder, v reflect.Value) error {
|
||||
if nilable(v) && v.IsNil() {
|
||||
return e.EncodeNil()
|
||||
}
|
||||
|
||||
encoder := v.Interface().(CustomEncoder)
|
||||
return encoder.EncodeMsgpack(e)
|
||||
}
|
||||
|
||||
func marshalValuePtr(e *Encoder, v reflect.Value) error {
|
||||
if !v.CanAddr() {
|
||||
return fmt.Errorf("msgpack: Encode(non-addressable %T)", v.Interface())
|
||||
}
|
||||
return marshalValue(e, v.Addr())
|
||||
}
|
||||
|
||||
func marshalValue(e *Encoder, v reflect.Value) error {
|
||||
if nilable(v) && v.IsNil() {
|
||||
return e.EncodeNil()
|
||||
}
|
||||
|
||||
marshaler := v.Interface().(Marshaler)
|
||||
b, err := marshaler.MarshalMsgpack()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = e.w.Write(b)
|
||||
return err
|
||||
}
|
||||
|
||||
func encodeBoolValue(e *Encoder, v reflect.Value) error {
|
||||
return e.EncodeBool(v.Bool())
|
||||
}
|
||||
|
||||
func encodeInterfaceValue(e *Encoder, v reflect.Value) error {
|
||||
if v.IsNil() {
|
||||
return e.EncodeNil()
|
||||
}
|
||||
return e.EncodeValue(v.Elem())
|
||||
}
|
||||
|
||||
func encodeErrorValue(e *Encoder, v reflect.Value) error {
|
||||
if v.IsNil() {
|
||||
return e.EncodeNil()
|
||||
}
|
||||
return e.EncodeString(v.Interface().(error).Error())
|
||||
}
|
||||
|
||||
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() {
|
||||
case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
func marshalBinaryValuePtr(e *Encoder, v reflect.Value) error {
|
||||
if !v.CanAddr() {
|
||||
return fmt.Errorf("msgpack: Encode(non-addressable %T)", v.Interface())
|
||||
}
|
||||
return marshalBinaryValue(e, v.Addr())
|
||||
}
|
||||
|
||||
func marshalBinaryValue(e *Encoder, v reflect.Value) error {
|
||||
if nilable(v) && v.IsNil() {
|
||||
return e.EncodeNil()
|
||||
}
|
||||
|
||||
marshaler := v.Interface().(encoding.BinaryMarshaler)
|
||||
data, err := marshaler.MarshalBinary()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return e.EncodeBytes(data)
|
||||
}
|
||||
244
vendor/github.com/vmihailenco/msgpack/v5/ext.go
сгенерированный
поставляемый
Обычный файл
244
vendor/github.com/vmihailenco/msgpack/v5/ext.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,244 @@
|
||||
package msgpack
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"sync"
|
||||
|
||||
"github.com/vmihailenco/msgpack/v5/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
|
||||
}
|
||||
15
vendor/github.com/vmihailenco/msgpack/v5/go.mod
сгенерированный
поставляемый
Обычный файл
15
vendor/github.com/vmihailenco/msgpack/v5/go.mod
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,15 @@
|
||||
module github.com/vmihailenco/msgpack/v5
|
||||
|
||||
require (
|
||||
github.com/davecgh/go-spew v1.1.1
|
||||
github.com/golang/protobuf v1.3.4 // indirect
|
||||
github.com/kr/pretty v0.1.0 // indirect
|
||||
github.com/stretchr/testify v1.5.1
|
||||
github.com/vmihailenco/msgpack/v4 v4.3.11
|
||||
github.com/vmihailenco/tagparser v0.1.1
|
||||
golang.org/x/net v0.0.0-20200301022130-244492dfa37a // indirect
|
||||
google.golang.org/appengine v1.6.5
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127
|
||||
)
|
||||
|
||||
go 1.11
|
||||
36
vendor/github.com/vmihailenco/msgpack/v5/go.sum
сгенерированный
поставляемый
Обычный файл
36
vendor/github.com/vmihailenco/msgpack/v5/go.sum
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,36 @@
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.4 h1:87PNWwrRvUSnqS4dlcBU/ftvOIBep4sYuBLlh6rX2wk=
|
||||
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/vmihailenco/msgpack v4.0.4+incompatible h1:dSLoQfGFAo3F6OoNhwUmLwVgaUXK79GlxNBwueZn0xI=
|
||||
github.com/vmihailenco/msgpack/v4 v4.3.11 h1:Q47CePddpNGNhk4GCnAx9DDtASi2rasatE0cd26cZoE=
|
||||
github.com/vmihailenco/msgpack/v4 v4.3.11/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4=
|
||||
github.com/vmihailenco/tagparser v0.1.1 h1:quXMXlA39OCbd2wAdTsGDlK9RkOk6Wuw+x37wVyIuWY=
|
||||
github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.0.0-20200301022130-244492dfa37a h1:GuSPYbZzB5/dcLNCwLQLsg3obCJtX9IJhpXkvY7kzk0=
|
||||
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
google.golang.org/appengine v1.6.5 h1:tycE03LOZYQNhDpS27tcQdAzLCVMaj7QT2SXxebnpCM=
|
||||
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
232
vendor/github.com/vmihailenco/msgpack/v5/intern.go
сгенерированный
поставляемый
Обычный файл
232
vendor/github.com/vmihailenco/msgpack/v5/intern.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,232 @@
|
||||
package msgpack
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
"reflect"
|
||||
|
||||
"github.com/vmihailenco/msgpack/v5/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 {
|
||||
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
|
||||
}
|
||||
37
vendor/github.com/vmihailenco/msgpack/v5/msgpack.go
сгенерированный
поставляемый
Обычный файл
37
vendor/github.com/vmihailenco/msgpack/v5/msgpack.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,37 @@
|
||||
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
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
type RawMessage []byte
|
||||
|
||||
var _ CustomEncoder = (RawMessage)(nil)
|
||||
var _ 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
|
||||
}
|
||||
13
vendor/github.com/vmihailenco/msgpack/v5/safe.go
сгенерированный
поставляемый
Обычный файл
13
vendor/github.com/vmihailenco/msgpack/v5/safe.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,13 @@
|
||||
// +build appengine
|
||||
|
||||
package msgpack
|
||||
|
||||
// bytesToString converts byte slice to string.
|
||||
func bytesToString(b []byte) string {
|
||||
return string(b)
|
||||
}
|
||||
|
||||
// stringToBytes converts string to byte slice.
|
||||
func stringToBytes(s string) []byte {
|
||||
return []byte(s)
|
||||
}
|
||||
155
vendor/github.com/vmihailenco/msgpack/v5/time.go
сгенерированный
поставляемый
Обычный файл
155
vendor/github.com/vmihailenco/msgpack/v5/time.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,155 @@
|
||||
package msgpack
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"time"
|
||||
|
||||
"github.com/vmihailenco/msgpack/v5/codes"
|
||||
)
|
||||
|
||||
var timeExtID int8 = -1
|
||||
|
||||
var timePtrType = reflect.TypeOf((*time.Time)(nil))
|
||||
|
||||
//nolint:gochecknoinits
|
||||
func init() {
|
||||
registerExt(timeExtID, timePtrType.Elem(), encodeTimeValue, decodeTimeValue)
|
||||
}
|
||||
|
||||
func (e *Encoder) EncodeTime(tm time.Time) error {
|
||||
b := e.encodeTime(tm)
|
||||
if err := e.encodeExtLen(len(b)); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := e.w.WriteByte(byte(timeExtID)); err != nil {
|
||||
return err
|
||||
}
|
||||
return e.write(b)
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
b := e.timeBuf[:12]
|
||||
binary.BigEndian.PutUint32(b, uint32(tm.Nanosecond()))
|
||||
binary.BigEndian.PutUint64(b[4:], secs)
|
||||
return b
|
||||
}
|
||||
|
||||
func (d *Decoder) DecodeTime() (time.Time, error) {
|
||||
tm, err := d.decodeTime()
|
||||
if err != nil {
|
||||
return tm, err
|
||||
}
|
||||
|
||||
if tm.IsZero() {
|
||||
// Assume that 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
|
||||
}
|
||||
}
|
||||
|
||||
b, err := d.readN(extLen)
|
||||
if err != nil {
|
||||
return time.Time{}, err
|
||||
}
|
||||
|
||||
switch len(b) {
|
||||
case 4:
|
||||
sec := binary.BigEndian.Uint32(b)
|
||||
return time.Unix(int64(sec), 0), nil
|
||||
case 8:
|
||||
sec := binary.BigEndian.Uint64(b)
|
||||
nsec := int64(sec >> 34)
|
||||
sec &= 0x00000003ffffffff
|
||||
return time.Unix(int64(sec), nsec), nil
|
||||
case 12:
|
||||
nsec := binary.BigEndian.Uint32(b)
|
||||
sec := binary.BigEndian.Uint64(b[4:])
|
||||
return time.Unix(int64(sec), int64(nsec)), nil
|
||||
default:
|
||||
err = fmt.Errorf("msgpack: invalid ext len=%d decoding time", extLen)
|
||||
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
|
||||
}
|
||||
385
vendor/github.com/vmihailenco/msgpack/v5/types.go
сгенерированный
поставляемый
Обычный файл
385
vendor/github.com/vmihailenco/msgpack/v5/types.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,385 @@
|
||||
package msgpack
|
||||
|
||||
import (
|
||||
"encoding"
|
||||
"fmt"
|
||||
"log"
|
||||
"reflect"
|
||||
"sync"
|
||||
|
||||
"github.com/vmihailenco/tagparser"
|
||||
)
|
||||
|
||||
var errorType = reflect.TypeOf((*error)(nil)).Elem()
|
||||
|
||||
var (
|
||||
customEncoderType = reflect.TypeOf((*CustomEncoder)(nil)).Elem()
|
||||
customDecoderType = reflect.TypeOf((*CustomDecoder)(nil)).Elem()
|
||||
)
|
||||
|
||||
var (
|
||||
marshalerType = reflect.TypeOf((*Marshaler)(nil)).Elem()
|
||||
unmarshalerType = reflect.TypeOf((*Unmarshaler)(nil)).Elem()
|
||||
)
|
||||
|
||||
var (
|
||||
binaryMarshalerType = reflect.TypeOf((*encoding.BinaryMarshaler)(nil)).Elem()
|
||||
binaryUnmarshalerType = reflect.TypeOf((*encoding.BinaryUnmarshaler)(nil)).Elem()
|
||||
)
|
||||
|
||||
type (
|
||||
encoderFunc func(*Encoder, reflect.Value) error
|
||||
decoderFunc func(*Decoder, reflect.Value) error
|
||||
)
|
||||
|
||||
var (
|
||||
typeEncMap sync.Map
|
||||
typeDecMap sync.Map
|
||||
)
|
||||
|
||||
// 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.
|
||||
func Register(value interface{}, enc encoderFunc, dec decoderFunc) {
|
||||
typ := reflect.TypeOf(value)
|
||||
if enc != nil {
|
||||
typeEncMap.Store(typ, enc)
|
||||
}
|
||||
if dec != nil {
|
||||
typeDecMap.Store(typ, dec)
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const defaultStructTag = "msgpack"
|
||||
|
||||
var structs = newStructCache()
|
||||
|
||||
type structCache struct {
|
||||
m sync.Map
|
||||
}
|
||||
|
||||
type structCacheKey struct {
|
||||
tag string
|
||||
typ reflect.Type
|
||||
}
|
||||
|
||||
func newStructCache() *structCache {
|
||||
return &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, tag)
|
||||
m.m.Store(key, fs)
|
||||
|
||||
return fs
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
type field struct {
|
||||
name string
|
||||
index []int
|
||||
omitEmpty bool
|
||||
encoder encoderFunc
|
||||
decoder decoderFunc
|
||||
}
|
||||
|
||||
func (f *field) Omit(strct reflect.Value) bool {
|
||||
v, ok := fieldByIndex(strct, f.index)
|
||||
if !ok {
|
||||
return true
|
||||
}
|
||||
return f.omitEmpty && isEmptyValue(v)
|
||||
}
|
||||
|
||||
func (f *field) EncodeValue(e *Encoder, strct reflect.Value) error {
|
||||
v, ok := fieldByIndex(strct, f.index)
|
||||
if !ok {
|
||||
return e.EncodeNil()
|
||||
}
|
||||
return f.encoder(e, v)
|
||||
}
|
||||
|
||||
func (f *field) DecodeValue(d *Decoder, strct reflect.Value) error {
|
||||
v := fieldByIndexAlloc(strct, f.index)
|
||||
return f.decoder(d, v)
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
type fields struct {
|
||||
Type reflect.Type
|
||||
Map map[string]*field
|
||||
List []*field
|
||||
AsArray bool
|
||||
|
||||
hasOmitEmpty bool
|
||||
}
|
||||
|
||||
func newFields(typ reflect.Type) *fields {
|
||||
return &fields{
|
||||
Type: typ,
|
||||
Map: make(map[string]*field, typ.NumField()),
|
||||
List: make([]*field, 0, typ.NumField()),
|
||||
}
|
||||
}
|
||||
|
||||
func (fs *fields) Add(field *field) {
|
||||
fs.warnIfFieldExists(field.name)
|
||||
fs.Map[field.name] = field
|
||||
fs.List = append(fs.List, field)
|
||||
if field.omitEmpty {
|
||||
fs.hasOmitEmpty = true
|
||||
}
|
||||
}
|
||||
|
||||
func (fs *fields) warnIfFieldExists(name string) {
|
||||
if _, ok := fs.Map[name]; ok {
|
||||
log.Printf("msgpack: %s already has field=%s", fs.Type, name)
|
||||
}
|
||||
}
|
||||
|
||||
func (fs *fields) OmitEmpty(strct reflect.Value) []*field {
|
||||
if !fs.hasOmitEmpty {
|
||||
return fs.List
|
||||
}
|
||||
|
||||
fields := make([]*field, 0, len(fs.List))
|
||||
|
||||
for _, f := range fs.List {
|
||||
if !f.Omit(strct) {
|
||||
fields = append(fields, f)
|
||||
}
|
||||
}
|
||||
|
||||
return 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(defaultStructTag)
|
||||
if tagStr == "" && fallbackTag != "" {
|
||||
tagStr = f.Tag.Get(fallbackTag)
|
||||
}
|
||||
|
||||
tag := tagparser.Parse(tagStr)
|
||||
if tag.Name == "-" {
|
||||
continue
|
||||
}
|
||||
|
||||
if f.Name == "_msgpack" {
|
||||
if tag.HasOption("asArray") {
|
||||
fs.AsArray = true
|
||||
}
|
||||
if tag.HasOption("omitempty") {
|
||||
omitEmpty = true
|
||||
}
|
||||
}
|
||||
|
||||
if f.PkgPath != "" && !f.Anonymous {
|
||||
continue
|
||||
}
|
||||
|
||||
field := &field{
|
||||
name: tag.Name,
|
||||
index: f.Index,
|
||||
omitEmpty: omitEmpty || tag.HasOption("omitempty"),
|
||||
}
|
||||
|
||||
if tag.HasOption("intern") {
|
||||
switch f.Type.Kind() {
|
||||
case reflect.Interface:
|
||||
field.encoder = encodeInternInterfaceValue
|
||||
field.decoder = decodeInternInterfaceValue
|
||||
case reflect.String:
|
||||
field.encoder = encodeInternStringValue
|
||||
field.decoder = decodeInternStringValue
|
||||
default:
|
||||
err := fmt.Errorf("msgpack: intern strings are not supported on %s", f.Type)
|
||||
panic(err)
|
||||
}
|
||||
} else {
|
||||
field.encoder = getEncoder(f.Type)
|
||||
field.decoder = getDecoder(f.Type)
|
||||
}
|
||||
|
||||
if field.name == "" {
|
||||
field.name = f.Name
|
||||
}
|
||||
|
||||
if f.Anonymous && !tag.HasOption("noinline") {
|
||||
inline := tag.HasOption("inline")
|
||||
if inline {
|
||||
inlineFields(fs, f.Type, field, fallbackTag)
|
||||
} else {
|
||||
inline = shouldInline(fs, f.Type, field, fallbackTag)
|
||||
}
|
||||
|
||||
if inline {
|
||||
if _, ok := fs.Map[field.name]; ok {
|
||||
log.Printf("msgpack: %s already has field=%s", fs.Type, field.name)
|
||||
}
|
||||
fs.Map[field.name] = field
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
fs.Add(field)
|
||||
|
||||
if alias, ok := tag.Options["alias"]; ok {
|
||||
fs.warnIfFieldExists(alias)
|
||||
fs.Map[alias] = field
|
||||
}
|
||||
}
|
||||
return fs
|
||||
}
|
||||
|
||||
var (
|
||||
encodeStructValuePtr uintptr
|
||||
decodeStructValuePtr uintptr
|
||||
)
|
||||
|
||||
//nolint:gochecknoinits
|
||||
func init() {
|
||||
encodeStructValuePtr = reflect.ValueOf(encodeStructValue).Pointer()
|
||||
decodeStructValuePtr = reflect.ValueOf(decodeStructValue).Pointer()
|
||||
}
|
||||
|
||||
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.
|
||||
continue
|
||||
}
|
||||
field.index = append(f.index, field.index...)
|
||||
fs.Add(field)
|
||||
}
|
||||
}
|
||||
|
||||
func shouldInline(fs *fields, typ reflect.Type, f *field, tag string) bool {
|
||||
var encoder encoderFunc
|
||||
var decoder decoderFunc
|
||||
|
||||
if typ.Kind() == reflect.Struct {
|
||||
encoder = f.encoder
|
||||
decoder = f.decoder
|
||||
} else {
|
||||
for typ.Kind() == reflect.Ptr {
|
||||
typ = typ.Elem()
|
||||
encoder = getEncoder(typ)
|
||||
decoder = getDecoder(typ)
|
||||
}
|
||||
if typ.Kind() != reflect.Struct {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
if reflect.ValueOf(encoder).Pointer() != encodeStructValuePtr {
|
||||
return false
|
||||
}
|
||||
if reflect.ValueOf(decoder).Pointer() != decodeStructValuePtr {
|
||||
return false
|
||||
}
|
||||
|
||||
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.
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
for _, field := range inlinedFields {
|
||||
field.index = append(f.index, field.index...)
|
||||
fs.Add(field)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func isEmptyValue(v reflect.Value) bool {
|
||||
switch v.Kind() {
|
||||
case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
|
||||
return v.Len() == 0
|
||||
case reflect.Bool:
|
||||
return !v.Bool()
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
return v.Int() == 0
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||
return v.Uint() == 0
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return v.Float() == 0
|
||||
case reflect.Interface, reflect.Ptr:
|
||||
return v.IsNil()
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func fieldByIndex(v reflect.Value, index []int) (_ reflect.Value, ok bool) {
|
||||
if len(index) == 1 {
|
||||
return v.Field(index[0]), true
|
||||
}
|
||||
|
||||
for i, idx := range index {
|
||||
if i > 0 {
|
||||
if v.Kind() == reflect.Ptr {
|
||||
if v.IsNil() {
|
||||
return v, false
|
||||
}
|
||||
v = v.Elem()
|
||||
}
|
||||
}
|
||||
v = v.Field(idx)
|
||||
}
|
||||
|
||||
return v, true
|
||||
}
|
||||
|
||||
func fieldByIndexAlloc(v reflect.Value, index []int) reflect.Value {
|
||||
if len(index) == 1 {
|
||||
return v.Field(index[0])
|
||||
}
|
||||
|
||||
for i, idx := range index {
|
||||
if i > 0 {
|
||||
var ok bool
|
||||
v, ok = indirectNil(v)
|
||||
if !ok {
|
||||
return v
|
||||
}
|
||||
}
|
||||
v = v.Field(idx)
|
||||
}
|
||||
|
||||
return v
|
||||
}
|
||||
|
||||
func indirectNil(v reflect.Value) (reflect.Value, bool) {
|
||||
if v.Kind() == reflect.Ptr {
|
||||
if v.IsNil() {
|
||||
if !v.CanSet() {
|
||||
return v, false
|
||||
}
|
||||
elemType := v.Type().Elem()
|
||||
if elemType.Kind() != reflect.Struct {
|
||||
return v, false
|
||||
}
|
||||
v.Set(reflect.New(elemType))
|
||||
}
|
||||
v = v.Elem()
|
||||
}
|
||||
return v, true
|
||||
}
|
||||
22
vendor/github.com/vmihailenco/msgpack/v5/unsafe.go
сгенерированный
поставляемый
Обычный файл
22
vendor/github.com/vmihailenco/msgpack/v5/unsafe.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,22 @@
|
||||
// +build !appengine
|
||||
|
||||
package msgpack
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// bytesToString converts byte slice to string.
|
||||
func bytesToString(b []byte) string { //nolint:deadcode,unused
|
||||
return *(*string)(unsafe.Pointer(&b))
|
||||
}
|
||||
|
||||
// stringToBytes converts string to byte slice.
|
||||
func stringToBytes(s string) []byte {
|
||||
return *(*[]byte)(unsafe.Pointer(
|
||||
&struct {
|
||||
string
|
||||
Cap int
|
||||
}{s, len(s)},
|
||||
))
|
||||
}
|
||||
Ссылка в новой задаче
Block a user