Initial QSfera import
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
# Binaries for programs and plugins
|
||||
*.exe
|
||||
*.exe~
|
||||
*.dll
|
||||
*.so
|
||||
*.dylib
|
||||
|
||||
# Test binary, build with `go test -c`
|
||||
*.test
|
||||
|
||||
# Output of the go coverage tool, specifically when used with LiteIDE
|
||||
*.out
|
||||
|
||||
# coverage
|
||||
*.coverprofile
|
||||
|
||||
.DS_Store
|
||||
.idea
|
||||
.vscode
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2025 Masayuki Shamoto
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
+120
@@ -0,0 +1,120 @@
|
||||
# MessagePack for Golang
|
||||
|
||||
[](https://pkg.go.dev/github.com/shamaton/msgpack)
|
||||

|
||||
[](https://goreportcard.com/report/github.com/shamaton/msgpack)
|
||||
[](https://codecov.io/gh/shamaton/msgpack)
|
||||
[](https://app.fossa.com/projects/git%2Bgithub.com%2Fshamaton%2Fmsgpack?ref=badge_shield)
|
||||
|
||||
## 📣 Announcement: `time.Time` decoding defaults to **UTC** in v3
|
||||
Starting with **v3.0.0**, when decoding MessagePack **Timestamp** into Go’s `time.Time`,
|
||||
the default `Location` will be **UTC** (previously `Local`). The instant is unchanged.
|
||||
To keep the old behavior, use `SetDecodedTimeAsLocal()`.
|
||||
|
||||
## Features
|
||||
* Supported types : primitive / array / slice / struct / map / interface{} and time.Time
|
||||
* Renaming fields via `msgpack:"field_name"`
|
||||
* Omitting fields via `msgpack:"-"`
|
||||
* Omitting empty fields via `msgpack:"field_name,omitempty"`
|
||||
* Supports extend encoder / decoder [(example)](./msgpack_example_test.go)
|
||||
* Can also Encoding / Decoding struct as array
|
||||
|
||||
## Installation
|
||||
|
||||
Current version is **msgpack/v2**.
|
||||
```sh
|
||||
go get -u github.com/shamaton/msgpack/v2
|
||||
```
|
||||
|
||||
## Quick Start
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/shamaton/msgpack/v2"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type Struct struct {
|
||||
String string
|
||||
}
|
||||
|
||||
// simple
|
||||
func main() {
|
||||
v := Struct{String: "msgpack"}
|
||||
|
||||
d, err := msgpack.Marshal(v)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
r := Struct{}
|
||||
if err = msgpack.Unmarshal(d, &r); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// streaming
|
||||
func handle(w http.ResponseWriter, r *http.Request) {
|
||||
var body Struct
|
||||
if err := msgpack.UnmarshalRead(r, &body); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if err := msgpack.MarshalWrite(w, body); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 📣 Announcement: `time.Time` decoding defaults to **UTC** in v3
|
||||
|
||||
**TL;DR:** Starting with **v3.0.0**, when decoding MessagePack **Timestamp** into Go’s `time.Time`, the default `Location` will be **UTC** (previously `Local`). The **instant** is unchanged—only the display/location changes. This avoids host-dependent differences and aligns with common distributed systems practice.
|
||||
|
||||
### What is changing?
|
||||
|
||||
* **Before (v2.x):** Decoded `time.Time` defaults to `Local`.
|
||||
* **After (v3.0.0):** Decoded `time.Time` defaults to **UTC**.
|
||||
|
||||
MessagePack’s Timestamp encodes an **instant** (epoch seconds + nanoseconds) and does **not** carry timezone info. Your data’s point in time is the same; only `time.Time.Location()` differs.
|
||||
|
||||
### Why?
|
||||
|
||||
* Eliminate environment-dependent behavior (e.g., different hosts showing different local zones).
|
||||
* Make “UTC by default” the safe, predictable baseline for logs, APIs, and distributed apps.
|
||||
|
||||
### Who is affected?
|
||||
|
||||
* Apps that **display local time** without explicitly converting from UTC.
|
||||
* If your code already normalizes to UTC or explicitly sets a location, you’re likely unaffected.
|
||||
|
||||
### Keep the old behavior (Local)
|
||||
|
||||
If you want the v2 behavior on v3:
|
||||
|
||||
```go
|
||||
msgpack.SetDecodedTimeAsLocal()
|
||||
```
|
||||
|
||||
Or convert after the fact:
|
||||
|
||||
```go
|
||||
var t time.Time
|
||||
_ = msgpack.Unmarshal(data, &t)
|
||||
t = t.In(time.Local)
|
||||
```
|
||||
|
||||
### Preview the new behavior on v2 (optional)
|
||||
|
||||
You can opt into UTC today on v2.x:
|
||||
|
||||
```go
|
||||
msgpack.SetDecodedTimeAsUTC()
|
||||
```
|
||||
|
||||
## Benchmark
|
||||
This result made from [shamaton/msgpack_bench](https://github.com/shamaton/msgpack_bench)
|
||||
|
||||

|
||||
|
||||
## License
|
||||
|
||||
This library is under the MIT License.
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
coverage:
|
||||
status:
|
||||
project: off
|
||||
patch: off
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
package msgpack
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/shamaton/msgpack/v2/internal/decoding"
|
||||
streamdecoding "github.com/shamaton/msgpack/v2/internal/stream/decoding"
|
||||
)
|
||||
|
||||
// UnmarshalAsMap decodes data that is encoded as map format.
|
||||
// This is the same thing that StructAsArray sets false.
|
||||
func UnmarshalAsMap(data []byte, v interface{}) error {
|
||||
return decoding.Decode(data, v, false)
|
||||
}
|
||||
|
||||
// UnmarshalAsArray decodes data that is encoded as array format.
|
||||
// This is the same thing that StructAsArray sets true.
|
||||
func UnmarshalAsArray(data []byte, v interface{}) error {
|
||||
return decoding.Decode(data, v, true)
|
||||
}
|
||||
|
||||
// UnmarshalReadAsMap decodes from stream. stream data expects map format.
|
||||
// This is the same thing that StructAsArray sets false.
|
||||
func UnmarshalReadAsMap(r io.Reader, v interface{}) error {
|
||||
return streamdecoding.Decode(r, v, false)
|
||||
}
|
||||
|
||||
// UnmarshalReadAsArray decodes from stream. stream data expects array format.
|
||||
// This is the same thing that StructAsArray sets true.
|
||||
func UnmarshalReadAsArray(r io.Reader, v interface{}) error {
|
||||
return streamdecoding.Decode(r, v, true)
|
||||
}
|
||||
+87
@@ -0,0 +1,87 @@
|
||||
package def
|
||||
|
||||
// IntSize : 32 or 64
|
||||
const IntSize = 32 << (^uint(0) >> 63)
|
||||
|
||||
var IsIntSize32 = IntSize == 32
|
||||
|
||||
// message pack format
|
||||
const (
|
||||
PositiveFixIntMin = 0x00
|
||||
PositiveFixIntMax = 0x7f
|
||||
|
||||
FixMap = 0x80
|
||||
FixArray = 0x90
|
||||
FixStr = 0xa0
|
||||
|
||||
Nil = 0xc0
|
||||
|
||||
False = 0xc2
|
||||
True = 0xc3
|
||||
|
||||
Bin8 = 0xc4
|
||||
Bin16 = 0xc5
|
||||
Bin32 = 0xc6
|
||||
|
||||
Ext8 = 0xc7
|
||||
Ext16 = 0xc8
|
||||
Ext32 = 0xc9
|
||||
|
||||
Float32 = 0xca
|
||||
Float64 = 0xcb
|
||||
|
||||
Uint8 = 0xcc
|
||||
Uint16 = 0xcd
|
||||
Uint32 = 0xce
|
||||
Uint64 = 0xcf
|
||||
|
||||
Int8 = 0xd0
|
||||
Int16 = 0xd1
|
||||
Int32 = 0xd2
|
||||
Int64 = 0xd3
|
||||
|
||||
Fixext1 = 0xd4
|
||||
Fixext2 = 0xd5
|
||||
Fixext4 = 0xd6
|
||||
Fixext8 = 0xd7
|
||||
Fixext16 = 0xd8
|
||||
|
||||
Str8 = 0xd9
|
||||
Str16 = 0xda
|
||||
Str32 = 0xdb
|
||||
|
||||
Array16 = 0xdc
|
||||
Array32 = 0xdd
|
||||
|
||||
Map16 = 0xde
|
||||
Map32 = 0xdf
|
||||
|
||||
NegativeFixintMin = -32 // 0xe0
|
||||
NegativeFixintMax = -1 // 0xff
|
||||
)
|
||||
|
||||
// byte
|
||||
const (
|
||||
Byte1 = 1 << iota
|
||||
Byte2
|
||||
Byte4
|
||||
Byte8
|
||||
Byte16
|
||||
Byte32
|
||||
)
|
||||
|
||||
// ext type
|
||||
const (
|
||||
TimeStamp = -1
|
||||
)
|
||||
|
||||
// ext type complex
|
||||
var complexTypeCode = int8(-128)
|
||||
|
||||
// ComplexTypeCode gets complexTypeCode
|
||||
func ComplexTypeCode() int8 { return complexTypeCode }
|
||||
|
||||
// SetComplexTypeCode sets complexTypeCode
|
||||
func SetComplexTypeCode(code int8) {
|
||||
complexTypeCode = code
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
package def
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
var (
|
||||
// base errors
|
||||
|
||||
ErrMsgpack = errors.New("")
|
||||
|
||||
// decoding errors
|
||||
|
||||
ErrNoData = fmt.Errorf("%wno data", ErrMsgpack)
|
||||
ErrHasLeftOver = fmt.Errorf("%wdata has left over", ErrMsgpack)
|
||||
ErrReceiverNotPointer = fmt.Errorf("%wreceiver not pointer", ErrMsgpack)
|
||||
ErrNotMatchArrayElement = fmt.Errorf("%wnot match array element", ErrMsgpack)
|
||||
ErrCanNotDecode = fmt.Errorf("%winvalid code", ErrMsgpack)
|
||||
ErrCanNotSetSliceAsMapKey = fmt.Errorf("%wcan not set slice as map key", ErrMsgpack)
|
||||
ErrCanNotSetMapAsMapKey = fmt.Errorf("%wcan not set map as map key", ErrMsgpack)
|
||||
|
||||
// encoding errors
|
||||
|
||||
ErrTooShortBytes = fmt.Errorf("%wtoo short bytes", ErrMsgpack)
|
||||
ErrLackDataLengthToSlice = fmt.Errorf("%wdata length lacks to create slice", ErrMsgpack)
|
||||
ErrLackDataLengthToMap = fmt.Errorf("%wdata length lacks to create map", ErrMsgpack)
|
||||
ErrUnsupportedType = fmt.Errorf("%wunsupported type", ErrMsgpack)
|
||||
ErrUnsupportedLength = fmt.Errorf("%wunsupported length", ErrMsgpack)
|
||||
ErrNotMatchLastIndex = fmt.Errorf("%wnot match last index", ErrMsgpack)
|
||||
)
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
package msgpack
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/shamaton/msgpack/v2/internal/encoding"
|
||||
streamencoding "github.com/shamaton/msgpack/v2/internal/stream/encoding"
|
||||
)
|
||||
|
||||
// MarshalAsMap encodes data as map format.
|
||||
// This is the same thing that StructAsArray sets false.
|
||||
func MarshalAsMap(v interface{}) ([]byte, error) {
|
||||
return encoding.Encode(v, false)
|
||||
}
|
||||
|
||||
// MarshalAsArray encodes data as array format.
|
||||
// This is the same thing that StructAsArray sets true.
|
||||
func MarshalAsArray(v interface{}) ([]byte, error) {
|
||||
return encoding.Encode(v, true)
|
||||
}
|
||||
|
||||
// MarshalWriteAsMap writes map format encoded data to writer.
|
||||
// This is the same thing that StructAsArray sets false.
|
||||
func MarshalWriteAsMap(w io.Writer, v interface{}) error {
|
||||
return streamencoding.Encode(w, v, false)
|
||||
}
|
||||
|
||||
// MarshalWriteAsArray writes array format encoded data to writer.
|
||||
// This is the same thing that StructAsArray sets true.
|
||||
func MarshalWriteAsArray(w io.Writer, v interface{}) error {
|
||||
return streamencoding.Encode(w, v, true)
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
package msgpack
|
||||
|
||||
import (
|
||||
"github.com/shamaton/msgpack/v2/def"
|
||||
)
|
||||
|
||||
// Error is used in all msgpack error as the based error.
|
||||
var Error = def.ErrMsgpack
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
package ext
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
|
||||
"github.com/shamaton/msgpack/v2/def"
|
||||
)
|
||||
|
||||
// Decoder defines an interface for decoding values from bytes.
|
||||
// It provides methods to get the decoder type, check if the data matches the type,
|
||||
// and convert the data into a Go value.
|
||||
type Decoder interface {
|
||||
// Code returns the unique code representing the decoder type.
|
||||
Code() int8
|
||||
|
||||
// IsType checks if the data at the given offset matches the expected type.
|
||||
// Returns true if the type matches, false otherwise.
|
||||
IsType(offset int, d *[]byte) bool
|
||||
|
||||
// AsValue decodes the data at the given offset into a Go value of the specified kind.
|
||||
// Returns the decoded value, the new offset, and an error if decoding fails.
|
||||
AsValue(offset int, k reflect.Kind, d *[]byte) (interface{}, int, error)
|
||||
}
|
||||
|
||||
// DecoderCommon provides common utility methods for decoding data from bytes.
|
||||
type DecoderCommon struct {
|
||||
}
|
||||
|
||||
// ReadSize1 reads a single byte from the given index in the byte slice.
|
||||
// Returns the byte and the new index after reading.
|
||||
func (cd *DecoderCommon) ReadSize1(index int, d *[]byte) (byte, int) {
|
||||
rb := def.Byte1
|
||||
return (*d)[index], index + rb
|
||||
}
|
||||
|
||||
// ReadSize2 reads two bytes from the given index in the byte slice.
|
||||
// Returns the bytes as a slice and the new index after reading.
|
||||
func (cd *DecoderCommon) ReadSize2(index int, d *[]byte) ([]byte, int) {
|
||||
rb := def.Byte2
|
||||
return (*d)[index : index+rb], index + rb
|
||||
}
|
||||
|
||||
// ReadSize4 reads four bytes from the given index in the byte slice.
|
||||
// Returns the bytes as a slice and the new index after reading.
|
||||
func (cd *DecoderCommon) ReadSize4(index int, d *[]byte) ([]byte, int) {
|
||||
rb := def.Byte4
|
||||
return (*d)[index : index+rb], index + rb
|
||||
}
|
||||
|
||||
// ReadSize8 reads eight bytes from the given index in the byte slice.
|
||||
// Returns the bytes as a slice and the new index after reading.
|
||||
func (cd *DecoderCommon) ReadSize8(index int, d *[]byte) ([]byte, int) {
|
||||
rb := def.Byte8
|
||||
return (*d)[index : index+rb], index + rb
|
||||
}
|
||||
|
||||
// ReadSizeN reads a specified number of bytes (n) from the given index in the byte slice.
|
||||
// Returns the bytes as a slice and the new index after reading.
|
||||
func (cd *DecoderCommon) ReadSizeN(index, n int, d *[]byte) ([]byte, int) {
|
||||
return (*d)[index : index+n], index + n
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
package ext
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// StreamDecoder defines an interface for decoding streams of data.
|
||||
// It provides methods to retrieve the decoder's code, check type compatibility,
|
||||
// and convert raw data into a Go value of a specified kind.
|
||||
type StreamDecoder interface {
|
||||
// Code returns the unique identifier for the decoder.
|
||||
Code() int8
|
||||
|
||||
// IsType checks if the provided code, inner type, and data length match the expected type.
|
||||
// Returns true if the type matches, otherwise false.
|
||||
IsType(code byte, innerType int8, dataLength int) bool
|
||||
|
||||
// ToValue converts the raw data into a Go value of the specified kind.
|
||||
// Takes the code, raw data, and the target kind as input.
|
||||
// Returns the decoded value or an error if the conversion fails.
|
||||
ToValue(code byte, data []byte, k reflect.Kind) (any, error)
|
||||
}
|
||||
+152
@@ -0,0 +1,152 @@
|
||||
package ext
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// Encoder defines an interface for encoding values into bytes.
|
||||
// It provides methods to get the encoding type, calculate the byte size of a value,
|
||||
// and write the encoded value into a byte slice.
|
||||
type Encoder interface {
|
||||
// Code returns the unique code representing the encoder type.
|
||||
Code() int8
|
||||
|
||||
// Type returns the reflect.Type of the value that the encoder handles.
|
||||
Type() reflect.Type
|
||||
|
||||
// CalcByteSize calculates the number of bytes required to encode the given value.
|
||||
// Returns the size and an error if the calculation fails.
|
||||
CalcByteSize(value reflect.Value) (int, error)
|
||||
|
||||
// WriteToBytes encodes the given value into a byte slice starting at the specified offset.
|
||||
// Returns the new offset after writing the bytes.
|
||||
WriteToBytes(value reflect.Value, offset int, bytes *[]byte) int
|
||||
}
|
||||
|
||||
// EncoderCommon provides utility methods for encoding various types of values into bytes.
|
||||
// It includes methods to encode integers and unsigned integers of different sizes,
|
||||
// as well as methods to write raw byte slices into a target byte slice.
|
||||
type EncoderCommon struct {
|
||||
}
|
||||
|
||||
// SetByte1Int64 encodes a single byte from the given int64 value into the byte slice at the specified offset.
|
||||
// Returns the new offset after writing the byte.
|
||||
func (c *EncoderCommon) SetByte1Int64(value int64, offset int, d *[]byte) int {
|
||||
(*d)[offset] = byte(value)
|
||||
return offset + 1
|
||||
}
|
||||
|
||||
// SetByte2Int64 encodes the lower two bytes of the given int64 value into the byte slice at the specified offset.
|
||||
// Returns the new offset after writing the bytes.
|
||||
func (c *EncoderCommon) SetByte2Int64(value int64, offset int, d *[]byte) int {
|
||||
(*d)[offset+0] = byte(value >> 8)
|
||||
(*d)[offset+1] = byte(value)
|
||||
return offset + 2
|
||||
}
|
||||
|
||||
// SetByte4Int64 encodes the lower four bytes of the given int64 value into the byte slice at the specified offset.
|
||||
// Returns the new offset after writing the bytes.
|
||||
func (c *EncoderCommon) SetByte4Int64(value int64, offset int, d *[]byte) int {
|
||||
(*d)[offset+0] = byte(value >> 24)
|
||||
(*d)[offset+1] = byte(value >> 16)
|
||||
(*d)[offset+2] = byte(value >> 8)
|
||||
(*d)[offset+3] = byte(value)
|
||||
return offset + 4
|
||||
}
|
||||
|
||||
// SetByte8Int64 encodes all eight bytes of the given int64 value into the byte slice at the specified offset.
|
||||
// Returns the new offset after writing the bytes.
|
||||
func (c *EncoderCommon) SetByte8Int64(value int64, offset int, d *[]byte) int {
|
||||
(*d)[offset] = byte(value >> 56)
|
||||
(*d)[offset+1] = byte(value >> 48)
|
||||
(*d)[offset+2] = byte(value >> 40)
|
||||
(*d)[offset+3] = byte(value >> 32)
|
||||
(*d)[offset+4] = byte(value >> 24)
|
||||
(*d)[offset+5] = byte(value >> 16)
|
||||
(*d)[offset+6] = byte(value >> 8)
|
||||
(*d)[offset+7] = byte(value)
|
||||
return offset + 8
|
||||
}
|
||||
|
||||
// SetByte1Uint64 encodes a single byte from the given uint64 value into the byte slice at the specified offset.
|
||||
// Returns the new offset after writing the byte.
|
||||
func (c *EncoderCommon) SetByte1Uint64(value uint64, offset int, d *[]byte) int {
|
||||
(*d)[offset] = byte(value)
|
||||
return offset + 1
|
||||
}
|
||||
|
||||
// SetByte2Uint64 encodes the lower two bytes of the given uint64 value into the byte slice at the specified offset.
|
||||
// Returns the new offset after writing the bytes.
|
||||
func (c *EncoderCommon) SetByte2Uint64(value uint64, offset int, d *[]byte) int {
|
||||
(*d)[offset] = byte(value >> 8)
|
||||
(*d)[offset+1] = byte(value)
|
||||
return offset + 2
|
||||
}
|
||||
|
||||
// SetByte4Uint64 encodes the lower four bytes of the given uint64 value into the byte slice at the specified offset.
|
||||
// Returns the new offset after writing the bytes.
|
||||
func (c *EncoderCommon) SetByte4Uint64(value uint64, offset int, d *[]byte) int {
|
||||
(*d)[offset] = byte(value >> 24)
|
||||
(*d)[offset+1] = byte(value >> 16)
|
||||
(*d)[offset+2] = byte(value >> 8)
|
||||
(*d)[offset+3] = byte(value)
|
||||
return offset + 4
|
||||
}
|
||||
|
||||
// SetByte8Uint64 encodes all eight bytes of the given uint64 value into the byte slice at the specified offset.
|
||||
// Returns the new offset after writing the bytes.
|
||||
func (c *EncoderCommon) SetByte8Uint64(value uint64, offset int, d *[]byte) int {
|
||||
(*d)[offset] = byte(value >> 56)
|
||||
(*d)[offset+1] = byte(value >> 48)
|
||||
(*d)[offset+2] = byte(value >> 40)
|
||||
(*d)[offset+3] = byte(value >> 32)
|
||||
(*d)[offset+4] = byte(value >> 24)
|
||||
(*d)[offset+5] = byte(value >> 16)
|
||||
(*d)[offset+6] = byte(value >> 8)
|
||||
(*d)[offset+7] = byte(value)
|
||||
return offset + 8
|
||||
}
|
||||
|
||||
// SetByte1Int encodes a single byte from the given int value into the byte slice at the specified offset.
|
||||
// Returns the new offset after writing the byte.
|
||||
func (c *EncoderCommon) SetByte1Int(code, offset int, d *[]byte) int {
|
||||
(*d)[offset] = byte(code)
|
||||
return offset + 1
|
||||
}
|
||||
|
||||
// SetByte2Int encodes the lower two bytes of the given int value into the byte slice at the specified offset.
|
||||
// Returns the new offset after writing the bytes.
|
||||
func (c *EncoderCommon) SetByte2Int(value int, offset int, d *[]byte) int {
|
||||
(*d)[offset] = byte(value >> 8)
|
||||
(*d)[offset+1] = byte(value)
|
||||
return offset + 2
|
||||
}
|
||||
|
||||
// SetByte4Int encodes the lower four bytes of the given int value into the byte slice at the specified offset.
|
||||
// Returns the new offset after writing the bytes.
|
||||
func (c *EncoderCommon) SetByte4Int(value int, offset int, d *[]byte) int {
|
||||
(*d)[offset] = byte(value >> 24)
|
||||
(*d)[offset+1] = byte(value >> 16)
|
||||
(*d)[offset+2] = byte(value >> 8)
|
||||
(*d)[offset+3] = byte(value)
|
||||
return offset + 4
|
||||
}
|
||||
|
||||
// SetByte4Uint32 encodes the lower four bytes of the given uint32 value into the byte slice at the specified offset.
|
||||
// Returns the new offset after writing the bytes.
|
||||
func (c *EncoderCommon) SetByte4Uint32(value uint32, offset int, d *[]byte) int {
|
||||
(*d)[offset] = byte(value >> 24)
|
||||
(*d)[offset+1] = byte(value >> 16)
|
||||
(*d)[offset+2] = byte(value >> 8)
|
||||
(*d)[offset+3] = byte(value)
|
||||
return offset + 4
|
||||
}
|
||||
|
||||
// SetBytes writes the given byte slice `bs` into the target byte slice at the specified offset.
|
||||
// Returns the new offset after writing the bytes.
|
||||
func (c *EncoderCommon) SetBytes(bs []byte, offset int, d *[]byte) int {
|
||||
for i := range bs {
|
||||
(*d)[offset+i] = bs[i]
|
||||
}
|
||||
return offset + len(bs)
|
||||
}
|
||||
+149
@@ -0,0 +1,149 @@
|
||||
package ext
|
||||
|
||||
import (
|
||||
"io"
|
||||
"reflect"
|
||||
|
||||
"github.com/shamaton/msgpack/v2/internal/common"
|
||||
)
|
||||
|
||||
// StreamEncoder is an interface that extended encoders should implement.
|
||||
// It defines methods for encoding data into a stream.
|
||||
type StreamEncoder interface {
|
||||
// Code returns the unique code for the encoder.
|
||||
Code() int8
|
||||
// Type returns the reflect.Type of the value being encoded.
|
||||
Type() reflect.Type
|
||||
// Write encodes the given value and writes it to the provided StreamWriter.
|
||||
Write(w StreamWriter, value reflect.Value) error
|
||||
}
|
||||
|
||||
// StreamWriter provides methods for writing data in extended formats.
|
||||
// It wraps an io.Writer and a buffer for efficient writing.
|
||||
type StreamWriter struct {
|
||||
w io.Writer // The underlying writer to write data to.
|
||||
buf *common.Buffer // A buffer used for temporary storage during writing.
|
||||
}
|
||||
|
||||
// CreateStreamWriter creates and returns a new StreamWriter instance.
|
||||
func CreateStreamWriter(w io.Writer, buf *common.Buffer) StreamWriter {
|
||||
return StreamWriter{w, buf}
|
||||
}
|
||||
|
||||
// WriteByte1Int64 writes a single byte representation of an int64 value.
|
||||
func (w *StreamWriter) WriteByte1Int64(value int64) error {
|
||||
return w.buf.Write(w.w,
|
||||
byte(value),
|
||||
)
|
||||
}
|
||||
|
||||
// WriteByte2Int64 writes a two-byte representation of an int64 value.
|
||||
func (w *StreamWriter) WriteByte2Int64(value int64) error {
|
||||
return w.buf.Write(w.w,
|
||||
byte(value>>8),
|
||||
byte(value),
|
||||
)
|
||||
}
|
||||
|
||||
// WriteByte4Int64 writes a four-byte representation of an int64 value.
|
||||
func (w *StreamWriter) WriteByte4Int64(value int64) error {
|
||||
return w.buf.Write(w.w,
|
||||
byte(value>>24),
|
||||
byte(value>>16),
|
||||
byte(value>>8),
|
||||
byte(value),
|
||||
)
|
||||
}
|
||||
|
||||
// WriteByte8Int64 writes an eight-byte representation of an int64 value.
|
||||
func (w *StreamWriter) WriteByte8Int64(value int64) error {
|
||||
return w.buf.Write(w.w,
|
||||
byte(value>>56),
|
||||
byte(value>>48),
|
||||
byte(value>>40),
|
||||
byte(value>>32),
|
||||
byte(value>>24),
|
||||
byte(value>>16),
|
||||
byte(value>>8),
|
||||
byte(value),
|
||||
)
|
||||
}
|
||||
|
||||
// WriteByte1Uint64 writes a single byte representation of a uint64 value.
|
||||
func (w *StreamWriter) WriteByte1Uint64(value uint64) error {
|
||||
return w.buf.Write(w.w,
|
||||
byte(value),
|
||||
)
|
||||
}
|
||||
|
||||
// WriteByte2Uint64 writes a two-byte representation of a uint64 value.
|
||||
func (w *StreamWriter) WriteByte2Uint64(value uint64) error {
|
||||
return w.buf.Write(w.w,
|
||||
byte(value>>8),
|
||||
byte(value),
|
||||
)
|
||||
}
|
||||
|
||||
// WriteByte4Uint64 writes a four-byte representation of a uint64 value.
|
||||
func (w *StreamWriter) WriteByte4Uint64(value uint64) error {
|
||||
return w.buf.Write(w.w,
|
||||
byte(value>>24),
|
||||
byte(value>>16),
|
||||
byte(value>>8),
|
||||
byte(value),
|
||||
)
|
||||
}
|
||||
|
||||
// WriteByte8Uint64 writes an eight-byte representation of a uint64 value.
|
||||
func (w *StreamWriter) WriteByte8Uint64(value uint64) error {
|
||||
return w.buf.Write(w.w,
|
||||
byte(value>>56),
|
||||
byte(value>>48),
|
||||
byte(value>>40),
|
||||
byte(value>>32),
|
||||
byte(value>>24),
|
||||
byte(value>>16),
|
||||
byte(value>>8),
|
||||
byte(value),
|
||||
)
|
||||
}
|
||||
|
||||
// WriteByte1Int writes a single byte representation of an int value.
|
||||
func (w *StreamWriter) WriteByte1Int(value int) error {
|
||||
return w.buf.Write(w.w,
|
||||
byte(value),
|
||||
)
|
||||
}
|
||||
|
||||
// WriteByte2Int writes a two-byte representation of an int value.
|
||||
func (w *StreamWriter) WriteByte2Int(value int) error {
|
||||
return w.buf.Write(w.w,
|
||||
byte(value>>8),
|
||||
byte(value),
|
||||
)
|
||||
}
|
||||
|
||||
// WriteByte4Int writes a four-byte representation of an int value.
|
||||
func (w *StreamWriter) WriteByte4Int(value int) error {
|
||||
return w.buf.Write(w.w,
|
||||
byte(value>>24),
|
||||
byte(value>>16),
|
||||
byte(value>>8),
|
||||
byte(value),
|
||||
)
|
||||
}
|
||||
|
||||
// WriteByte4Uint32 writes a four-byte representation of a uint32 value.
|
||||
func (w *StreamWriter) WriteByte4Uint32(value uint32) error {
|
||||
return w.buf.Write(w.w,
|
||||
byte(value>>24),
|
||||
byte(value>>16),
|
||||
byte(value>>8),
|
||||
byte(value),
|
||||
)
|
||||
}
|
||||
|
||||
// WriteBytes writes a slice of bytes to the underlying writer.
|
||||
func (w *StreamWriter) WriteBytes(bs []byte) error {
|
||||
return w.buf.Write(w.w, bs...)
|
||||
}
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"io"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type Buffer struct {
|
||||
Data []byte
|
||||
B1 []byte
|
||||
B2 []byte
|
||||
B4 []byte
|
||||
B8 []byte
|
||||
B16 []byte
|
||||
offset int
|
||||
}
|
||||
|
||||
func (b *Buffer) Write(w io.Writer, vs ...byte) error {
|
||||
if len(b.Data) < b.offset+len(vs) {
|
||||
_, err := w.Write(b.Data[:b.offset])
|
||||
b.offset = 0
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(b.Data) < len(vs) {
|
||||
b.Data = append(b.Data, make([]byte, len(vs)-len(b.Data))...)
|
||||
}
|
||||
}
|
||||
for i := range vs {
|
||||
b.Data[b.offset+i] = vs[i]
|
||||
}
|
||||
b.offset += len(vs)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *Buffer) Flush(w io.Writer) error {
|
||||
_, err := w.Write(b.Data[:b.offset])
|
||||
return err
|
||||
}
|
||||
|
||||
var bufPool = sync.Pool{
|
||||
New: func() interface{} {
|
||||
data := make([]byte, 64)
|
||||
return &Buffer{
|
||||
Data: data,
|
||||
B1: data[:1],
|
||||
B2: data[:2],
|
||||
B4: data[:4],
|
||||
B8: data[:8],
|
||||
B16: data[:16],
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
func GetBuffer() *Buffer {
|
||||
buf := bufPool.Get().(*Buffer)
|
||||
buf.offset = 0
|
||||
return buf
|
||||
}
|
||||
|
||||
func PutBuffer(buf *Buffer) {
|
||||
bufPool.Put(buf)
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Common is used encoding/decoding
|
||||
type Common struct {
|
||||
}
|
||||
|
||||
// CheckField returns flag whether should encode/decode or not and field name
|
||||
func (c *Common) CheckField(field reflect.StructField) (public, omit bool, name string) {
|
||||
// A to Z
|
||||
if !c.isPublic(field.Name) {
|
||||
return false, false, ""
|
||||
}
|
||||
tag := field.Tag.Get("msgpack")
|
||||
if tag == "" {
|
||||
return true, false, field.Name
|
||||
}
|
||||
|
||||
parts := strings.Split(tag, ",")
|
||||
// check ignore
|
||||
if parts[0] == "-" {
|
||||
return false, false, ""
|
||||
}
|
||||
// check omitempty
|
||||
for _, part := range parts[1:] {
|
||||
if part == "omitempty" {
|
||||
omit = true
|
||||
}
|
||||
}
|
||||
// check name
|
||||
name = field.Name
|
||||
if parts[0] != "" {
|
||||
name = parts[0]
|
||||
}
|
||||
return true, omit, name
|
||||
}
|
||||
|
||||
func (c *Common) isPublic(name string) bool {
|
||||
return 0x41 <= name[0] && name[0] <= 0x5a
|
||||
}
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
package decoding
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"reflect"
|
||||
"unsafe"
|
||||
|
||||
"github.com/shamaton/msgpack/v2/def"
|
||||
)
|
||||
|
||||
func (d *decoder) isCodeBin(v byte) bool {
|
||||
switch v {
|
||||
case def.Bin8, def.Bin16, def.Bin32:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (d *decoder) asBin(offset int, k reflect.Kind) ([]byte, int, error) {
|
||||
code, offset, err := d.readSize1(offset)
|
||||
if err != nil {
|
||||
return emptyBytes, 0, err
|
||||
}
|
||||
|
||||
switch code {
|
||||
case def.Bin8:
|
||||
l, offset, err := d.readSize1(offset)
|
||||
if err != nil {
|
||||
return emptyBytes, 0, err
|
||||
}
|
||||
v, offset, err := d.readSizeN(offset, int(uint8(l)))
|
||||
if err != nil {
|
||||
return emptyBytes, 0, err
|
||||
}
|
||||
return v, offset, nil
|
||||
case def.Bin16:
|
||||
bs, offset, err := d.readSize2(offset)
|
||||
if err != nil {
|
||||
return emptyBytes, 0, err
|
||||
}
|
||||
v, offset, err := d.readSizeN(offset, int(binary.BigEndian.Uint16(bs)))
|
||||
if err != nil {
|
||||
return emptyBytes, 0, err
|
||||
}
|
||||
return v, offset, nil
|
||||
case def.Bin32:
|
||||
bs, offset, err := d.readSize4(offset)
|
||||
if err != nil {
|
||||
return emptyBytes, 0, err
|
||||
}
|
||||
v, offset, err := d.readSizeN(offset, int(binary.BigEndian.Uint32(bs)))
|
||||
if err != nil {
|
||||
return emptyBytes, 0, err
|
||||
}
|
||||
return v, offset, nil
|
||||
}
|
||||
|
||||
return emptyBytes, 0, d.errorTemplate(code, k)
|
||||
}
|
||||
|
||||
func (d *decoder) asBinString(offset int, k reflect.Kind) (string, int, error) {
|
||||
bs, offset, err := d.asBin(offset, k)
|
||||
return *(*string)(unsafe.Pointer(&bs)), offset, err
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
package decoding
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
|
||||
"github.com/shamaton/msgpack/v2/def"
|
||||
)
|
||||
|
||||
func (d *decoder) asBool(offset int, k reflect.Kind) (bool, int, error) {
|
||||
code, offset, err := d.readSize1(offset)
|
||||
if err != nil {
|
||||
return false, 0, err
|
||||
}
|
||||
|
||||
switch code {
|
||||
case def.True:
|
||||
return true, offset, nil
|
||||
case def.False:
|
||||
return false, offset, nil
|
||||
}
|
||||
return false, 0, d.errorTemplate(code, k)
|
||||
}
|
||||
+114
@@ -0,0 +1,114 @@
|
||||
package decoding
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"math"
|
||||
"reflect"
|
||||
|
||||
"github.com/shamaton/msgpack/v2/def"
|
||||
)
|
||||
|
||||
func (d *decoder) asComplex64(offset int, k reflect.Kind) (complex64, int, error) {
|
||||
code, offset, err := d.readSize1(offset)
|
||||
if err != nil {
|
||||
return complex(0, 0), 0, err
|
||||
}
|
||||
|
||||
switch code {
|
||||
case def.Fixext8:
|
||||
t, offset, err := d.readSize1(offset)
|
||||
if err != nil {
|
||||
return complex(0, 0), 0, err
|
||||
}
|
||||
if int8(t) != def.ComplexTypeCode() {
|
||||
return complex(0, 0), 0, fmt.Errorf("fixext8. complex type is diffrent %d, %d", t, def.ComplexTypeCode())
|
||||
}
|
||||
rb, offset, err := d.readSize4(offset)
|
||||
if err != nil {
|
||||
return complex(0, 0), 0, err
|
||||
}
|
||||
ib, offset, err := d.readSize4(offset)
|
||||
if err != nil {
|
||||
return complex(0, 0), 0, err
|
||||
}
|
||||
r := math.Float32frombits(binary.BigEndian.Uint32(rb))
|
||||
i := math.Float32frombits(binary.BigEndian.Uint32(ib))
|
||||
return complex(r, i), offset, nil
|
||||
|
||||
case def.Fixext16:
|
||||
t, offset, err := d.readSize1(offset)
|
||||
if err != nil {
|
||||
return complex(0, 0), 0, err
|
||||
}
|
||||
if int8(t) != def.ComplexTypeCode() {
|
||||
return complex(0, 0), 0, fmt.Errorf("fixext16. complex type is diffrent %d, %d", t, def.ComplexTypeCode())
|
||||
}
|
||||
rb, offset, err := d.readSize8(offset)
|
||||
if err != nil {
|
||||
return complex(0, 0), 0, err
|
||||
}
|
||||
ib, offset, err := d.readSize8(offset)
|
||||
if err != nil {
|
||||
return complex(0, 0), 0, err
|
||||
}
|
||||
r := math.Float64frombits(binary.BigEndian.Uint64(rb))
|
||||
i := math.Float64frombits(binary.BigEndian.Uint64(ib))
|
||||
return complex64(complex(r, i)), offset, nil
|
||||
|
||||
}
|
||||
|
||||
return complex(0, 0), 0, d.errorTemplate(code, k)
|
||||
}
|
||||
|
||||
func (d *decoder) asComplex128(offset int, k reflect.Kind) (complex128, int, error) {
|
||||
code, offset, err := d.readSize1(offset)
|
||||
if err != nil {
|
||||
return complex(0, 0), 0, err
|
||||
}
|
||||
|
||||
switch code {
|
||||
case def.Fixext8:
|
||||
t, offset, err := d.readSize1(offset)
|
||||
if err != nil {
|
||||
return complex(0, 0), 0, err
|
||||
}
|
||||
if int8(t) != def.ComplexTypeCode() {
|
||||
return complex(0, 0), 0, fmt.Errorf("fixext8. complex type is diffrent %d, %d", t, def.ComplexTypeCode())
|
||||
}
|
||||
rb, offset, err := d.readSize4(offset)
|
||||
if err != nil {
|
||||
return complex(0, 0), 0, err
|
||||
}
|
||||
ib, offset, err := d.readSize4(offset)
|
||||
if err != nil {
|
||||
return complex(0, 0), 0, err
|
||||
}
|
||||
r := math.Float32frombits(binary.BigEndian.Uint32(rb))
|
||||
i := math.Float32frombits(binary.BigEndian.Uint32(ib))
|
||||
return complex128(complex(r, i)), offset, nil
|
||||
|
||||
case def.Fixext16:
|
||||
t, offset, err := d.readSize1(offset)
|
||||
if err != nil {
|
||||
return complex(0, 0), 0, err
|
||||
}
|
||||
if int8(t) != def.ComplexTypeCode() {
|
||||
return complex(0, 0), 0, fmt.Errorf("fixext16. complex type is diffrent %d, %d", t, def.ComplexTypeCode())
|
||||
}
|
||||
rb, offset, err := d.readSize8(offset)
|
||||
if err != nil {
|
||||
return complex(0, 0), 0, err
|
||||
}
|
||||
ib, offset, err := d.readSize8(offset)
|
||||
if err != nil {
|
||||
return complex(0, 0), 0, err
|
||||
}
|
||||
r := math.Float64frombits(binary.BigEndian.Uint64(rb))
|
||||
i := math.Float64frombits(binary.BigEndian.Uint64(ib))
|
||||
return complex(r, i), offset, nil
|
||||
|
||||
}
|
||||
|
||||
return complex(0, 0), 0, d.errorTemplate(code, k)
|
||||
}
|
||||
+343
@@ -0,0 +1,343 @@
|
||||
package decoding
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"github.com/shamaton/msgpack/v2/def"
|
||||
"github.com/shamaton/msgpack/v2/internal/common"
|
||||
)
|
||||
|
||||
type decoder struct {
|
||||
data []byte
|
||||
asArray bool
|
||||
common.Common
|
||||
}
|
||||
|
||||
// Decode analyzes the MessagePack-encoded data and stores
|
||||
// the result into the pointer of v.
|
||||
func Decode(data []byte, v interface{}, asArray bool) error {
|
||||
d := decoder{data: data, asArray: asArray}
|
||||
|
||||
if d.data == nil || len(d.data) < 1 {
|
||||
return def.ErrNoData
|
||||
}
|
||||
rv := reflect.ValueOf(v)
|
||||
if rv.Kind() != reflect.Ptr {
|
||||
return fmt.Errorf("%w. v.(type): %T", def.ErrReceiverNotPointer, v)
|
||||
}
|
||||
|
||||
rv = rv.Elem()
|
||||
|
||||
last, err := d.decode(rv, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(data) != last {
|
||||
return fmt.Errorf("%w size=%d, last=%d", def.ErrHasLeftOver, len(data), last)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (d *decoder) decode(rv reflect.Value, offset int) (int, error) {
|
||||
k := rv.Kind()
|
||||
switch k {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
v, o, err := d.asInt(offset, k)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
rv.SetInt(v)
|
||||
offset = o
|
||||
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
v, o, err := d.asUint(offset, k)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
rv.SetUint(v)
|
||||
offset = o
|
||||
|
||||
case reflect.Float32:
|
||||
v, o, err := d.asFloat32(offset, k)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
rv.SetFloat(float64(v))
|
||||
offset = o
|
||||
|
||||
case reflect.Float64:
|
||||
v, o, err := d.asFloat64(offset, k)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
rv.SetFloat(v)
|
||||
offset = o
|
||||
|
||||
case reflect.String:
|
||||
// byte slice
|
||||
if d.isCodeBin(d.data[offset]) {
|
||||
v, offset, err := d.asBinString(offset, k)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
rv.SetString(v)
|
||||
return offset, nil
|
||||
}
|
||||
v, o, err := d.asString(offset, k)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
rv.SetString(v)
|
||||
offset = o
|
||||
|
||||
case reflect.Bool:
|
||||
v, o, err := d.asBool(offset, k)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
rv.SetBool(v)
|
||||
offset = o
|
||||
|
||||
case reflect.Slice:
|
||||
// nil
|
||||
if d.isCodeNil(d.data[offset]) {
|
||||
offset++
|
||||
return offset, nil
|
||||
}
|
||||
// byte slice
|
||||
if d.isCodeBin(d.data[offset]) {
|
||||
bs, offset, err := d.asBin(offset, k)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
rv.SetBytes(bs)
|
||||
return offset, nil
|
||||
}
|
||||
// string to bytes
|
||||
if d.isCodeString(d.data[offset]) {
|
||||
l, offset, err := d.stringByteLength(offset, k)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
bs, offset, err := d.asStringByteByLength(offset, l, k)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
rv.SetBytes(bs)
|
||||
return offset, nil
|
||||
}
|
||||
|
||||
// get slice length
|
||||
l, o, err := d.sliceLength(offset, k)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
if err = d.hasRequiredLeastSliceSize(o, l); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// check fixed type
|
||||
fixedOffset, found, err := d.asFixedSlice(rv, o, l)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if found {
|
||||
return fixedOffset, nil
|
||||
}
|
||||
|
||||
// create slice dynamically
|
||||
tmpSlice := reflect.MakeSlice(rv.Type(), l, l)
|
||||
for i := 0; i < l; i++ {
|
||||
v := tmpSlice.Index(i)
|
||||
if v.Kind() == reflect.Struct {
|
||||
o, err = d.setStruct(v, o, k)
|
||||
} else {
|
||||
o, err = d.decode(v, o)
|
||||
}
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
rv.Set(tmpSlice)
|
||||
offset = o
|
||||
|
||||
case reflect.Complex64:
|
||||
v, o, err := d.asComplex64(offset, k)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
rv.SetComplex(complex128(v))
|
||||
offset = o
|
||||
|
||||
case reflect.Complex128:
|
||||
v, o, err := d.asComplex128(offset, k)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
rv.SetComplex(v)
|
||||
offset = o
|
||||
|
||||
case reflect.Array:
|
||||
// nil
|
||||
if d.isCodeNil(d.data[offset]) {
|
||||
offset++
|
||||
return offset, nil
|
||||
}
|
||||
// byte slice
|
||||
if d.isCodeBin(d.data[offset]) {
|
||||
bs, offset, err := d.asBin(offset, k)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if len(bs) > rv.Len() {
|
||||
return 0, fmt.Errorf("%v len is %d, but msgpack has %d elements, %w", rv.Type(), rv.Len(), len(bs), def.ErrNotMatchArrayElement)
|
||||
}
|
||||
for i, b := range bs {
|
||||
rv.Index(i).SetUint(uint64(b))
|
||||
}
|
||||
return offset, nil
|
||||
}
|
||||
// string to bytes
|
||||
if d.isCodeString(d.data[offset]) {
|
||||
l, offset, err := d.stringByteLength(offset, k)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if l > rv.Len() {
|
||||
return 0, fmt.Errorf("%v len is %d, but msgpack has %d elements, %w", rv.Type(), rv.Len(), l, def.ErrNotMatchArrayElement)
|
||||
}
|
||||
bs, offset, err := d.asStringByteByLength(offset, l, k)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
for i, b := range bs {
|
||||
rv.Index(i).SetUint(uint64(b))
|
||||
}
|
||||
return offset, nil
|
||||
}
|
||||
|
||||
// get slice length
|
||||
l, o, err := d.sliceLength(offset, k)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
if l > rv.Len() {
|
||||
return 0, fmt.Errorf("%v len is %d, but msgpack has %d elements, %w", rv.Type(), rv.Len(), l, def.ErrNotMatchArrayElement)
|
||||
}
|
||||
|
||||
if err = d.hasRequiredLeastSliceSize(o, l); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// create array dynamically
|
||||
for i := 0; i < l; i++ {
|
||||
o, err = d.decode(rv.Index(i), o)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
offset = o
|
||||
|
||||
case reflect.Map:
|
||||
// nil
|
||||
if d.isCodeNil(d.data[offset]) {
|
||||
offset++
|
||||
return offset, nil
|
||||
}
|
||||
|
||||
// get map length
|
||||
l, o, err := d.mapLength(offset, k)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
if err = d.hasRequiredLeastMapSize(o, l); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// check fixed type
|
||||
fixedOffset, found, err := d.asFixedMap(rv, o, l)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if found {
|
||||
return fixedOffset, nil
|
||||
}
|
||||
|
||||
// create dynamically
|
||||
key := rv.Type().Key()
|
||||
value := rv.Type().Elem()
|
||||
if rv.IsNil() {
|
||||
rv.Set(reflect.MakeMapWithSize(rv.Type(), l))
|
||||
}
|
||||
for i := 0; i < l; i++ {
|
||||
k := reflect.New(key).Elem()
|
||||
v := reflect.New(value).Elem()
|
||||
o, err = d.decode(k, o)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
o, err = d.decode(v, o)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
rv.SetMapIndex(k, v)
|
||||
}
|
||||
offset = o
|
||||
|
||||
case reflect.Struct:
|
||||
o, err := d.setStruct(rv, offset, k)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
offset = o
|
||||
|
||||
case reflect.Ptr:
|
||||
// nil
|
||||
if d.isCodeNil(d.data[offset]) {
|
||||
offset++
|
||||
return offset, nil
|
||||
}
|
||||
|
||||
if rv.Elem().Kind() == reflect.Invalid {
|
||||
n := reflect.New(rv.Type().Elem())
|
||||
rv.Set(n)
|
||||
}
|
||||
|
||||
o, err := d.decode(rv.Elem(), offset)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
offset = o
|
||||
|
||||
case reflect.Interface:
|
||||
if rv.Elem().Kind() == reflect.Ptr {
|
||||
o, err := d.decode(rv.Elem(), offset)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
offset = o
|
||||
} else {
|
||||
v, o, err := d.asInterface(offset, k)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if v != nil {
|
||||
rv.Set(reflect.ValueOf(v))
|
||||
}
|
||||
offset = o
|
||||
}
|
||||
|
||||
default:
|
||||
return 0, fmt.Errorf("%v is %w type", rv.Kind(), def.ErrUnsupportedType)
|
||||
}
|
||||
return offset, nil
|
||||
}
|
||||
|
||||
func (d *decoder) errorTemplate(code byte, k reflect.Kind) error {
|
||||
return fmt.Errorf("%w %x decoding as %v", def.ErrCanNotDecode, code, k)
|
||||
}
|
||||
+102
@@ -0,0 +1,102 @@
|
||||
package decoding
|
||||
|
||||
import (
|
||||
"github.com/shamaton/msgpack/v2/ext"
|
||||
"github.com/shamaton/msgpack/v2/time"
|
||||
)
|
||||
|
||||
var extCoderMap = map[int8]ext.Decoder{time.Decoder.Code(): time.Decoder}
|
||||
var extCoders = []ext.Decoder{time.Decoder}
|
||||
|
||||
// AddExtDecoder adds decoders for extension types.
|
||||
func AddExtDecoder(f ext.Decoder) {
|
||||
// ignore time
|
||||
if f.Code() == time.Decoder.Code() {
|
||||
return
|
||||
}
|
||||
|
||||
_, ok := extCoderMap[f.Code()]
|
||||
if !ok {
|
||||
extCoderMap[f.Code()] = f
|
||||
updateExtCoders()
|
||||
}
|
||||
}
|
||||
|
||||
// RemoveExtDecoder removes decoders for extension types.
|
||||
func RemoveExtDecoder(f ext.Decoder) {
|
||||
// ignore time
|
||||
if f.Code() == time.Decoder.Code() {
|
||||
return
|
||||
}
|
||||
|
||||
_, ok := extCoderMap[f.Code()]
|
||||
if ok {
|
||||
delete(extCoderMap, f.Code())
|
||||
updateExtCoders()
|
||||
}
|
||||
}
|
||||
|
||||
func updateExtCoders() {
|
||||
extCoders = make([]ext.Decoder, len(extCoderMap))
|
||||
i := 0
|
||||
for k := range extCoderMap {
|
||||
extCoders[i] = extCoderMap[k]
|
||||
i++
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
var zero = time.Unix(0,0)
|
||||
|
||||
func (d *decoder) isDateTime(offset int) bool {
|
||||
code, offset := d.readSize1(offset)
|
||||
|
||||
if code == def.Fixext4 {
|
||||
t, _ := d.readSize1(offset)
|
||||
return int8(t) == def.TimeStamp
|
||||
} else if code == def.Fixext8 {
|
||||
t, _ := d.readSize1(offset)
|
||||
return int8(t) == def.TimeStamp
|
||||
} else if code == def.Ext8 {
|
||||
l, offset := d.readSize1(offset)
|
||||
t, _ := d.readSize1(offset)
|
||||
return l == 12 && int8(t) == def.TimeStamp
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (d *decoder) asDateTime(offset int, k reflect.Kind) (time.Time, int, error) {
|
||||
code, offset := d.readSize1(offset)
|
||||
|
||||
switch code {
|
||||
case def.Fixext4:
|
||||
_, offset = d.readSize1(offset)
|
||||
bs, offset := d.readSize4(offset)
|
||||
return time.Unix(int64(binary.BigEndian.Uint32(bs)), 0), offset, nil
|
||||
|
||||
case def.Fixext8:
|
||||
_, offset = d.readSize1(offset)
|
||||
bs, offset := d.readSize8(offset)
|
||||
data64 := binary.BigEndian.Uint64(bs)
|
||||
nano := int64(data64 >> 34)
|
||||
if nano > 999999999 {
|
||||
return zero, 0, fmt.Errorf("In timestamp 64 formats, nanoseconds must not be larger than 999999999 : %d", nano)
|
||||
}
|
||||
return time.Unix(int64(data64&0x00000003ffffffff), nano), offset, nil
|
||||
|
||||
case def.Ext8:
|
||||
_, offset = d.readSize1(offset)
|
||||
_, offset = d.readSize1(offset)
|
||||
nanobs, offset := d.readSize4(offset)
|
||||
secbs, offset := d.readSize8(offset)
|
||||
nano := binary.BigEndian.Uint32(nanobs)
|
||||
if nano > 999999999 {
|
||||
return zero, 0, fmt.Errorf("In timestamp 96 formats, nanoseconds must not be larger than 999999999 : %d", nano)
|
||||
}
|
||||
sec := binary.BigEndian.Uint64(secbs)
|
||||
return time.Unix(int64(sec), int64(nano)), offset, nil
|
||||
}
|
||||
|
||||
return zero, 0, d.errorTemplate(code, k)
|
||||
}
|
||||
*/
|
||||
+92
@@ -0,0 +1,92 @@
|
||||
package decoding
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"math"
|
||||
"reflect"
|
||||
|
||||
"github.com/shamaton/msgpack/v2/def"
|
||||
)
|
||||
|
||||
func (d *decoder) asFloat32(offset int, k reflect.Kind) (float32, int, error) {
|
||||
code, _, err := d.readSize1(offset)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
|
||||
switch {
|
||||
case code == def.Float32:
|
||||
offset++
|
||||
bs, offset, err := d.readSize4(offset)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
v := math.Float32frombits(binary.BigEndian.Uint32(bs))
|
||||
return v, offset, nil
|
||||
|
||||
case d.isPositiveFixNum(code), code == def.Uint8, code == def.Uint16, code == def.Uint32, code == def.Uint64:
|
||||
v, offset, err := d.asUint(offset, k)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
return float32(v), offset, nil
|
||||
|
||||
case d.isNegativeFixNum(code), code == def.Int8, code == def.Int16, code == def.Int32, code == def.Int64:
|
||||
v, offset, err := d.asInt(offset, k)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
return float32(v), offset, nil
|
||||
|
||||
case code == def.Nil:
|
||||
offset++
|
||||
return 0, offset, nil
|
||||
}
|
||||
return 0, 0, d.errorTemplate(code, k)
|
||||
}
|
||||
|
||||
func (d *decoder) asFloat64(offset int, k reflect.Kind) (float64, int, error) {
|
||||
code, _, err := d.readSize1(offset)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
|
||||
switch {
|
||||
case code == def.Float64:
|
||||
offset++
|
||||
bs, offset, err := d.readSize8(offset)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
v := math.Float64frombits(binary.BigEndian.Uint64(bs))
|
||||
return v, offset, nil
|
||||
|
||||
case code == def.Float32:
|
||||
offset++
|
||||
bs, offset, err := d.readSize4(offset)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
v := math.Float32frombits(binary.BigEndian.Uint32(bs))
|
||||
return float64(v), offset, nil
|
||||
|
||||
case d.isPositiveFixNum(code), code == def.Uint8, code == def.Uint16, code == def.Uint32, code == def.Uint64:
|
||||
v, offset, err := d.asUint(offset, k)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
return float64(v), offset, nil
|
||||
|
||||
case d.isNegativeFixNum(code), code == def.Int8, code == def.Int16, code == def.Int32, code == def.Int64:
|
||||
v, offset, err := d.asInt(offset, k)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
return float64(v), offset, nil
|
||||
|
||||
case code == def.Nil:
|
||||
offset++
|
||||
return 0, offset, nil
|
||||
}
|
||||
return 0, 0, d.errorTemplate(code, k)
|
||||
}
|
||||
+128
@@ -0,0 +1,128 @@
|
||||
package decoding
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"reflect"
|
||||
|
||||
"github.com/shamaton/msgpack/v2/def"
|
||||
)
|
||||
|
||||
func (d *decoder) isPositiveFixNum(v byte) bool {
|
||||
return def.PositiveFixIntMin <= v && v <= def.PositiveFixIntMax
|
||||
}
|
||||
|
||||
func (d *decoder) isNegativeFixNum(v byte) bool {
|
||||
return def.NegativeFixintMin <= int8(v) && int8(v) <= def.NegativeFixintMax
|
||||
}
|
||||
|
||||
func (d *decoder) asInt(offset int, k reflect.Kind) (int64, int, error) {
|
||||
|
||||
code, _, err := d.readSize1(offset)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
|
||||
switch {
|
||||
case d.isPositiveFixNum(code):
|
||||
b, offset, err := d.readSize1(offset)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
return int64(b), offset, nil
|
||||
|
||||
case d.isNegativeFixNum(code):
|
||||
b, offset, err := d.readSize1(offset)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
return int64(int8(b)), offset, nil
|
||||
|
||||
case code == def.Uint8:
|
||||
offset++
|
||||
b, offset, err := d.readSize1(offset)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
return int64(uint8(b)), offset, nil
|
||||
|
||||
case code == def.Int8:
|
||||
offset++
|
||||
b, offset, err := d.readSize1(offset)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
return int64(int8(b)), offset, nil
|
||||
|
||||
case code == def.Uint16:
|
||||
offset++
|
||||
bs, offset, err := d.readSize2(offset)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
v := binary.BigEndian.Uint16(bs)
|
||||
return int64(v), offset, nil
|
||||
|
||||
case code == def.Int16:
|
||||
offset++
|
||||
bs, offset, err := d.readSize2(offset)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
v := int16(binary.BigEndian.Uint16(bs))
|
||||
return int64(v), offset, nil
|
||||
|
||||
case code == def.Uint32:
|
||||
offset++
|
||||
bs, offset, err := d.readSize4(offset)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
v := binary.BigEndian.Uint32(bs)
|
||||
return int64(v), offset, nil
|
||||
|
||||
case code == def.Int32:
|
||||
offset++
|
||||
bs, offset, err := d.readSize4(offset)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
v := int32(binary.BigEndian.Uint32(bs))
|
||||
return int64(v), offset, nil
|
||||
|
||||
case code == def.Uint64:
|
||||
offset++
|
||||
bs, offset, err := d.readSize8(offset)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
return int64(binary.BigEndian.Uint64(bs)), offset, nil
|
||||
|
||||
case code == def.Int64:
|
||||
offset++
|
||||
bs, offset, err := d.readSize8(offset)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
return int64(binary.BigEndian.Uint64(bs)), offset, nil
|
||||
|
||||
case code == def.Float32:
|
||||
v, offset, err := d.asFloat32(offset, k)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
return int64(v), offset, nil
|
||||
|
||||
case code == def.Float64:
|
||||
v, offset, err := d.asFloat64(offset, k)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
return int64(v), offset, nil
|
||||
|
||||
case code == def.Nil:
|
||||
offset++
|
||||
return 0, offset, nil
|
||||
}
|
||||
|
||||
return 0, 0, d.errorTemplate(code, k)
|
||||
}
|
||||
+190
@@ -0,0 +1,190 @@
|
||||
package decoding
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"github.com/shamaton/msgpack/v2/def"
|
||||
)
|
||||
|
||||
func (d *decoder) asInterface(offset int, k reflect.Kind) (interface{}, int, error) {
|
||||
code, _, err := d.readSize1(offset)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
|
||||
switch {
|
||||
case code == def.Nil:
|
||||
offset++
|
||||
return nil, offset, nil
|
||||
|
||||
case code == def.True, code == def.False:
|
||||
v, offset, err := d.asBool(offset, k)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
return v, offset, nil
|
||||
|
||||
case d.isPositiveFixNum(code), code == def.Uint8:
|
||||
v, offset, err := d.asUint(offset, k)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
return uint8(v), offset, err
|
||||
case code == def.Uint16:
|
||||
v, offset, err := d.asUint(offset, k)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
return uint16(v), offset, err
|
||||
case code == def.Uint32:
|
||||
v, offset, err := d.asUint(offset, k)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
return uint32(v), offset, err
|
||||
case code == def.Uint64:
|
||||
v, offset, err := d.asUint(offset, k)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
return v, offset, err
|
||||
|
||||
case d.isNegativeFixNum(code), code == def.Int8:
|
||||
v, offset, err := d.asInt(offset, k)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
return int8(v), offset, err
|
||||
case code == def.Int16:
|
||||
v, offset, err := d.asInt(offset, k)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
return int16(v), offset, err
|
||||
case code == def.Int32:
|
||||
v, offset, err := d.asInt(offset, k)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
return int32(v), offset, err
|
||||
case code == def.Int64:
|
||||
v, offset, err := d.asInt(offset, k)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
return v, offset, err
|
||||
|
||||
case code == def.Float32:
|
||||
v, offset, err := d.asFloat32(offset, k)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
return v, offset, err
|
||||
case code == def.Float64:
|
||||
v, offset, err := d.asFloat64(offset, k)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
return v, offset, err
|
||||
|
||||
case d.isFixString(code), code == def.Str8, code == def.Str16, code == def.Str32:
|
||||
v, offset, err := d.asString(offset, k)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
return v, offset, err
|
||||
|
||||
case code == def.Bin8, code == def.Bin16, code == def.Bin32:
|
||||
v, offset, err := d.asBin(offset, k)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
return v, offset, err
|
||||
|
||||
case d.isFixSlice(code), code == def.Array16, code == def.Array32:
|
||||
l, o, err := d.sliceLength(offset, k)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
if err = d.hasRequiredLeastSliceSize(o, l); err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
v := make([]interface{}, l)
|
||||
for i := 0; i < l; i++ {
|
||||
vv, o2, err := d.asInterface(o, k)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
v[i] = vv
|
||||
o = o2
|
||||
}
|
||||
offset = o
|
||||
return v, offset, nil
|
||||
|
||||
case d.isFixMap(code), code == def.Map16, code == def.Map32:
|
||||
l, o, err := d.mapLength(offset, k)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
if err = d.hasRequiredLeastMapSize(o, l); err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
v := make(map[interface{}]interface{}, l)
|
||||
for i := 0; i < l; i++ {
|
||||
if err := d.canSetAsMapKey(o); err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
key, o2, err := d.asInterface(o, k)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
value, o2, err := d.asInterface(o2, k)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
v[key] = value
|
||||
o = o2
|
||||
}
|
||||
offset = o
|
||||
return v, offset, nil
|
||||
}
|
||||
|
||||
/* use ext
|
||||
if d.isDateTime(offset) {
|
||||
v, offset, err := d.asDateTime(offset, k)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
return v, offset, nil
|
||||
}
|
||||
*/
|
||||
|
||||
// ext
|
||||
for i := range extCoders {
|
||||
if extCoders[i].IsType(offset, &d.data) {
|
||||
v, offset, err := extCoders[i].AsValue(offset, k, &d.data)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
return v, offset, nil
|
||||
}
|
||||
}
|
||||
return nil, 0, d.errorTemplate(code, k)
|
||||
}
|
||||
|
||||
func (d *decoder) canSetAsMapKey(index int) error {
|
||||
code, _, err := d.readSize1(index)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
switch {
|
||||
case d.isFixSlice(code), code == def.Array16, code == def.Array32:
|
||||
return fmt.Errorf("%w. code: %x", def.ErrCanNotSetSliceAsMapKey, code)
|
||||
case d.isFixMap(code), code == def.Map16, code == def.Map32:
|
||||
return fmt.Errorf("%w. code: %x", def.ErrCanNotSetMapAsMapKey, code)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
+749
@@ -0,0 +1,749 @@
|
||||
package decoding
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"reflect"
|
||||
|
||||
"github.com/shamaton/msgpack/v2/def"
|
||||
)
|
||||
|
||||
var (
|
||||
typeMapStringInt = reflect.TypeOf(map[string]int{})
|
||||
typeMapStringInt8 = reflect.TypeOf(map[string]int8{})
|
||||
typeMapStringInt16 = reflect.TypeOf(map[string]int16{})
|
||||
typeMapStringInt32 = reflect.TypeOf(map[string]int32{})
|
||||
typeMapStringInt64 = reflect.TypeOf(map[string]int64{})
|
||||
|
||||
typeMapStringUint = reflect.TypeOf(map[string]uint{})
|
||||
typeMapStringUint8 = reflect.TypeOf(map[string]uint8{})
|
||||
typeMapStringUint16 = reflect.TypeOf(map[string]uint16{})
|
||||
typeMapStringUint32 = reflect.TypeOf(map[string]uint32{})
|
||||
typeMapStringUint64 = reflect.TypeOf(map[string]uint64{})
|
||||
|
||||
typeMapStringFloat32 = reflect.TypeOf(map[string]float32{})
|
||||
typeMapStringFloat64 = reflect.TypeOf(map[string]float64{})
|
||||
|
||||
typeMapStringBool = reflect.TypeOf(map[string]bool{})
|
||||
typeMapStringString = reflect.TypeOf(map[string]string{})
|
||||
|
||||
typeMapIntString = reflect.TypeOf(map[int]string{})
|
||||
typeMapInt8String = reflect.TypeOf(map[int8]string{})
|
||||
typeMapInt16String = reflect.TypeOf(map[int16]string{})
|
||||
typeMapInt32String = reflect.TypeOf(map[int32]string{})
|
||||
typeMapInt64String = reflect.TypeOf(map[int64]string{})
|
||||
typeMapIntBool = reflect.TypeOf(map[int]bool{})
|
||||
typeMapInt8Bool = reflect.TypeOf(map[int8]bool{})
|
||||
typeMapInt16Bool = reflect.TypeOf(map[int16]bool{})
|
||||
typeMapInt32Bool = reflect.TypeOf(map[int32]bool{})
|
||||
typeMapInt64Bool = reflect.TypeOf(map[int64]bool{})
|
||||
|
||||
typeMapUintString = reflect.TypeOf(map[uint]string{})
|
||||
typeMapUint8String = reflect.TypeOf(map[uint8]string{})
|
||||
typeMapUint16String = reflect.TypeOf(map[uint16]string{})
|
||||
typeMapUint32String = reflect.TypeOf(map[uint32]string{})
|
||||
typeMapUint64String = reflect.TypeOf(map[uint64]string{})
|
||||
typeMapUintBool = reflect.TypeOf(map[uint]bool{})
|
||||
typeMapUint8Bool = reflect.TypeOf(map[uint8]bool{})
|
||||
typeMapUint16Bool = reflect.TypeOf(map[uint16]bool{})
|
||||
typeMapUint32Bool = reflect.TypeOf(map[uint32]bool{})
|
||||
typeMapUint64Bool = reflect.TypeOf(map[uint64]bool{})
|
||||
|
||||
typeMapFloat32String = reflect.TypeOf(map[float32]string{})
|
||||
typeMapFloat64String = reflect.TypeOf(map[float64]string{})
|
||||
typeMapFloat32Bool = reflect.TypeOf(map[float32]bool{})
|
||||
typeMapFloat64Bool = reflect.TypeOf(map[float64]bool{})
|
||||
)
|
||||
|
||||
func (d *decoder) isFixMap(v byte) bool {
|
||||
return def.FixMap <= v && v <= def.FixMap+0x0f
|
||||
}
|
||||
|
||||
func (d *decoder) mapLength(offset int, k reflect.Kind) (int, int, error) {
|
||||
code, offset, err := d.readSize1(offset)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
|
||||
switch {
|
||||
case d.isFixMap(code):
|
||||
return int(code - def.FixMap), offset, nil
|
||||
case code == def.Map16:
|
||||
bs, offset, err := d.readSize2(offset)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
return int(binary.BigEndian.Uint16(bs)), offset, nil
|
||||
case code == def.Map32:
|
||||
bs, offset, err := d.readSize4(offset)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
return int(binary.BigEndian.Uint32(bs)), offset, nil
|
||||
}
|
||||
|
||||
return 0, 0, d.errorTemplate(code, k)
|
||||
}
|
||||
|
||||
func (d *decoder) hasRequiredLeastMapSize(offset, length int) error {
|
||||
// minimum check (byte length)
|
||||
if len(d.data[offset:]) < length*2 {
|
||||
return def.ErrLackDataLengthToMap
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *decoder) asFixedMap(rv reflect.Value, offset int, l int) (int, bool, error) {
|
||||
t := rv.Type()
|
||||
|
||||
keyKind := t.Key().Kind()
|
||||
valueKind := t.Elem().Kind()
|
||||
|
||||
switch t {
|
||||
case typeMapStringInt:
|
||||
m := make(map[string]int, l)
|
||||
for i := 0; i < l; i++ {
|
||||
k, o, err := d.asString(offset, keyKind)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
v, o, err := d.asInt(o, valueKind)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
m[k] = int(v)
|
||||
offset = o
|
||||
}
|
||||
rv.Set(reflect.ValueOf(m))
|
||||
return offset, true, nil
|
||||
|
||||
case typeMapStringUint:
|
||||
m := make(map[string]uint, l)
|
||||
for i := 0; i < l; i++ {
|
||||
k, o, err := d.asString(offset, keyKind)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
v, o, err := d.asUint(o, valueKind)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
m[k] = uint(v)
|
||||
offset = o
|
||||
}
|
||||
rv.Set(reflect.ValueOf(m))
|
||||
return offset, true, nil
|
||||
|
||||
case typeMapStringFloat32:
|
||||
m := make(map[string]float32, l)
|
||||
for i := 0; i < l; i++ {
|
||||
k, o, err := d.asString(offset, keyKind)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
v, o, err := d.asFloat32(o, valueKind)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
m[k] = v
|
||||
offset = o
|
||||
}
|
||||
rv.Set(reflect.ValueOf(m))
|
||||
return offset, true, nil
|
||||
|
||||
case typeMapStringFloat64:
|
||||
m := make(map[string]float64, l)
|
||||
for i := 0; i < l; i++ {
|
||||
k, o, err := d.asString(offset, keyKind)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
v, o, err := d.asFloat64(o, valueKind)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
m[k] = v
|
||||
offset = o
|
||||
}
|
||||
rv.Set(reflect.ValueOf(m))
|
||||
return offset, true, nil
|
||||
|
||||
case typeMapStringBool:
|
||||
m := make(map[string]bool, l)
|
||||
for i := 0; i < l; i++ {
|
||||
k, o, err := d.asString(offset, keyKind)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
v, o, err := d.asBool(o, valueKind)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
m[k] = v
|
||||
offset = o
|
||||
}
|
||||
rv.Set(reflect.ValueOf(m))
|
||||
return offset, true, nil
|
||||
|
||||
case typeMapStringString:
|
||||
m := make(map[string]string, l)
|
||||
for i := 0; i < l; i++ {
|
||||
k, o, err := d.asString(offset, keyKind)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
v, o, err := d.asString(o, valueKind)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
m[k] = v
|
||||
offset = o
|
||||
}
|
||||
rv.Set(reflect.ValueOf(m))
|
||||
return offset, true, nil
|
||||
|
||||
case typeMapStringInt8:
|
||||
m := make(map[string]int8, l)
|
||||
for i := 0; i < l; i++ {
|
||||
k, o, err := d.asString(offset, keyKind)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
v, o, err := d.asInt(o, valueKind)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
m[k] = int8(v)
|
||||
offset = o
|
||||
}
|
||||
rv.Set(reflect.ValueOf(m))
|
||||
return offset, true, nil
|
||||
|
||||
case typeMapStringInt16:
|
||||
m := make(map[string]int16, l)
|
||||
for i := 0; i < l; i++ {
|
||||
k, o, err := d.asString(offset, keyKind)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
v, o, err := d.asInt(o, valueKind)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
m[k] = int16(v)
|
||||
offset = o
|
||||
}
|
||||
rv.Set(reflect.ValueOf(m))
|
||||
return offset, true, nil
|
||||
|
||||
case typeMapStringInt32:
|
||||
m := make(map[string]int32, l)
|
||||
for i := 0; i < l; i++ {
|
||||
k, o, err := d.asString(offset, keyKind)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
v, o, err := d.asInt(o, valueKind)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
m[k] = int32(v)
|
||||
offset = o
|
||||
}
|
||||
rv.Set(reflect.ValueOf(m))
|
||||
return offset, true, nil
|
||||
|
||||
case typeMapStringInt64:
|
||||
m := make(map[string]int64, l)
|
||||
for i := 0; i < l; i++ {
|
||||
k, o, err := d.asString(offset, keyKind)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
v, o, err := d.asInt(o, valueKind)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
m[k] = v
|
||||
offset = o
|
||||
}
|
||||
rv.Set(reflect.ValueOf(m))
|
||||
return offset, true, nil
|
||||
|
||||
case typeMapStringUint8:
|
||||
m := make(map[string]uint8, l)
|
||||
for i := 0; i < l; i++ {
|
||||
k, o, err := d.asString(offset, keyKind)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
v, o, err := d.asUint(o, valueKind)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
m[k] = uint8(v)
|
||||
offset = o
|
||||
}
|
||||
rv.Set(reflect.ValueOf(m))
|
||||
return offset, true, nil
|
||||
case typeMapStringUint16:
|
||||
m := make(map[string]uint16, l)
|
||||
for i := 0; i < l; i++ {
|
||||
k, o, err := d.asString(offset, keyKind)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
v, o, err := d.asUint(o, valueKind)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
m[k] = uint16(v)
|
||||
offset = o
|
||||
}
|
||||
rv.Set(reflect.ValueOf(m))
|
||||
return offset, true, nil
|
||||
|
||||
case typeMapStringUint32:
|
||||
m := make(map[string]uint32, l)
|
||||
for i := 0; i < l; i++ {
|
||||
k, o, err := d.asString(offset, keyKind)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
v, o, err := d.asUint(o, valueKind)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
m[k] = uint32(v)
|
||||
offset = o
|
||||
}
|
||||
rv.Set(reflect.ValueOf(m))
|
||||
return offset, true, nil
|
||||
|
||||
case typeMapStringUint64:
|
||||
m := make(map[string]uint64, l)
|
||||
for i := 0; i < l; i++ {
|
||||
k, o, err := d.asString(offset, keyKind)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
v, o, err := d.asUint(o, valueKind)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
m[k] = v
|
||||
offset = o
|
||||
}
|
||||
rv.Set(reflect.ValueOf(m))
|
||||
return offset, true, nil
|
||||
|
||||
case typeMapIntString:
|
||||
m := make(map[int]string, l)
|
||||
for i := 0; i < l; i++ {
|
||||
k, o, err := d.asInt(offset, keyKind)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
v, o, err := d.asString(o, valueKind)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
m[int(k)] = v
|
||||
offset = o
|
||||
}
|
||||
rv.Set(reflect.ValueOf(m))
|
||||
return offset, true, nil
|
||||
|
||||
case typeMapInt8String:
|
||||
m := make(map[int8]string, l)
|
||||
for i := 0; i < l; i++ {
|
||||
k, o, err := d.asInt(offset, keyKind)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
v, o, err := d.asString(o, valueKind)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
m[int8(k)] = v
|
||||
offset = o
|
||||
}
|
||||
rv.Set(reflect.ValueOf(m))
|
||||
return offset, true, nil
|
||||
|
||||
case typeMapInt16String:
|
||||
m := make(map[int16]string, l)
|
||||
for i := 0; i < l; i++ {
|
||||
k, o, err := d.asInt(offset, keyKind)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
v, o, err := d.asString(o, valueKind)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
m[int16(k)] = v
|
||||
offset = o
|
||||
}
|
||||
rv.Set(reflect.ValueOf(m))
|
||||
return offset, true, nil
|
||||
|
||||
case typeMapInt32String:
|
||||
m := make(map[int32]string, l)
|
||||
for i := 0; i < l; i++ {
|
||||
k, o, err := d.asInt(offset, keyKind)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
v, o, err := d.asString(o, valueKind)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
m[int32(k)] = v
|
||||
offset = o
|
||||
}
|
||||
rv.Set(reflect.ValueOf(m))
|
||||
return offset, true, nil
|
||||
|
||||
case typeMapInt64String:
|
||||
m := make(map[int64]string, l)
|
||||
for i := 0; i < l; i++ {
|
||||
k, o, err := d.asInt(offset, keyKind)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
v, o, err := d.asString(o, valueKind)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
m[k] = v
|
||||
offset = o
|
||||
}
|
||||
rv.Set(reflect.ValueOf(m))
|
||||
return offset, true, nil
|
||||
|
||||
case typeMapIntBool:
|
||||
m := make(map[int]bool, l)
|
||||
for i := 0; i < l; i++ {
|
||||
k, o, err := d.asInt(offset, keyKind)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
v, o, err := d.asBool(o, valueKind)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
m[int(k)] = v
|
||||
offset = o
|
||||
}
|
||||
rv.Set(reflect.ValueOf(m))
|
||||
return offset, true, nil
|
||||
|
||||
case typeMapInt8Bool:
|
||||
m := make(map[int8]bool, l)
|
||||
for i := 0; i < l; i++ {
|
||||
k, o, err := d.asInt(offset, keyKind)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
v, o, err := d.asBool(o, valueKind)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
m[int8(k)] = v
|
||||
offset = o
|
||||
}
|
||||
rv.Set(reflect.ValueOf(m))
|
||||
return offset, true, nil
|
||||
|
||||
case typeMapInt16Bool:
|
||||
m := make(map[int16]bool, l)
|
||||
for i := 0; i < l; i++ {
|
||||
k, o, err := d.asInt(offset, keyKind)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
v, o, err := d.asBool(o, valueKind)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
m[int16(k)] = v
|
||||
offset = o
|
||||
}
|
||||
rv.Set(reflect.ValueOf(m))
|
||||
return offset, true, nil
|
||||
|
||||
case typeMapInt32Bool:
|
||||
m := make(map[int32]bool, l)
|
||||
for i := 0; i < l; i++ {
|
||||
k, o, err := d.asInt(offset, keyKind)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
v, o, err := d.asBool(o, valueKind)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
m[int32(k)] = v
|
||||
offset = o
|
||||
}
|
||||
rv.Set(reflect.ValueOf(m))
|
||||
return offset, true, nil
|
||||
|
||||
case typeMapInt64Bool:
|
||||
m := make(map[int64]bool, l)
|
||||
for i := 0; i < l; i++ {
|
||||
k, o, err := d.asInt(offset, keyKind)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
v, o, err := d.asBool(o, valueKind)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
m[k] = v
|
||||
offset = o
|
||||
}
|
||||
rv.Set(reflect.ValueOf(m))
|
||||
return offset, true, nil
|
||||
|
||||
case typeMapUintString:
|
||||
m := make(map[uint]string, l)
|
||||
for i := 0; i < l; i++ {
|
||||
k, o, err := d.asUint(offset, keyKind)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
v, o, err := d.asString(o, valueKind)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
m[uint(k)] = v
|
||||
offset = o
|
||||
}
|
||||
rv.Set(reflect.ValueOf(m))
|
||||
return offset, true, nil
|
||||
|
||||
case typeMapUint8String:
|
||||
m := make(map[uint8]string, l)
|
||||
for i := 0; i < l; i++ {
|
||||
k, o, err := d.asUint(offset, keyKind)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
v, o, err := d.asString(o, valueKind)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
m[uint8(k)] = v
|
||||
offset = o
|
||||
}
|
||||
rv.Set(reflect.ValueOf(m))
|
||||
return offset, true, nil
|
||||
|
||||
case typeMapUint16String:
|
||||
m := make(map[uint16]string, l)
|
||||
for i := 0; i < l; i++ {
|
||||
k, o, err := d.asUint(offset, keyKind)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
v, o, err := d.asString(o, valueKind)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
m[uint16(k)] = v
|
||||
offset = o
|
||||
}
|
||||
rv.Set(reflect.ValueOf(m))
|
||||
return offset, true, nil
|
||||
|
||||
case typeMapUint32String:
|
||||
m := make(map[uint32]string, l)
|
||||
for i := 0; i < l; i++ {
|
||||
k, o, err := d.asUint(offset, keyKind)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
v, o, err := d.asString(o, valueKind)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
m[uint32(k)] = v
|
||||
offset = o
|
||||
}
|
||||
rv.Set(reflect.ValueOf(m))
|
||||
return offset, true, nil
|
||||
|
||||
case typeMapUint64String:
|
||||
m := make(map[uint64]string, l)
|
||||
for i := 0; i < l; i++ {
|
||||
k, o, err := d.asUint(offset, keyKind)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
v, o, err := d.asString(o, valueKind)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
m[k] = v
|
||||
offset = o
|
||||
}
|
||||
rv.Set(reflect.ValueOf(m))
|
||||
return offset, true, nil
|
||||
|
||||
case typeMapUintBool:
|
||||
m := make(map[uint]bool, l)
|
||||
for i := 0; i < l; i++ {
|
||||
k, o, err := d.asUint(offset, keyKind)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
v, o, err := d.asBool(o, valueKind)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
m[uint(k)] = v
|
||||
offset = o
|
||||
}
|
||||
rv.Set(reflect.ValueOf(m))
|
||||
return offset, true, nil
|
||||
|
||||
case typeMapUint8Bool:
|
||||
m := make(map[uint8]bool, l)
|
||||
for i := 0; i < l; i++ {
|
||||
k, o, err := d.asUint(offset, keyKind)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
v, o, err := d.asBool(o, valueKind)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
m[uint8(k)] = v
|
||||
offset = o
|
||||
}
|
||||
rv.Set(reflect.ValueOf(m))
|
||||
return offset, true, nil
|
||||
|
||||
case typeMapUint16Bool:
|
||||
m := make(map[uint16]bool, l)
|
||||
for i := 0; i < l; i++ {
|
||||
k, o, err := d.asUint(offset, keyKind)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
v, o, err := d.asBool(o, valueKind)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
m[uint16(k)] = v
|
||||
offset = o
|
||||
}
|
||||
rv.Set(reflect.ValueOf(m))
|
||||
return offset, true, nil
|
||||
|
||||
case typeMapUint32Bool:
|
||||
m := make(map[uint32]bool, l)
|
||||
for i := 0; i < l; i++ {
|
||||
k, o, err := d.asUint(offset, keyKind)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
v, o, err := d.asBool(o, valueKind)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
m[uint32(k)] = v
|
||||
offset = o
|
||||
}
|
||||
rv.Set(reflect.ValueOf(m))
|
||||
return offset, true, nil
|
||||
|
||||
case typeMapUint64Bool:
|
||||
m := make(map[uint64]bool, l)
|
||||
for i := 0; i < l; i++ {
|
||||
k, o, err := d.asUint(offset, keyKind)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
v, o, err := d.asBool(o, valueKind)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
m[k] = v
|
||||
offset = o
|
||||
}
|
||||
rv.Set(reflect.ValueOf(m))
|
||||
return offset, true, nil
|
||||
|
||||
case typeMapFloat32String:
|
||||
m := make(map[float32]string, l)
|
||||
for i := 0; i < l; i++ {
|
||||
k, o, err := d.asFloat32(offset, keyKind)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
v, o, err := d.asString(o, valueKind)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
m[k] = v
|
||||
offset = o
|
||||
}
|
||||
rv.Set(reflect.ValueOf(m))
|
||||
return offset, true, nil
|
||||
|
||||
case typeMapFloat64String:
|
||||
m := make(map[float64]string, l)
|
||||
for i := 0; i < l; i++ {
|
||||
k, o, err := d.asFloat64(offset, keyKind)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
v, o, err := d.asString(o, valueKind)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
m[k] = v
|
||||
offset = o
|
||||
}
|
||||
rv.Set(reflect.ValueOf(m))
|
||||
return offset, true, nil
|
||||
|
||||
case typeMapFloat32Bool:
|
||||
m := make(map[float32]bool, l)
|
||||
for i := 0; i < l; i++ {
|
||||
k, o, err := d.asFloat32(offset, keyKind)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
v, o, err := d.asBool(o, valueKind)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
m[k] = v
|
||||
offset = o
|
||||
}
|
||||
rv.Set(reflect.ValueOf(m))
|
||||
return offset, true, nil
|
||||
|
||||
case typeMapFloat64Bool:
|
||||
m := make(map[float64]bool, l)
|
||||
for i := 0; i < l; i++ {
|
||||
k, o, err := d.asFloat64(offset, keyKind)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
v, o, err := d.asBool(o, valueKind)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
m[k] = v
|
||||
offset = o
|
||||
}
|
||||
rv.Set(reflect.ValueOf(m))
|
||||
return offset, true, nil
|
||||
}
|
||||
|
||||
return offset, false, nil
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package decoding
|
||||
|
||||
import "github.com/shamaton/msgpack/v2/def"
|
||||
|
||||
func (d *decoder) isCodeNil(v byte) bool {
|
||||
return def.Nil == v
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
package decoding
|
||||
|
||||
import (
|
||||
"github.com/shamaton/msgpack/v2/def"
|
||||
)
|
||||
|
||||
func (d *decoder) readSize1(index int) (byte, int, error) {
|
||||
rb := def.Byte1
|
||||
if len(d.data) < index+rb {
|
||||
return 0, 0, def.ErrTooShortBytes
|
||||
}
|
||||
return d.data[index], index + rb, nil
|
||||
}
|
||||
|
||||
func (d *decoder) readSize2(index int) ([]byte, int, error) {
|
||||
return d.readSizeN(index, def.Byte2)
|
||||
}
|
||||
|
||||
func (d *decoder) readSize4(index int) ([]byte, int, error) {
|
||||
return d.readSizeN(index, def.Byte4)
|
||||
}
|
||||
|
||||
func (d *decoder) readSize8(index int) ([]byte, int, error) {
|
||||
return d.readSizeN(index, def.Byte8)
|
||||
}
|
||||
|
||||
func (d *decoder) readSizeN(index, n int) ([]byte, int, error) {
|
||||
if len(d.data) < index+n {
|
||||
return emptyBytes, 0, def.ErrTooShortBytes
|
||||
}
|
||||
return d.data[index : index+n], index + n, nil
|
||||
}
|
||||
+257
@@ -0,0 +1,257 @@
|
||||
package decoding
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"reflect"
|
||||
|
||||
"github.com/shamaton/msgpack/v2/def"
|
||||
)
|
||||
|
||||
var (
|
||||
typeIntSlice = reflect.TypeOf([]int{})
|
||||
typeInt8Slice = reflect.TypeOf([]int8{})
|
||||
typeInt16Slice = reflect.TypeOf([]int16{})
|
||||
typeInt32Slice = reflect.TypeOf([]int32{})
|
||||
typeInt64Slice = reflect.TypeOf([]int64{})
|
||||
|
||||
typeUintSlice = reflect.TypeOf([]uint{})
|
||||
typeUint8Slice = reflect.TypeOf([]uint8{})
|
||||
typeUint16Slice = reflect.TypeOf([]uint16{})
|
||||
typeUint32Slice = reflect.TypeOf([]uint32{})
|
||||
typeUint64Slice = reflect.TypeOf([]uint64{})
|
||||
|
||||
typeFloat32Slice = reflect.TypeOf([]float32{})
|
||||
typeFloat64Slice = reflect.TypeOf([]float64{})
|
||||
|
||||
typeStringSlice = reflect.TypeOf([]string{})
|
||||
|
||||
typeBoolSlice = reflect.TypeOf([]bool{})
|
||||
)
|
||||
|
||||
func (d *decoder) isFixSlice(v byte) bool {
|
||||
return def.FixArray <= v && v <= def.FixArray+0x0f
|
||||
}
|
||||
|
||||
func (d *decoder) sliceLength(offset int, k reflect.Kind) (int, int, error) {
|
||||
code, offset, err := d.readSize1(offset)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
|
||||
switch {
|
||||
case d.isFixSlice(code):
|
||||
return int(code - def.FixArray), offset, nil
|
||||
case code == def.Array16:
|
||||
bs, offset, err := d.readSize2(offset)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
return int(binary.BigEndian.Uint16(bs)), offset, nil
|
||||
case code == def.Array32:
|
||||
bs, offset, err := d.readSize4(offset)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
return int(binary.BigEndian.Uint32(bs)), offset, nil
|
||||
}
|
||||
return 0, 0, d.errorTemplate(code, k)
|
||||
}
|
||||
|
||||
func (d *decoder) hasRequiredLeastSliceSize(offset, length int) error {
|
||||
// minimum check (byte length)
|
||||
if len(d.data[offset:]) < length {
|
||||
return def.ErrLackDataLengthToSlice
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *decoder) asFixedSlice(rv reflect.Value, offset int, l int) (int, bool, error) {
|
||||
t := rv.Type()
|
||||
k := t.Elem().Kind()
|
||||
|
||||
switch t {
|
||||
case typeIntSlice:
|
||||
sli := make([]int, l)
|
||||
for i := range sli {
|
||||
v, o, err := d.asInt(offset, k)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
sli[i] = int(v)
|
||||
offset = o
|
||||
}
|
||||
rv.Set(reflect.ValueOf(sli))
|
||||
return offset, true, nil
|
||||
|
||||
case typeUintSlice:
|
||||
sli := make([]uint, l)
|
||||
for i := range sli {
|
||||
v, o, err := d.asUint(offset, k)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
sli[i] = uint(v)
|
||||
offset = o
|
||||
}
|
||||
rv.Set(reflect.ValueOf(sli))
|
||||
return offset, true, nil
|
||||
|
||||
case typeStringSlice:
|
||||
sli := make([]string, l)
|
||||
for i := range sli {
|
||||
v, o, err := d.asString(offset, k)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
sli[i] = v
|
||||
offset = o
|
||||
}
|
||||
rv.Set(reflect.ValueOf(sli))
|
||||
return offset, true, nil
|
||||
|
||||
case typeBoolSlice:
|
||||
sli := make([]bool, l)
|
||||
for i := range sli {
|
||||
v, o, err := d.asBool(offset, k)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
sli[i] = v
|
||||
offset = o
|
||||
}
|
||||
rv.Set(reflect.ValueOf(sli))
|
||||
return offset, true, nil
|
||||
|
||||
case typeFloat32Slice:
|
||||
sli := make([]float32, l)
|
||||
for i := range sli {
|
||||
v, o, err := d.asFloat32(offset, k)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
sli[i] = v
|
||||
offset = o
|
||||
}
|
||||
rv.Set(reflect.ValueOf(sli))
|
||||
return offset, true, nil
|
||||
|
||||
case typeFloat64Slice:
|
||||
sli := make([]float64, l)
|
||||
for i := range sli {
|
||||
v, o, err := d.asFloat64(offset, k)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
sli[i] = v
|
||||
offset = o
|
||||
}
|
||||
rv.Set(reflect.ValueOf(sli))
|
||||
return offset, true, nil
|
||||
|
||||
case typeInt8Slice:
|
||||
sli := make([]int8, l)
|
||||
for i := range sli {
|
||||
v, o, err := d.asInt(offset, k)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
sli[i] = int8(v)
|
||||
offset = o
|
||||
}
|
||||
rv.Set(reflect.ValueOf(sli))
|
||||
return offset, true, nil
|
||||
|
||||
case typeInt16Slice:
|
||||
sli := make([]int16, l)
|
||||
for i := range sli {
|
||||
v, o, err := d.asInt(offset, k)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
sli[i] = int16(v)
|
||||
offset = o
|
||||
}
|
||||
rv.Set(reflect.ValueOf(sli))
|
||||
return offset, true, nil
|
||||
|
||||
case typeInt32Slice:
|
||||
sli := make([]int32, l)
|
||||
for i := range sli {
|
||||
v, o, err := d.asInt(offset, k)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
sli[i] = int32(v)
|
||||
offset = o
|
||||
}
|
||||
rv.Set(reflect.ValueOf(sli))
|
||||
return offset, true, nil
|
||||
|
||||
case typeInt64Slice:
|
||||
sli := make([]int64, l)
|
||||
for i := range sli {
|
||||
v, o, err := d.asInt(offset, k)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
sli[i] = v
|
||||
offset = o
|
||||
}
|
||||
rv.Set(reflect.ValueOf(sli))
|
||||
return offset, true, nil
|
||||
|
||||
case typeUint8Slice:
|
||||
sli := make([]uint8, l)
|
||||
for i := range sli {
|
||||
v, o, err := d.asUint(offset, k)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
sli[i] = uint8(v)
|
||||
offset = o
|
||||
}
|
||||
rv.Set(reflect.ValueOf(sli))
|
||||
return offset, true, nil
|
||||
|
||||
case typeUint16Slice:
|
||||
sli := make([]uint16, l)
|
||||
for i := range sli {
|
||||
v, o, err := d.asUint(offset, k)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
sli[i] = uint16(v)
|
||||
offset = o
|
||||
}
|
||||
rv.Set(reflect.ValueOf(sli))
|
||||
return offset, true, nil
|
||||
|
||||
case typeUint32Slice:
|
||||
sli := make([]uint32, l)
|
||||
for i := range sli {
|
||||
v, o, err := d.asUint(offset, k)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
sli[i] = uint32(v)
|
||||
offset = o
|
||||
}
|
||||
rv.Set(reflect.ValueOf(sli))
|
||||
return offset, true, nil
|
||||
|
||||
case typeUint64Slice:
|
||||
sli := make([]uint64, l)
|
||||
for i := range sli {
|
||||
v, o, err := d.asUint(offset, k)
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
sli[i] = v
|
||||
offset = o
|
||||
}
|
||||
rv.Set(reflect.ValueOf(sli))
|
||||
return offset, true, nil
|
||||
}
|
||||
|
||||
return offset, false, nil
|
||||
}
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
package decoding
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"reflect"
|
||||
|
||||
"github.com/shamaton/msgpack/v2/def"
|
||||
)
|
||||
|
||||
var emptyString = ""
|
||||
var emptyBytes = []byte{}
|
||||
|
||||
func (d *decoder) isCodeString(code byte) bool {
|
||||
return d.isFixString(code) || code == def.Str8 || code == def.Str16 || code == def.Str32
|
||||
}
|
||||
|
||||
func (d *decoder) isFixString(v byte) bool {
|
||||
return def.FixStr <= v && v <= def.FixStr+0x1f
|
||||
}
|
||||
|
||||
func (d *decoder) stringByteLength(offset int, k reflect.Kind) (int, int, error) {
|
||||
code, offset, err := d.readSize1(offset)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
|
||||
if def.FixStr <= code && code <= def.FixStr+0x1f {
|
||||
l := int(code - def.FixStr)
|
||||
return l, offset, nil
|
||||
} else if code == def.Str8 {
|
||||
b, offset, err := d.readSize1(offset)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
return int(b), offset, nil
|
||||
} else if code == def.Str16 {
|
||||
b, offset, err := d.readSize2(offset)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
return int(binary.BigEndian.Uint16(b)), offset, nil
|
||||
} else if code == def.Str32 {
|
||||
b, offset, err := d.readSize4(offset)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
return int(binary.BigEndian.Uint32(b)), offset, nil
|
||||
} else if code == def.Nil {
|
||||
return 0, offset, nil
|
||||
}
|
||||
return 0, 0, d.errorTemplate(code, k)
|
||||
}
|
||||
|
||||
func (d *decoder) asString(offset int, k reflect.Kind) (string, int, error) {
|
||||
bs, offset, err := d.asStringByte(offset, k)
|
||||
if err != nil {
|
||||
return emptyString, 0, err
|
||||
}
|
||||
return string(bs), offset, nil
|
||||
}
|
||||
|
||||
func (d *decoder) asStringByte(offset int, k reflect.Kind) ([]byte, int, error) {
|
||||
l, offset, err := d.stringByteLength(offset, k)
|
||||
if err != nil {
|
||||
return emptyBytes, 0, err
|
||||
}
|
||||
|
||||
return d.asStringByteByLength(offset, l, k)
|
||||
}
|
||||
|
||||
func (d *decoder) asStringByteByLength(offset int, l int, k reflect.Kind) ([]byte, int, error) {
|
||||
if l < 1 {
|
||||
return emptyBytes, offset, nil
|
||||
}
|
||||
|
||||
return d.readSizeN(offset, l)
|
||||
}
|
||||
+315
@@ -0,0 +1,315 @@
|
||||
package decoding
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"reflect"
|
||||
"sync"
|
||||
|
||||
"github.com/shamaton/msgpack/v2/def"
|
||||
)
|
||||
|
||||
type structCacheTypeMap struct {
|
||||
keys [][]byte
|
||||
indexes []int
|
||||
}
|
||||
|
||||
type structCacheTypeArray struct {
|
||||
m []int
|
||||
}
|
||||
|
||||
// struct cache map
|
||||
var mapSCTM = sync.Map{}
|
||||
var mapSCTA = sync.Map{}
|
||||
|
||||
func (d *decoder) setStruct(rv reflect.Value, offset int, k reflect.Kind) (int, error) {
|
||||
/*
|
||||
if d.isDateTime(offset) {
|
||||
dt, offset, err := d.asDateTime(offset, k)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
rv.Set(reflect.ValueOf(dt))
|
||||
return offset, nil
|
||||
}
|
||||
*/
|
||||
|
||||
for i := range extCoders {
|
||||
if extCoders[i].IsType(offset, &d.data) {
|
||||
v, offset, err := extCoders[i].AsValue(offset, k, &d.data)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// Validate that the receptacle is of the right value type.
|
||||
if rv.Type() == reflect.TypeOf(v) {
|
||||
rv.Set(reflect.ValueOf(v))
|
||||
return offset, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if d.asArray {
|
||||
return d.setStructFromArray(rv, offset, k)
|
||||
}
|
||||
return d.setStructFromMap(rv, offset, k)
|
||||
}
|
||||
|
||||
func (d *decoder) setStructFromArray(rv reflect.Value, offset int, k reflect.Kind) (int, error) {
|
||||
// get length
|
||||
l, o, err := d.sliceLength(offset, k)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
if err = d.hasRequiredLeastSliceSize(o, l); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// find or create reference
|
||||
var scta *structCacheTypeArray
|
||||
cache, findCache := mapSCTA.Load(rv.Type())
|
||||
if !findCache {
|
||||
scta = &structCacheTypeArray{}
|
||||
for i := 0; i < rv.NumField(); i++ {
|
||||
if ok, _, _ := d.CheckField(rv.Type().Field(i)); ok {
|
||||
scta.m = append(scta.m, i)
|
||||
}
|
||||
}
|
||||
mapSCTA.Store(rv.Type(), scta)
|
||||
} else {
|
||||
scta = cache.(*structCacheTypeArray)
|
||||
}
|
||||
// set value
|
||||
for i := 0; i < l; i++ {
|
||||
if i < len(scta.m) {
|
||||
o, err = d.decode(rv.Field(scta.m[i]), o)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
} else {
|
||||
o, err = d.jumpOffset(o)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
}
|
||||
return o, nil
|
||||
}
|
||||
|
||||
func (d *decoder) setStructFromMap(rv reflect.Value, offset int, k reflect.Kind) (int, error) {
|
||||
// get length
|
||||
l, o, err := d.mapLength(offset, k)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
if err = d.hasRequiredLeastMapSize(o, l); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
var sctm *structCacheTypeMap
|
||||
cache, cacheFind := mapSCTM.Load(rv.Type())
|
||||
if !cacheFind {
|
||||
sctm = &structCacheTypeMap{}
|
||||
for i := 0; i < rv.NumField(); i++ {
|
||||
if ok, _, name := d.CheckField(rv.Type().Field(i)); ok {
|
||||
sctm.keys = append(sctm.keys, []byte(name))
|
||||
sctm.indexes = append(sctm.indexes, i)
|
||||
}
|
||||
}
|
||||
mapSCTM.Store(rv.Type(), sctm)
|
||||
} else {
|
||||
sctm = cache.(*structCacheTypeMap)
|
||||
}
|
||||
|
||||
for i := 0; i < l; i++ {
|
||||
dataKey, o2, err := d.asStringByte(o, k)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
fieldIndex := -1
|
||||
for keyIndex, keyBytes := range sctm.keys {
|
||||
if len(keyBytes) != len(dataKey) {
|
||||
continue
|
||||
}
|
||||
|
||||
fieldIndex = sctm.indexes[keyIndex]
|
||||
for dataIndex := range dataKey {
|
||||
if dataKey[dataIndex] != keyBytes[dataIndex] {
|
||||
fieldIndex = -1
|
||||
break
|
||||
}
|
||||
}
|
||||
if fieldIndex >= 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if fieldIndex >= 0 {
|
||||
o2, err = d.decode(rv.Field(fieldIndex), o2)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
} else {
|
||||
o2, err = d.jumpOffset(o2)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
o = o2
|
||||
}
|
||||
return o, nil
|
||||
}
|
||||
|
||||
func (d *decoder) jumpOffset(offset int) (int, error) {
|
||||
code, offset, err := d.readSize1(offset)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
switch {
|
||||
case code == def.True, code == def.False, code == def.Nil:
|
||||
// do nothing
|
||||
|
||||
case d.isPositiveFixNum(code) || d.isNegativeFixNum(code):
|
||||
// do nothing
|
||||
case code == def.Uint8, code == def.Int8:
|
||||
offset += def.Byte1
|
||||
case code == def.Uint16, code == def.Int16:
|
||||
offset += def.Byte2
|
||||
case code == def.Uint32, code == def.Int32, code == def.Float32:
|
||||
offset += def.Byte4
|
||||
case code == def.Uint64, code == def.Int64, code == def.Float64:
|
||||
offset += def.Byte8
|
||||
|
||||
case d.isFixString(code):
|
||||
offset += int(code - def.FixStr)
|
||||
case code == def.Str8, code == def.Bin8:
|
||||
b, o, err := d.readSize1(offset)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
o += int(b)
|
||||
offset = o
|
||||
case code == def.Str16, code == def.Bin16:
|
||||
bs, o, err := d.readSize2(offset)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
o += int(binary.BigEndian.Uint16(bs))
|
||||
offset = o
|
||||
case code == def.Str32, code == def.Bin32:
|
||||
bs, o, err := d.readSize4(offset)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
o += int(binary.BigEndian.Uint32(bs))
|
||||
offset = o
|
||||
|
||||
case d.isFixSlice(code):
|
||||
l := int(code - def.FixArray)
|
||||
for i := 0; i < l; i++ {
|
||||
offset, err = d.jumpOffset(offset)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
case code == def.Array16:
|
||||
bs, o, err := d.readSize2(offset)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
l := int(binary.BigEndian.Uint16(bs))
|
||||
for i := 0; i < l; i++ {
|
||||
o, err = d.jumpOffset(o)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
offset = o
|
||||
case code == def.Array32:
|
||||
bs, o, err := d.readSize4(offset)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
l := int(binary.BigEndian.Uint32(bs))
|
||||
for i := 0; i < l; i++ {
|
||||
o, err = d.jumpOffset(o)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
offset = o
|
||||
|
||||
case d.isFixMap(code):
|
||||
l := int(code - def.FixMap)
|
||||
for i := 0; i < l*2; i++ {
|
||||
offset, err = d.jumpOffset(offset)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
case code == def.Map16:
|
||||
bs, o, err := d.readSize2(offset)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
l := int(binary.BigEndian.Uint16(bs))
|
||||
for i := 0; i < l*2; i++ {
|
||||
o, err = d.jumpOffset(o)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
offset = o
|
||||
case code == def.Map32:
|
||||
bs, o, err := d.readSize4(offset)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
l := int(binary.BigEndian.Uint32(bs))
|
||||
for i := 0; i < l*2; i++ {
|
||||
o, err = d.jumpOffset(o)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
offset = o
|
||||
|
||||
case code == def.Fixext1:
|
||||
offset += def.Byte1 + def.Byte1
|
||||
case code == def.Fixext2:
|
||||
offset += def.Byte1 + def.Byte2
|
||||
case code == def.Fixext4:
|
||||
offset += def.Byte1 + def.Byte4
|
||||
case code == def.Fixext8:
|
||||
offset += def.Byte1 + def.Byte8
|
||||
case code == def.Fixext16:
|
||||
offset += def.Byte1 + def.Byte16
|
||||
|
||||
case code == def.Ext8:
|
||||
b, o, err := d.readSize1(offset)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
o += def.Byte1 + int(b)
|
||||
offset = o
|
||||
case code == def.Ext16:
|
||||
bs, o, err := d.readSize2(offset)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
o += def.Byte1 + int(binary.BigEndian.Uint16(bs))
|
||||
offset = o
|
||||
case code == def.Ext32:
|
||||
bs, o, err := d.readSize4(offset)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
o += def.Byte1 + int(binary.BigEndian.Uint32(bs))
|
||||
offset = o
|
||||
|
||||
}
|
||||
return offset, nil
|
||||
}
|
||||
+106
@@ -0,0 +1,106 @@
|
||||
package decoding
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"reflect"
|
||||
|
||||
"github.com/shamaton/msgpack/v2/def"
|
||||
)
|
||||
|
||||
func (d *decoder) asUint(offset int, k reflect.Kind) (uint64, int, error) {
|
||||
|
||||
code, _, err := d.readSize1(offset)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
|
||||
switch {
|
||||
case d.isPositiveFixNum(code):
|
||||
b, offset, err := d.readSize1(offset)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
return uint64(b), offset, nil
|
||||
|
||||
case d.isNegativeFixNum(code):
|
||||
b, offset, err := d.readSize1(offset)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
return uint64(int8(b)), offset, nil
|
||||
|
||||
case code == def.Uint8:
|
||||
offset++
|
||||
b, offset, err := d.readSize1(offset)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
return uint64(uint8(b)), offset, nil
|
||||
|
||||
case code == def.Int8:
|
||||
offset++
|
||||
b, offset, err := d.readSize1(offset)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
return uint64(int8(b)), offset, nil
|
||||
|
||||
case code == def.Uint16:
|
||||
offset++
|
||||
bs, offset, err := d.readSize2(offset)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
v := binary.BigEndian.Uint16(bs)
|
||||
return uint64(v), offset, nil
|
||||
|
||||
case code == def.Int16:
|
||||
offset++
|
||||
bs, offset, err := d.readSize2(offset)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
v := int16(binary.BigEndian.Uint16(bs))
|
||||
return uint64(v), offset, nil
|
||||
|
||||
case code == def.Uint32:
|
||||
offset++
|
||||
bs, offset, err := d.readSize4(offset)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
v := binary.BigEndian.Uint32(bs)
|
||||
return uint64(v), offset, nil
|
||||
|
||||
case code == def.Int32:
|
||||
offset++
|
||||
bs, offset, err := d.readSize4(offset)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
v := int32(binary.BigEndian.Uint32(bs))
|
||||
return uint64(v), offset, nil
|
||||
|
||||
case code == def.Uint64:
|
||||
offset++
|
||||
bs, offset, err := d.readSize8(offset)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
return binary.BigEndian.Uint64(bs), offset, nil
|
||||
|
||||
case code == def.Int64:
|
||||
offset++
|
||||
bs, offset, err := d.readSize8(offset)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
return binary.BigEndian.Uint64(bs), offset, nil
|
||||
|
||||
case code == def.Nil:
|
||||
offset++
|
||||
return 0, offset, nil
|
||||
}
|
||||
|
||||
return 0, 0, d.errorTemplate(code, k)
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
package encoding
|
||||
|
||||
import "github.com/shamaton/msgpack/v2/def"
|
||||
|
||||
//func (e *encoder) calcBool() int {
|
||||
// return 0
|
||||
//}
|
||||
|
||||
func (e *encoder) writeBool(v bool, offset int) int {
|
||||
if v {
|
||||
offset = e.setByte1Int(def.True, offset)
|
||||
} else {
|
||||
offset = e.setByte1Int(def.False, offset)
|
||||
}
|
||||
return offset
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
package encoding
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"reflect"
|
||||
|
||||
"github.com/shamaton/msgpack/v2/def"
|
||||
)
|
||||
|
||||
var typeByte = reflect.TypeOf(byte(0))
|
||||
|
||||
func (e *encoder) isByteSlice(rv reflect.Value) bool {
|
||||
return rv.Type().Elem() == typeByte
|
||||
}
|
||||
|
||||
func (e *encoder) calcByteSlice(l int) (int, error) {
|
||||
if l <= math.MaxUint8 {
|
||||
return def.Byte1 + def.Byte1 + l, nil
|
||||
} else if l <= math.MaxUint16 {
|
||||
return def.Byte1 + def.Byte2 + l, nil
|
||||
} else if uint(l) <= math.MaxUint32 {
|
||||
return def.Byte1 + def.Byte4 + l, nil
|
||||
}
|
||||
// not supported error
|
||||
return 0, fmt.Errorf("%w slice length : %d", def.ErrUnsupportedType, l)
|
||||
}
|
||||
|
||||
func (e *encoder) writeByteSliceLength(l int, offset int) int {
|
||||
if l <= math.MaxUint8 {
|
||||
offset = e.setByte1Int(def.Bin8, offset)
|
||||
offset = e.setByte1Int(l, offset)
|
||||
} else if l <= math.MaxUint16 {
|
||||
offset = e.setByte1Int(def.Bin16, offset)
|
||||
offset = e.setByte2Int(l, offset)
|
||||
} else if uint(l) <= math.MaxUint32 {
|
||||
offset = e.setByte1Int(def.Bin32, offset)
|
||||
offset = e.setByte4Int(l, offset)
|
||||
}
|
||||
return offset
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
package encoding
|
||||
|
||||
import (
|
||||
"math"
|
||||
|
||||
"github.com/shamaton/msgpack/v2/def"
|
||||
)
|
||||
|
||||
func (e *encoder) calcComplex64() int {
|
||||
return def.Byte1 + def.Byte1 + def.Byte8
|
||||
}
|
||||
|
||||
func (e *encoder) calcComplex128() int {
|
||||
return def.Byte1 + def.Byte1 + def.Byte16
|
||||
}
|
||||
|
||||
func (e *encoder) writeComplex64(v complex64, offset int) int {
|
||||
offset = e.setByte1Int(def.Fixext8, offset)
|
||||
offset = e.setByte1Int(int(def.ComplexTypeCode()), offset)
|
||||
offset = e.setByte4Uint64(uint64(math.Float32bits(real(v))), offset)
|
||||
offset = e.setByte4Uint64(uint64(math.Float32bits(imag(v))), offset)
|
||||
return offset
|
||||
}
|
||||
|
||||
func (e *encoder) writeComplex128(v complex128, offset int) int {
|
||||
offset = e.setByte1Int(def.Fixext16, offset)
|
||||
offset = e.setByte1Int(int(def.ComplexTypeCode()), offset)
|
||||
offset = e.setByte8Uint64(math.Float64bits(real(v)), offset)
|
||||
offset = e.setByte8Uint64(math.Float64bits(imag(v)), offset)
|
||||
return offset
|
||||
}
|
||||
+382
@@ -0,0 +1,382 @@
|
||||
package encoding
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"reflect"
|
||||
|
||||
"github.com/shamaton/msgpack/v2/def"
|
||||
"github.com/shamaton/msgpack/v2/internal/common"
|
||||
)
|
||||
|
||||
type encoder struct {
|
||||
d []byte
|
||||
asArray bool
|
||||
common.Common
|
||||
mk map[uintptr][]reflect.Value
|
||||
mv map[uintptr][]reflect.Value
|
||||
}
|
||||
|
||||
// Encode returns the MessagePack-encoded byte array of v.
|
||||
func Encode(v interface{}, asArray bool) (b []byte, err error) {
|
||||
e := encoder{asArray: asArray}
|
||||
/*
|
||||
defer func() {
|
||||
e := recover()
|
||||
if e != nil {
|
||||
b = nil
|
||||
err = fmt.Errorf("unexpected error!! \n%s", stackTrace())
|
||||
}
|
||||
}()
|
||||
*/
|
||||
|
||||
rv := reflect.ValueOf(v)
|
||||
if rv.Kind() == reflect.Ptr {
|
||||
rv = rv.Elem()
|
||||
if rv.Kind() == reflect.Ptr {
|
||||
rv = rv.Elem()
|
||||
}
|
||||
}
|
||||
size, err := e.calcSize(rv)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
e.d = make([]byte, size)
|
||||
last := e.create(rv, 0)
|
||||
if size != last {
|
||||
return nil, fmt.Errorf("%w size=%d, lastIdx=%d", def.ErrNotMatchLastIndex, size, last)
|
||||
}
|
||||
return e.d, err
|
||||
}
|
||||
|
||||
//func stackTrace() string {
|
||||
// msg := ""
|
||||
// for depth := 0; ; depth++ {
|
||||
// _, file, line, ok := runtime.Caller(depth)
|
||||
// if !ok {
|
||||
// break
|
||||
// }
|
||||
// msg += fmt.Sprintln(depth, ": ", file, ":", line)
|
||||
// }
|
||||
// return msg
|
||||
//}
|
||||
|
||||
func (e *encoder) calcSize(rv reflect.Value) (int, error) {
|
||||
switch rv.Kind() {
|
||||
case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
|
||||
v := rv.Uint()
|
||||
return e.calcUint(v), nil
|
||||
|
||||
case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
|
||||
v := rv.Int()
|
||||
return e.calcInt(int64(v)), nil
|
||||
|
||||
case reflect.Float32:
|
||||
return e.calcFloat32(0), nil
|
||||
|
||||
case reflect.Float64:
|
||||
return e.calcFloat64(0), nil
|
||||
|
||||
case reflect.String:
|
||||
return e.calcString(rv.String()), nil
|
||||
|
||||
case reflect.Bool:
|
||||
return def.Byte1, nil
|
||||
|
||||
case reflect.Complex64:
|
||||
return e.calcComplex64(), nil
|
||||
|
||||
case reflect.Complex128:
|
||||
return e.calcComplex128(), nil
|
||||
|
||||
case reflect.Slice:
|
||||
if rv.IsNil() {
|
||||
return def.Byte1, nil
|
||||
}
|
||||
// bin format
|
||||
if e.isByteSlice(rv) {
|
||||
size, err := e.calcByteSlice(rv.Len())
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return size, nil
|
||||
}
|
||||
|
||||
if size, find := e.calcFixedSlice(rv); find {
|
||||
return size, nil
|
||||
}
|
||||
|
||||
// func
|
||||
elem := rv.Type().Elem()
|
||||
var f structCalcFunc
|
||||
if elem.Kind() == reflect.Struct {
|
||||
f = e.getStructCalc(elem)
|
||||
} else {
|
||||
f = e.calcSize
|
||||
}
|
||||
|
||||
l := rv.Len()
|
||||
size, err := e.calcLength(l)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// objects size
|
||||
for i := 0; i < l; i++ {
|
||||
s, err := f(rv.Index(i))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
size += s
|
||||
}
|
||||
return size, nil
|
||||
|
||||
case reflect.Array:
|
||||
// bin format
|
||||
if e.isByteSlice(rv) {
|
||||
size, err := e.calcByteSlice(rv.Len())
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return size, nil
|
||||
}
|
||||
|
||||
// func
|
||||
elem := rv.Type().Elem()
|
||||
var f structCalcFunc
|
||||
if elem.Kind() == reflect.Struct {
|
||||
f = e.getStructCalc(elem)
|
||||
} else {
|
||||
f = e.calcSize
|
||||
}
|
||||
|
||||
l := rv.Len()
|
||||
size, err := e.calcLength(l)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// objects size
|
||||
for i := 0; i < l; i++ {
|
||||
s, err := f(rv.Index(i))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
size += s
|
||||
}
|
||||
return size, nil
|
||||
|
||||
case reflect.Map:
|
||||
if rv.IsNil() {
|
||||
return def.Byte1, nil
|
||||
}
|
||||
|
||||
if size, find := e.calcFixedMap(rv); find {
|
||||
return size, nil
|
||||
}
|
||||
|
||||
if e.mk == nil {
|
||||
e.mk = map[uintptr][]reflect.Value{}
|
||||
e.mv = map[uintptr][]reflect.Value{}
|
||||
}
|
||||
|
||||
keys := rv.MapKeys()
|
||||
size, err := e.calcLength(len(keys))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// key-value
|
||||
mv := make([]reflect.Value, len(keys))
|
||||
i := 0
|
||||
for _, k := range keys {
|
||||
keySize, err := e.calcSize(k)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
value := rv.MapIndex(k)
|
||||
valueSize, err := e.calcSize(value)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
size += keySize + valueSize
|
||||
mv[i] = value
|
||||
i++
|
||||
}
|
||||
e.mk[rv.Pointer()], e.mv[rv.Pointer()] = keys, mv
|
||||
return size, nil
|
||||
|
||||
case reflect.Struct:
|
||||
size, err := e.calcStruct(rv)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return size, nil
|
||||
|
||||
case reflect.Ptr:
|
||||
if rv.IsNil() {
|
||||
return def.Byte1, nil
|
||||
}
|
||||
size, err := e.calcSize(rv.Elem())
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return size, nil
|
||||
|
||||
case reflect.Interface:
|
||||
size, err := e.calcSize(rv.Elem())
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return size, nil
|
||||
|
||||
case reflect.Invalid:
|
||||
// do nothing (return nil)
|
||||
return def.Byte1, nil
|
||||
|
||||
default:
|
||||
return 0, fmt.Errorf("%v is %w type", rv.Kind(), def.ErrUnsupportedType)
|
||||
}
|
||||
}
|
||||
|
||||
func (e *encoder) calcLength(l int) (int, error) {
|
||||
if l <= 0x0f {
|
||||
return def.Byte1, nil
|
||||
} else if l <= math.MaxUint16 {
|
||||
return def.Byte1 + def.Byte2, nil
|
||||
} else if uint(l) <= math.MaxUint32 {
|
||||
return def.Byte1 + def.Byte4, nil
|
||||
}
|
||||
// not supported error
|
||||
return 0, fmt.Errorf("array length %d is %w", l, def.ErrUnsupportedLength)
|
||||
}
|
||||
|
||||
func (e *encoder) create(rv reflect.Value, offset int) int {
|
||||
|
||||
switch rv.Kind() {
|
||||
case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
|
||||
v := rv.Uint()
|
||||
offset = e.writeUint(v, offset)
|
||||
|
||||
case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
|
||||
v := rv.Int()
|
||||
offset = e.writeInt(v, offset)
|
||||
|
||||
case reflect.Float32:
|
||||
offset = e.writeFloat32(rv.Float(), offset)
|
||||
|
||||
case reflect.Float64:
|
||||
offset = e.writeFloat64(rv.Float(), offset)
|
||||
|
||||
case reflect.Bool:
|
||||
offset = e.writeBool(rv.Bool(), offset)
|
||||
|
||||
case reflect.String:
|
||||
offset = e.writeString(rv.String(), offset)
|
||||
|
||||
case reflect.Complex64:
|
||||
offset = e.writeComplex64(complex64(rv.Complex()), offset)
|
||||
|
||||
case reflect.Complex128:
|
||||
offset = e.writeComplex128(rv.Complex(), offset)
|
||||
|
||||
case reflect.Slice:
|
||||
if rv.IsNil() {
|
||||
return e.writeNil(offset)
|
||||
}
|
||||
|
||||
// bin format
|
||||
if e.isByteSlice(rv) {
|
||||
offset = e.writeByteSliceLength(rv.Len(), offset)
|
||||
offset = e.setBytes(rv.Bytes(), offset)
|
||||
return offset
|
||||
}
|
||||
|
||||
if offset, find := e.writeFixedSlice(rv, offset); find {
|
||||
return offset
|
||||
}
|
||||
|
||||
// func
|
||||
elem := rv.Type().Elem()
|
||||
var f structWriteFunc
|
||||
if elem.Kind() == reflect.Struct {
|
||||
f = e.getStructWriter(elem)
|
||||
} else {
|
||||
f = e.create
|
||||
}
|
||||
|
||||
// objects
|
||||
l := rv.Len()
|
||||
offset = e.writeSliceLength(l, offset)
|
||||
for i := 0; i < l; i++ {
|
||||
offset = f(rv.Index(i), offset)
|
||||
}
|
||||
|
||||
case reflect.Array:
|
||||
l := rv.Len()
|
||||
// bin format
|
||||
if e.isByteSlice(rv) {
|
||||
offset = e.writeByteSliceLength(l, offset)
|
||||
// objects
|
||||
for i := 0; i < l; i++ {
|
||||
offset = e.setByte1Uint64(rv.Index(i).Uint(), offset)
|
||||
}
|
||||
return offset
|
||||
}
|
||||
|
||||
// format
|
||||
offset = e.writeSliceLength(l, offset)
|
||||
|
||||
// func
|
||||
elem := rv.Type().Elem()
|
||||
var f structWriteFunc
|
||||
if elem.Kind() == reflect.Struct {
|
||||
f = e.getStructWriter(elem)
|
||||
} else {
|
||||
f = e.create
|
||||
}
|
||||
|
||||
// objects
|
||||
for i := 0; i < l; i++ {
|
||||
offset = f(rv.Index(i), offset)
|
||||
}
|
||||
|
||||
case reflect.Map:
|
||||
if rv.IsNil() {
|
||||
return e.writeNil(offset)
|
||||
}
|
||||
|
||||
l := rv.Len()
|
||||
offset = e.writeMapLength(l, offset)
|
||||
|
||||
if offset, find := e.writeFixedMap(rv, offset); find {
|
||||
return offset
|
||||
}
|
||||
|
||||
// key-value
|
||||
p := rv.Pointer()
|
||||
for i := range e.mk[p] {
|
||||
offset = e.create(e.mk[p][i], offset)
|
||||
offset = e.create(e.mv[p][i], offset)
|
||||
}
|
||||
|
||||
case reflect.Struct:
|
||||
offset = e.writeStruct(rv, offset)
|
||||
|
||||
case reflect.Ptr:
|
||||
if rv.IsNil() {
|
||||
return e.writeNil(offset)
|
||||
}
|
||||
|
||||
offset = e.create(rv.Elem(), offset)
|
||||
|
||||
case reflect.Interface:
|
||||
offset = e.create(rv.Elem(), offset)
|
||||
|
||||
case reflect.Invalid:
|
||||
return e.writeNil(offset)
|
||||
|
||||
}
|
||||
return offset
|
||||
}
|
||||
+97
@@ -0,0 +1,97 @@
|
||||
package encoding
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
|
||||
"github.com/shamaton/msgpack/v2/ext"
|
||||
"github.com/shamaton/msgpack/v2/time"
|
||||
)
|
||||
|
||||
var extCoderMap = map[reflect.Type]ext.Encoder{time.Encoder.Type(): time.Encoder}
|
||||
var extCoders = []ext.Encoder{time.Encoder}
|
||||
|
||||
// AddExtEncoder adds encoders for extension types.
|
||||
func AddExtEncoder(f ext.Encoder) {
|
||||
// ignore time
|
||||
if f.Type() == time.Encoder.Type() {
|
||||
return
|
||||
}
|
||||
|
||||
_, ok := extCoderMap[f.Type()]
|
||||
if !ok {
|
||||
extCoderMap[f.Type()] = f
|
||||
updateExtCoders()
|
||||
}
|
||||
}
|
||||
|
||||
// RemoveExtEncoder removes encoders for extension types.
|
||||
func RemoveExtEncoder(f ext.Encoder) {
|
||||
// ignore time
|
||||
if f.Type() == time.Encoder.Type() {
|
||||
return
|
||||
}
|
||||
|
||||
_, ok := extCoderMap[f.Type()]
|
||||
if ok {
|
||||
delete(extCoderMap, f.Type())
|
||||
updateExtCoders()
|
||||
}
|
||||
}
|
||||
|
||||
func updateExtCoders() {
|
||||
extCoders = make([]ext.Encoder, len(extCoderMap))
|
||||
i := 0
|
||||
for k := range extCoderMap {
|
||||
extCoders[i] = extCoderMap[k]
|
||||
i++
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
func (e *encoder) isDateTime(value reflect.Value) (bool, time.Time) {
|
||||
i := value.Interface()
|
||||
switch t := i.(type) {
|
||||
case time.Time:
|
||||
return true, t
|
||||
}
|
||||
return false, now
|
||||
}
|
||||
|
||||
func (e *encoder) calcTime(t time.Time) int {
|
||||
secs := uint64(t.Unix())
|
||||
if secs>>34 == 0 {
|
||||
data := uint64(t.Nanosecond())<<34 | secs
|
||||
if data&0xffffffff00000000 == 0 {
|
||||
return def.Byte1 + def.Byte4
|
||||
}
|
||||
return def.Byte1 + def.Byte8
|
||||
}
|
||||
|
||||
return def.Byte1 + def.Byte1 + def.Byte4 + def.Byte8
|
||||
}
|
||||
|
||||
func (e *encoder) writeTime(t time.Time, offset int) int {
|
||||
secs := uint64(t.Unix())
|
||||
if secs>>34 == 0 {
|
||||
data := uint64(t.Nanosecond())<<34 | secs
|
||||
if data&0xffffffff00000000 == 0 {
|
||||
offset = e.setByte1Int(def.Fixext4, offset)
|
||||
offset = e.setByte1Int(def.TimeStamp, offset)
|
||||
offset = e.setByte4Uint64(data, offset)
|
||||
return offset
|
||||
}
|
||||
|
||||
offset = e.setByte1Int(def.Fixext8, offset)
|
||||
offset = e.setByte1Int(def.TimeStamp, offset)
|
||||
offset = e.setByte8Uint64(data, offset)
|
||||
return offset
|
||||
}
|
||||
|
||||
offset = e.setByte1Int(def.Ext8, offset)
|
||||
offset = e.setByte1Int(12, offset)
|
||||
offset = e.setByte1Int(def.TimeStamp, offset)
|
||||
offset = e.setByte4Int(t.Nanosecond(), offset)
|
||||
offset = e.setByte8Uint64(secs, offset)
|
||||
return offset
|
||||
}
|
||||
*/
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
package encoding
|
||||
|
||||
import (
|
||||
"math"
|
||||
|
||||
"github.com/shamaton/msgpack/v2/def"
|
||||
)
|
||||
|
||||
func (e *encoder) calcFloat32(_ float64) int {
|
||||
return def.Byte1 + def.Byte4
|
||||
}
|
||||
|
||||
func (e *encoder) calcFloat64(_ float64) int {
|
||||
return def.Byte1 + def.Byte8
|
||||
}
|
||||
|
||||
func (e *encoder) writeFloat32(v float64, offset int) int {
|
||||
offset = e.setByte1Int(def.Float32, offset)
|
||||
offset = e.setByte4Uint64(uint64(math.Float32bits(float32(v))), offset)
|
||||
return offset
|
||||
}
|
||||
|
||||
func (e *encoder) writeFloat64(v float64, offset int) int {
|
||||
offset = e.setByte1Int(def.Float64, offset)
|
||||
offset = e.setByte8Uint64(math.Float64bits(v), offset)
|
||||
return offset
|
||||
}
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
package encoding
|
||||
|
||||
import (
|
||||
"math"
|
||||
|
||||
"github.com/shamaton/msgpack/v2/def"
|
||||
)
|
||||
|
||||
func (e *encoder) isNegativeFixInt64(v int64) bool {
|
||||
return def.NegativeFixintMin <= v && v <= def.NegativeFixintMax
|
||||
}
|
||||
|
||||
func (e *encoder) calcInt(v int64) int {
|
||||
if v >= 0 {
|
||||
return e.calcUint(uint64(v))
|
||||
} else if e.isNegativeFixInt64(v) {
|
||||
// format code only
|
||||
return def.Byte1
|
||||
} else if v >= math.MinInt8 {
|
||||
return def.Byte1 + def.Byte1
|
||||
} else if v >= math.MinInt16 {
|
||||
return def.Byte1 + def.Byte2
|
||||
} else if v >= math.MinInt32 {
|
||||
return def.Byte1 + def.Byte4
|
||||
}
|
||||
return def.Byte1 + def.Byte8
|
||||
}
|
||||
|
||||
func (e *encoder) writeInt(v int64, offset int) int {
|
||||
if v >= 0 {
|
||||
offset = e.writeUint(uint64(v), offset)
|
||||
} else if e.isNegativeFixInt64(v) {
|
||||
offset = e.setByte1Int64(v, offset)
|
||||
} else if v >= math.MinInt8 {
|
||||
offset = e.setByte1Int(def.Int8, offset)
|
||||
offset = e.setByte1Int64(v, offset)
|
||||
} else if v >= math.MinInt16 {
|
||||
offset = e.setByte1Int(def.Int16, offset)
|
||||
offset = e.setByte2Int64(v, offset)
|
||||
} else if v >= math.MinInt32 {
|
||||
offset = e.setByte1Int(def.Int32, offset)
|
||||
offset = e.setByte4Int64(v, offset)
|
||||
} else {
|
||||
offset = e.setByte1Int(def.Int64, offset)
|
||||
offset = e.setByte8Int64(v, offset)
|
||||
}
|
||||
return offset
|
||||
}
|
||||
+559
@@ -0,0 +1,559 @@
|
||||
package encoding
|
||||
|
||||
import (
|
||||
"math"
|
||||
"reflect"
|
||||
|
||||
"github.com/shamaton/msgpack/v2/def"
|
||||
)
|
||||
|
||||
func (e *encoder) calcFixedMap(rv reflect.Value) (int, bool) {
|
||||
// calcLength formally returns (int, error), but for map lengths in Go
|
||||
// the error case is unreachable. The error value is always nil and is
|
||||
// intentionally ignored with `_`.
|
||||
switch m := rv.Interface().(type) {
|
||||
case map[string]int:
|
||||
size, _ := e.calcLength(len(m))
|
||||
for k, v := range m {
|
||||
size += e.calcString(k)
|
||||
size += e.calcInt(int64(v))
|
||||
}
|
||||
return size, true
|
||||
|
||||
case map[string]uint:
|
||||
size, _ := e.calcLength(len(m))
|
||||
for k, v := range m {
|
||||
size += e.calcString(k)
|
||||
size += e.calcUint(uint64(v))
|
||||
}
|
||||
return size, true
|
||||
|
||||
case map[string]string:
|
||||
size, _ := e.calcLength(len(m))
|
||||
for k, v := range m {
|
||||
size += e.calcString(k)
|
||||
size += e.calcString(v)
|
||||
}
|
||||
return size, true
|
||||
|
||||
case map[string]float32:
|
||||
size, _ := e.calcLength(len(m))
|
||||
for k := range m {
|
||||
size += e.calcString(k)
|
||||
size += e.calcFloat32(0)
|
||||
}
|
||||
return size, true
|
||||
|
||||
case map[string]float64:
|
||||
size, _ := e.calcLength(len(m))
|
||||
for k := range m {
|
||||
size += e.calcString(k)
|
||||
size += e.calcFloat64(0)
|
||||
}
|
||||
return size, true
|
||||
|
||||
case map[string]bool:
|
||||
size, _ := e.calcLength(len(m))
|
||||
for k := range m {
|
||||
size += e.calcString(k)
|
||||
size += def.Byte1 /*+ e.calcBool()*/
|
||||
}
|
||||
return size, true
|
||||
|
||||
case map[string]int8:
|
||||
size, _ := e.calcLength(len(m))
|
||||
for k, v := range m {
|
||||
size += e.calcString(k)
|
||||
size += e.calcInt(int64(v))
|
||||
}
|
||||
return size, true
|
||||
case map[string]int16:
|
||||
size, _ := e.calcLength(len(m))
|
||||
for k, v := range m {
|
||||
size += e.calcString(k)
|
||||
size += e.calcInt(int64(v))
|
||||
}
|
||||
return size, true
|
||||
case map[string]int32:
|
||||
size, _ := e.calcLength(len(m))
|
||||
for k, v := range m {
|
||||
size += e.calcString(k)
|
||||
size += e.calcInt(int64(v))
|
||||
}
|
||||
return size, true
|
||||
case map[string]int64:
|
||||
size, _ := e.calcLength(len(m))
|
||||
for k, v := range m {
|
||||
size += e.calcString(k)
|
||||
size += e.calcInt(v)
|
||||
}
|
||||
return size, true
|
||||
case map[string]uint8:
|
||||
size, _ := e.calcLength(len(m))
|
||||
for k, v := range m {
|
||||
size += e.calcString(k)
|
||||
size += e.calcUint(uint64(v))
|
||||
}
|
||||
return size, true
|
||||
case map[string]uint16:
|
||||
size, _ := e.calcLength(len(m))
|
||||
for k, v := range m {
|
||||
size += e.calcString(k)
|
||||
size += e.calcUint(uint64(v))
|
||||
}
|
||||
return size, true
|
||||
case map[string]uint32:
|
||||
size, _ := e.calcLength(len(m))
|
||||
for k, v := range m {
|
||||
size += e.calcString(k)
|
||||
size += e.calcUint(uint64(v))
|
||||
}
|
||||
return size, true
|
||||
case map[string]uint64:
|
||||
size, _ := e.calcLength(len(m))
|
||||
for k, v := range m {
|
||||
size += e.calcString(k)
|
||||
size += e.calcUint(v)
|
||||
}
|
||||
return size, true
|
||||
|
||||
case map[int]string:
|
||||
size, _ := e.calcLength(len(m))
|
||||
for k, v := range m {
|
||||
size += e.calcInt(int64(k))
|
||||
size += e.calcString(v)
|
||||
}
|
||||
return size, true
|
||||
case map[int]bool:
|
||||
size, _ := e.calcLength(len(m))
|
||||
for k := range m {
|
||||
size += e.calcInt(int64(k))
|
||||
size += def.Byte1 /* + e.calcBool()*/
|
||||
}
|
||||
return size, true
|
||||
|
||||
case map[uint]string:
|
||||
size, _ := e.calcLength(len(m))
|
||||
for k, v := range m {
|
||||
size += e.calcUint(uint64(k))
|
||||
size += e.calcString(v)
|
||||
}
|
||||
return size, true
|
||||
case map[uint]bool:
|
||||
size, _ := e.calcLength(len(m))
|
||||
for k := range m {
|
||||
size += e.calcUint(uint64(k))
|
||||
size += def.Byte1 /* + e.calcBool()*/
|
||||
}
|
||||
return size, true
|
||||
|
||||
case map[float32]string:
|
||||
size, _ := e.calcLength(len(m))
|
||||
for k, v := range m {
|
||||
size += e.calcFloat32(float64(k))
|
||||
size += e.calcString(v)
|
||||
}
|
||||
return size, true
|
||||
case map[float32]bool:
|
||||
size, _ := e.calcLength(len(m))
|
||||
for k := range m {
|
||||
size += e.calcFloat32(float64(k))
|
||||
size += def.Byte1 /* + e.calcBool()*/
|
||||
}
|
||||
return size, true
|
||||
|
||||
case map[float64]string:
|
||||
size, _ := e.calcLength(len(m))
|
||||
for k, v := range m {
|
||||
size += e.calcFloat64(k)
|
||||
size += e.calcString(v)
|
||||
}
|
||||
return size, true
|
||||
case map[float64]bool:
|
||||
size, _ := e.calcLength(len(m))
|
||||
for k := range m {
|
||||
size += e.calcFloat64(k)
|
||||
size += def.Byte1 /* + e.calcBool()*/
|
||||
}
|
||||
return size, true
|
||||
|
||||
case map[int8]string:
|
||||
size, _ := e.calcLength(len(m))
|
||||
for k, v := range m {
|
||||
size += e.calcInt(int64(k))
|
||||
size += e.calcString(v)
|
||||
}
|
||||
return size, true
|
||||
case map[int8]bool:
|
||||
size, _ := e.calcLength(len(m))
|
||||
for k := range m {
|
||||
size += e.calcInt(int64(k))
|
||||
size += def.Byte1 /* + e.calcBool()*/
|
||||
}
|
||||
return size, true
|
||||
case map[int16]string:
|
||||
size, _ := e.calcLength(len(m))
|
||||
for k, v := range m {
|
||||
size += e.calcInt(int64(k))
|
||||
size += e.calcString(v)
|
||||
}
|
||||
return size, true
|
||||
case map[int16]bool:
|
||||
size, _ := e.calcLength(len(m))
|
||||
for k := range m {
|
||||
size += e.calcInt(int64(k))
|
||||
size += def.Byte1 /* + e.calcBool()*/
|
||||
}
|
||||
return size, true
|
||||
case map[int32]string:
|
||||
size, _ := e.calcLength(len(m))
|
||||
for k, v := range m {
|
||||
size += e.calcInt(int64(k))
|
||||
size += e.calcString(v)
|
||||
}
|
||||
return size, true
|
||||
case map[int32]bool:
|
||||
size, _ := e.calcLength(len(m))
|
||||
for k := range m {
|
||||
size += e.calcInt(int64(k))
|
||||
size += def.Byte1 /* + e.calcBool()*/
|
||||
}
|
||||
return size, true
|
||||
case map[int64]string:
|
||||
size, _ := e.calcLength(len(m))
|
||||
for k, v := range m {
|
||||
size += e.calcInt(k)
|
||||
size += e.calcString(v)
|
||||
}
|
||||
return size, true
|
||||
case map[int64]bool:
|
||||
size, _ := e.calcLength(len(m))
|
||||
for k := range m {
|
||||
size += e.calcInt(k)
|
||||
size += def.Byte1 /* + e.calcBool()*/
|
||||
}
|
||||
return size, true
|
||||
|
||||
case map[uint8]string:
|
||||
size, _ := e.calcLength(len(m))
|
||||
for k, v := range m {
|
||||
size += e.calcUint(uint64(k))
|
||||
size += e.calcString(v)
|
||||
}
|
||||
return size, true
|
||||
case map[uint8]bool:
|
||||
size, _ := e.calcLength(len(m))
|
||||
for k := range m {
|
||||
size += e.calcUint(uint64(k))
|
||||
size += def.Byte1 /* + e.calcBool()*/
|
||||
}
|
||||
return size, true
|
||||
case map[uint16]string:
|
||||
size, _ := e.calcLength(len(m))
|
||||
for k, v := range m {
|
||||
size += e.calcUint(uint64(k))
|
||||
size += e.calcString(v)
|
||||
}
|
||||
return size, true
|
||||
case map[uint16]bool:
|
||||
size, _ := e.calcLength(len(m))
|
||||
for k := range m {
|
||||
size += e.calcUint(uint64(k))
|
||||
size += def.Byte1 /* + e.calcBool()*/
|
||||
}
|
||||
return size, true
|
||||
case map[uint32]string:
|
||||
size, _ := e.calcLength(len(m))
|
||||
for k, v := range m {
|
||||
size += e.calcUint(uint64(k))
|
||||
size += e.calcString(v)
|
||||
}
|
||||
return size, true
|
||||
case map[uint32]bool:
|
||||
size, _ := e.calcLength(len(m))
|
||||
for k := range m {
|
||||
size += e.calcUint(uint64(k))
|
||||
size += def.Byte1 /* + e.calcBool()*/
|
||||
}
|
||||
return size, true
|
||||
case map[uint64]string:
|
||||
size, _ := e.calcLength(len(m))
|
||||
for k, v := range m {
|
||||
size += e.calcUint(k)
|
||||
size += e.calcString(v)
|
||||
}
|
||||
return size, true
|
||||
case map[uint64]bool:
|
||||
size, _ := e.calcLength(len(m))
|
||||
for k := range m {
|
||||
size += e.calcUint(k)
|
||||
size += def.Byte1 /* + e.calcBool()*/
|
||||
}
|
||||
return size, true
|
||||
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
|
||||
func (e *encoder) writeMapLength(l int, offset int) int {
|
||||
|
||||
// format
|
||||
if l <= 0x0f {
|
||||
offset = e.setByte1Int(def.FixMap+l, offset)
|
||||
} else if l <= math.MaxUint16 {
|
||||
offset = e.setByte1Int(def.Map16, offset)
|
||||
offset = e.setByte2Int(l, offset)
|
||||
} else if uint(l) <= math.MaxUint32 {
|
||||
offset = e.setByte1Int(def.Map32, offset)
|
||||
offset = e.setByte4Int(l, offset)
|
||||
}
|
||||
return offset
|
||||
}
|
||||
|
||||
func (e *encoder) writeFixedMap(rv reflect.Value, offset int) (int, bool) {
|
||||
switch m := rv.Interface().(type) {
|
||||
case map[string]int:
|
||||
for k, v := range m {
|
||||
offset = e.writeString(k, offset)
|
||||
offset = e.writeInt(int64(v), offset)
|
||||
}
|
||||
return offset, true
|
||||
|
||||
case map[string]uint:
|
||||
for k, v := range m {
|
||||
offset = e.writeString(k, offset)
|
||||
offset = e.writeUint(uint64(v), offset)
|
||||
}
|
||||
return offset, true
|
||||
|
||||
case map[string]float32:
|
||||
for k, v := range m {
|
||||
offset = e.writeString(k, offset)
|
||||
offset = e.writeFloat32(float64(v), offset)
|
||||
}
|
||||
return offset, true
|
||||
|
||||
case map[string]float64:
|
||||
for k, v := range m {
|
||||
offset = e.writeString(k, offset)
|
||||
offset = e.writeFloat64(v, offset)
|
||||
}
|
||||
return offset, true
|
||||
|
||||
case map[string]bool:
|
||||
for k, v := range m {
|
||||
offset = e.writeString(k, offset)
|
||||
offset = e.writeBool(v, offset)
|
||||
}
|
||||
return offset, true
|
||||
|
||||
case map[string]string:
|
||||
for k, v := range m {
|
||||
offset = e.writeString(k, offset)
|
||||
offset = e.writeString(v, offset)
|
||||
}
|
||||
return offset, true
|
||||
|
||||
case map[string]int8:
|
||||
for k, v := range m {
|
||||
offset = e.writeString(k, offset)
|
||||
offset = e.writeInt(int64(v), offset)
|
||||
}
|
||||
return offset, true
|
||||
case map[string]int16:
|
||||
for k, v := range m {
|
||||
offset = e.writeString(k, offset)
|
||||
offset = e.writeInt(int64(v), offset)
|
||||
}
|
||||
return offset, true
|
||||
case map[string]int32:
|
||||
for k, v := range m {
|
||||
offset = e.writeString(k, offset)
|
||||
offset = e.writeInt(int64(v), offset)
|
||||
}
|
||||
return offset, true
|
||||
case map[string]int64:
|
||||
for k, v := range m {
|
||||
offset = e.writeString(k, offset)
|
||||
offset = e.writeInt(int64(v), offset)
|
||||
}
|
||||
return offset, true
|
||||
|
||||
case map[string]uint8:
|
||||
for k, v := range m {
|
||||
offset = e.writeString(k, offset)
|
||||
offset = e.writeUint(uint64(v), offset)
|
||||
}
|
||||
return offset, true
|
||||
case map[string]uint16:
|
||||
for k, v := range m {
|
||||
offset = e.writeString(k, offset)
|
||||
offset = e.writeUint(uint64(v), offset)
|
||||
}
|
||||
return offset, true
|
||||
case map[string]uint32:
|
||||
for k, v := range m {
|
||||
offset = e.writeString(k, offset)
|
||||
offset = e.writeUint(uint64(v), offset)
|
||||
}
|
||||
return offset, true
|
||||
case map[string]uint64:
|
||||
for k, v := range m {
|
||||
offset = e.writeString(k, offset)
|
||||
offset = e.writeUint(uint64(v), offset)
|
||||
}
|
||||
return offset, true
|
||||
|
||||
case map[int]string:
|
||||
for k, v := range m {
|
||||
offset = e.writeInt(int64(k), offset)
|
||||
offset = e.writeString(v, offset)
|
||||
}
|
||||
return offset, true
|
||||
case map[int]bool:
|
||||
for k, v := range m {
|
||||
offset = e.writeInt(int64(k), offset)
|
||||
offset = e.writeBool(v, offset)
|
||||
}
|
||||
return offset, true
|
||||
|
||||
case map[uint]string:
|
||||
for k, v := range m {
|
||||
offset = e.writeUint(uint64(k), offset)
|
||||
offset = e.writeString(v, offset)
|
||||
}
|
||||
return offset, true
|
||||
case map[uint]bool:
|
||||
for k, v := range m {
|
||||
offset = e.writeUint(uint64(k), offset)
|
||||
offset = e.writeBool(v, offset)
|
||||
}
|
||||
return offset, true
|
||||
|
||||
case map[float32]string:
|
||||
for k, v := range m {
|
||||
offset = e.writeFloat32(float64(k), offset)
|
||||
offset = e.writeString(v, offset)
|
||||
}
|
||||
return offset, true
|
||||
case map[float32]bool:
|
||||
for k, v := range m {
|
||||
offset = e.writeFloat32(float64(k), offset)
|
||||
offset = e.writeBool(v, offset)
|
||||
}
|
||||
return offset, true
|
||||
|
||||
case map[float64]string:
|
||||
for k, v := range m {
|
||||
offset = e.writeFloat64(k, offset)
|
||||
offset = e.writeString(v, offset)
|
||||
}
|
||||
return offset, true
|
||||
case map[float64]bool:
|
||||
for k, v := range m {
|
||||
offset = e.writeFloat64(k, offset)
|
||||
offset = e.writeBool(v, offset)
|
||||
}
|
||||
return offset, true
|
||||
|
||||
case map[int8]string:
|
||||
for k, v := range m {
|
||||
offset = e.writeInt(int64(k), offset)
|
||||
offset = e.writeString(v, offset)
|
||||
}
|
||||
return offset, true
|
||||
case map[int8]bool:
|
||||
for k, v := range m {
|
||||
offset = e.writeInt(int64(k), offset)
|
||||
offset = e.writeBool(v, offset)
|
||||
}
|
||||
return offset, true
|
||||
case map[int16]string:
|
||||
for k, v := range m {
|
||||
offset = e.writeInt(int64(k), offset)
|
||||
offset = e.writeString(v, offset)
|
||||
}
|
||||
return offset, true
|
||||
case map[int16]bool:
|
||||
for k, v := range m {
|
||||
offset = e.writeInt(int64(k), offset)
|
||||
offset = e.writeBool(v, offset)
|
||||
}
|
||||
return offset, true
|
||||
case map[int32]string:
|
||||
for k, v := range m {
|
||||
offset = e.writeInt(int64(k), offset)
|
||||
offset = e.writeString(v, offset)
|
||||
}
|
||||
return offset, true
|
||||
case map[int32]bool:
|
||||
for k, v := range m {
|
||||
offset = e.writeInt(int64(k), offset)
|
||||
offset = e.writeBool(v, offset)
|
||||
}
|
||||
return offset, true
|
||||
case map[int64]string:
|
||||
for k, v := range m {
|
||||
offset = e.writeInt(k, offset)
|
||||
offset = e.writeString(v, offset)
|
||||
}
|
||||
return offset, true
|
||||
case map[int64]bool:
|
||||
for k, v := range m {
|
||||
offset = e.writeInt(k, offset)
|
||||
offset = e.writeBool(v, offset)
|
||||
}
|
||||
return offset, true
|
||||
|
||||
case map[uint8]string:
|
||||
for k, v := range m {
|
||||
offset = e.writeUint(uint64(k), offset)
|
||||
offset = e.writeString(v, offset)
|
||||
}
|
||||
return offset, true
|
||||
case map[uint8]bool:
|
||||
for k, v := range m {
|
||||
offset = e.writeUint(uint64(k), offset)
|
||||
offset = e.writeBool(v, offset)
|
||||
}
|
||||
return offset, true
|
||||
case map[uint16]string:
|
||||
for k, v := range m {
|
||||
offset = e.writeUint(uint64(k), offset)
|
||||
offset = e.writeString(v, offset)
|
||||
}
|
||||
return offset, true
|
||||
case map[uint16]bool:
|
||||
for k, v := range m {
|
||||
offset = e.writeUint(uint64(k), offset)
|
||||
offset = e.writeBool(v, offset)
|
||||
}
|
||||
return offset, true
|
||||
case map[uint32]string:
|
||||
for k, v := range m {
|
||||
offset = e.writeUint(uint64(k), offset)
|
||||
offset = e.writeString(v, offset)
|
||||
}
|
||||
return offset, true
|
||||
case map[uint32]bool:
|
||||
for k, v := range m {
|
||||
offset = e.writeUint(uint64(k), offset)
|
||||
offset = e.writeBool(v, offset)
|
||||
}
|
||||
return offset, true
|
||||
case map[uint64]string:
|
||||
for k, v := range m {
|
||||
offset = e.writeUint(k, offset)
|
||||
offset = e.writeString(v, offset)
|
||||
}
|
||||
return offset, true
|
||||
case map[uint64]bool:
|
||||
for k, v := range m {
|
||||
offset = e.writeUint(k, offset)
|
||||
offset = e.writeBool(v, offset)
|
||||
}
|
||||
return offset, true
|
||||
|
||||
}
|
||||
return offset, false
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
package encoding
|
||||
|
||||
import "github.com/shamaton/msgpack/v2/def"
|
||||
|
||||
func (e *encoder) writeNil(offset int) int {
|
||||
offset = e.setByte1Int(def.Nil, offset)
|
||||
return offset
|
||||
}
|
||||
+89
@@ -0,0 +1,89 @@
|
||||
package encoding
|
||||
|
||||
func (e *encoder) setByte1Int64(value int64, offset int) int {
|
||||
e.d[offset] = byte(value)
|
||||
return offset + 1
|
||||
}
|
||||
|
||||
func (e *encoder) setByte2Int64(value int64, offset int) int {
|
||||
e.d[offset+0] = byte(value >> 8)
|
||||
e.d[offset+1] = byte(value)
|
||||
return offset + 2
|
||||
}
|
||||
|
||||
func (e *encoder) setByte4Int64(value int64, offset int) int {
|
||||
e.d[offset+0] = byte(value >> 24)
|
||||
e.d[offset+1] = byte(value >> 16)
|
||||
e.d[offset+2] = byte(value >> 8)
|
||||
e.d[offset+3] = byte(value)
|
||||
return offset + 4
|
||||
}
|
||||
|
||||
func (e *encoder) setByte8Int64(value int64, offset int) int {
|
||||
e.d[offset] = byte(value >> 56)
|
||||
e.d[offset+1] = byte(value >> 48)
|
||||
e.d[offset+2] = byte(value >> 40)
|
||||
e.d[offset+3] = byte(value >> 32)
|
||||
e.d[offset+4] = byte(value >> 24)
|
||||
e.d[offset+5] = byte(value >> 16)
|
||||
e.d[offset+6] = byte(value >> 8)
|
||||
e.d[offset+7] = byte(value)
|
||||
return offset + 8
|
||||
}
|
||||
|
||||
func (e *encoder) setByte1Uint64(value uint64, offset int) int {
|
||||
e.d[offset] = byte(value)
|
||||
return offset + 1
|
||||
}
|
||||
|
||||
func (e *encoder) setByte2Uint64(value uint64, offset int) int {
|
||||
e.d[offset] = byte(value >> 8)
|
||||
e.d[offset+1] = byte(value)
|
||||
return offset + 2
|
||||
}
|
||||
|
||||
func (e *encoder) setByte4Uint64(value uint64, offset int) int {
|
||||
e.d[offset] = byte(value >> 24)
|
||||
e.d[offset+1] = byte(value >> 16)
|
||||
e.d[offset+2] = byte(value >> 8)
|
||||
e.d[offset+3] = byte(value)
|
||||
return offset + 4
|
||||
}
|
||||
|
||||
func (e *encoder) setByte8Uint64(value uint64, offset int) int {
|
||||
e.d[offset] = byte(value >> 56)
|
||||
e.d[offset+1] = byte(value >> 48)
|
||||
e.d[offset+2] = byte(value >> 40)
|
||||
e.d[offset+3] = byte(value >> 32)
|
||||
e.d[offset+4] = byte(value >> 24)
|
||||
e.d[offset+5] = byte(value >> 16)
|
||||
e.d[offset+6] = byte(value >> 8)
|
||||
e.d[offset+7] = byte(value)
|
||||
return offset + 8
|
||||
}
|
||||
|
||||
func (e *encoder) setByte1Int(code, offset int) int {
|
||||
e.d[offset] = byte(code)
|
||||
return offset + 1
|
||||
}
|
||||
|
||||
func (e *encoder) setByte2Int(value int, offset int) int {
|
||||
e.d[offset] = byte(value >> 8)
|
||||
e.d[offset+1] = byte(value)
|
||||
return offset + 2
|
||||
}
|
||||
|
||||
func (e *encoder) setByte4Int(value int, offset int) int {
|
||||
e.d[offset] = byte(value >> 24)
|
||||
e.d[offset+1] = byte(value >> 16)
|
||||
e.d[offset+2] = byte(value >> 8)
|
||||
e.d[offset+3] = byte(value)
|
||||
return offset + 4
|
||||
}
|
||||
|
||||
func (e *encoder) setBytes(bs []byte, offset int) int {
|
||||
for i := range bs {
|
||||
e.d[offset+i] = bs[i]
|
||||
}
|
||||
return offset + len(bs)
|
||||
}
|
||||
+232
@@ -0,0 +1,232 @@
|
||||
package encoding
|
||||
|
||||
import (
|
||||
"math"
|
||||
"reflect"
|
||||
|
||||
"github.com/shamaton/msgpack/v2/def"
|
||||
)
|
||||
|
||||
func (e *encoder) calcFixedSlice(rv reflect.Value) (int, bool) {
|
||||
// calcLength formally returns (int, error), but for map lengths in Go
|
||||
// the error case is unreachable. The error value is always nil and is
|
||||
// intentionally ignored with `_`.
|
||||
switch sli := rv.Interface().(type) {
|
||||
case []int:
|
||||
size, _ := e.calcLength(len(sli))
|
||||
for _, v := range sli {
|
||||
size += e.calcInt(int64(v))
|
||||
}
|
||||
return size, true
|
||||
|
||||
case []uint:
|
||||
size, _ := e.calcLength(len(sli))
|
||||
for _, v := range sli {
|
||||
size += e.calcUint(uint64(v))
|
||||
}
|
||||
return size, true
|
||||
|
||||
case []string:
|
||||
size, _ := e.calcLength(len(sli))
|
||||
for _, v := range sli {
|
||||
size += e.calcString(v)
|
||||
}
|
||||
return size, true
|
||||
|
||||
case []float32:
|
||||
size, _ := e.calcLength(len(sli))
|
||||
for _, v := range sli {
|
||||
size += e.calcFloat32(float64(v))
|
||||
}
|
||||
return size, true
|
||||
|
||||
case []float64:
|
||||
size, _ := e.calcLength(len(sli))
|
||||
for _, v := range sli {
|
||||
size += e.calcFloat64(v)
|
||||
}
|
||||
return size, true
|
||||
|
||||
case []bool:
|
||||
size, _ := e.calcLength(len(sli))
|
||||
size += def.Byte1 * len(sli)
|
||||
return size, true
|
||||
|
||||
case []int8:
|
||||
size, _ := e.calcLength(len(sli))
|
||||
for _, v := range sli {
|
||||
size += e.calcInt(int64(v))
|
||||
}
|
||||
return size, true
|
||||
|
||||
case []int16:
|
||||
size, _ := e.calcLength(len(sli))
|
||||
for _, v := range sli {
|
||||
size += e.calcInt(int64(v))
|
||||
}
|
||||
return size, true
|
||||
|
||||
case []int32:
|
||||
size, _ := e.calcLength(len(sli))
|
||||
for _, v := range sli {
|
||||
size += e.calcInt(int64(v))
|
||||
}
|
||||
return size, true
|
||||
|
||||
case []int64:
|
||||
size, _ := e.calcLength(len(sli))
|
||||
for _, v := range sli {
|
||||
size += e.calcInt(v)
|
||||
}
|
||||
return size, true
|
||||
|
||||
case []uint8:
|
||||
size, _ := e.calcLength(len(sli))
|
||||
for _, v := range sli {
|
||||
size += e.calcUint(uint64(v))
|
||||
}
|
||||
return size, true
|
||||
|
||||
case []uint16:
|
||||
size, _ := e.calcLength(len(sli))
|
||||
for _, v := range sli {
|
||||
size += e.calcUint(uint64(v))
|
||||
}
|
||||
return size, true
|
||||
|
||||
case []uint32:
|
||||
size, _ := e.calcLength(len(sli))
|
||||
for _, v := range sli {
|
||||
size += e.calcUint(uint64(v))
|
||||
}
|
||||
return size, true
|
||||
|
||||
case []uint64:
|
||||
size, _ := e.calcLength(len(sli))
|
||||
for _, v := range sli {
|
||||
size += e.calcUint(v)
|
||||
}
|
||||
return size, true
|
||||
}
|
||||
|
||||
return 0, false
|
||||
}
|
||||
|
||||
func (e *encoder) writeSliceLength(l int, offset int) int {
|
||||
// format size
|
||||
if l <= 0x0f {
|
||||
offset = e.setByte1Int(def.FixArray+l, offset)
|
||||
} else if l <= math.MaxUint16 {
|
||||
offset = e.setByte1Int(def.Array16, offset)
|
||||
offset = e.setByte2Int(l, offset)
|
||||
} else if uint(l) <= math.MaxUint32 {
|
||||
offset = e.setByte1Int(def.Array32, offset)
|
||||
offset = e.setByte4Int(l, offset)
|
||||
}
|
||||
return offset
|
||||
}
|
||||
|
||||
func (e *encoder) writeFixedSlice(rv reflect.Value, offset int) (int, bool) {
|
||||
|
||||
switch sli := rv.Interface().(type) {
|
||||
case []int:
|
||||
offset = e.writeSliceLength(len(sli), offset)
|
||||
for _, v := range sli {
|
||||
offset = e.writeInt(int64(v), offset)
|
||||
}
|
||||
return offset, true
|
||||
|
||||
case []uint:
|
||||
offset = e.writeSliceLength(len(sli), offset)
|
||||
for _, v := range sli {
|
||||
offset = e.writeUint(uint64(v), offset)
|
||||
}
|
||||
return offset, true
|
||||
|
||||
case []string:
|
||||
offset = e.writeSliceLength(len(sli), offset)
|
||||
for _, v := range sli {
|
||||
offset = e.writeString(v, offset)
|
||||
}
|
||||
return offset, true
|
||||
|
||||
case []float32:
|
||||
offset = e.writeSliceLength(len(sli), offset)
|
||||
for _, v := range sli {
|
||||
offset = e.writeFloat32(float64(v), offset)
|
||||
}
|
||||
return offset, true
|
||||
|
||||
case []float64:
|
||||
offset = e.writeSliceLength(len(sli), offset)
|
||||
for _, v := range sli {
|
||||
offset = e.writeFloat64(float64(v), offset)
|
||||
}
|
||||
return offset, true
|
||||
|
||||
case []bool:
|
||||
offset = e.writeSliceLength(len(sli), offset)
|
||||
for _, v := range sli {
|
||||
offset = e.writeBool(v, offset)
|
||||
}
|
||||
return offset, true
|
||||
|
||||
case []int8:
|
||||
offset = e.writeSliceLength(len(sli), offset)
|
||||
for _, v := range sli {
|
||||
offset = e.writeInt(int64(v), offset)
|
||||
}
|
||||
return offset, true
|
||||
|
||||
case []int16:
|
||||
offset = e.writeSliceLength(len(sli), offset)
|
||||
for _, v := range sli {
|
||||
offset = e.writeInt(int64(v), offset)
|
||||
}
|
||||
return offset, true
|
||||
|
||||
case []int32:
|
||||
offset = e.writeSliceLength(len(sli), offset)
|
||||
for _, v := range sli {
|
||||
offset = e.writeInt(int64(v), offset)
|
||||
}
|
||||
return offset, true
|
||||
|
||||
case []int64:
|
||||
offset = e.writeSliceLength(len(sli), offset)
|
||||
for _, v := range sli {
|
||||
offset = e.writeInt(v, offset)
|
||||
}
|
||||
return offset, true
|
||||
|
||||
case []uint8:
|
||||
offset = e.writeSliceLength(len(sli), offset)
|
||||
for _, v := range sli {
|
||||
offset = e.writeUint(uint64(v), offset)
|
||||
}
|
||||
return offset, true
|
||||
|
||||
case []uint16:
|
||||
offset = e.writeSliceLength(len(sli), offset)
|
||||
for _, v := range sli {
|
||||
offset = e.writeUint(uint64(v), offset)
|
||||
}
|
||||
return offset, true
|
||||
|
||||
case []uint32:
|
||||
offset = e.writeSliceLength(len(sli), offset)
|
||||
for _, v := range sli {
|
||||
offset = e.writeUint(uint64(v), offset)
|
||||
}
|
||||
return offset, true
|
||||
|
||||
case []uint64:
|
||||
offset = e.writeSliceLength(len(sli), offset)
|
||||
for _, v := range sli {
|
||||
offset = e.writeUint(v, offset)
|
||||
}
|
||||
return offset, true
|
||||
}
|
||||
|
||||
return offset, false
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
package encoding
|
||||
|
||||
import (
|
||||
"math"
|
||||
"unsafe"
|
||||
|
||||
"github.com/shamaton/msgpack/v2/def"
|
||||
)
|
||||
|
||||
func (e *encoder) calcString(v string) int {
|
||||
// NOTE : unsafe
|
||||
strBytes := *(*[]byte)(unsafe.Pointer(&v))
|
||||
l := len(strBytes)
|
||||
if l < 32 {
|
||||
return def.Byte1 + l
|
||||
} else if l <= math.MaxUint8 {
|
||||
return def.Byte1 + def.Byte1 + l
|
||||
} else if l <= math.MaxUint16 {
|
||||
return def.Byte1 + def.Byte2 + l
|
||||
}
|
||||
return def.Byte1 + def.Byte4 + l
|
||||
// NOTE : length over uint32
|
||||
}
|
||||
|
||||
func (e *encoder) writeString(str string, offset int) int {
|
||||
// NOTE : unsafe
|
||||
strBytes := *(*[]byte)(unsafe.Pointer(&str))
|
||||
l := len(strBytes)
|
||||
if l < 32 {
|
||||
offset = e.setByte1Int(def.FixStr+l, offset)
|
||||
} else if l <= math.MaxUint8 {
|
||||
offset = e.setByte1Int(def.Str8, offset)
|
||||
offset = e.setByte1Int(l, offset)
|
||||
} else if l <= math.MaxUint16 {
|
||||
offset = e.setByte1Int(def.Str16, offset)
|
||||
offset = e.setByte2Int(l, offset)
|
||||
} else {
|
||||
offset = e.setByte1Int(def.Str32, offset)
|
||||
offset = e.setByte4Int(l, offset)
|
||||
}
|
||||
offset += copy(e.d[offset:], str)
|
||||
return offset
|
||||
}
|
||||
+275
@@ -0,0 +1,275 @@
|
||||
package encoding
|
||||
|
||||
import (
|
||||
"math"
|
||||
"reflect"
|
||||
"sync"
|
||||
|
||||
"github.com/shamaton/msgpack/v2/def"
|
||||
"github.com/shamaton/msgpack/v2/internal/common"
|
||||
)
|
||||
|
||||
type structCache struct {
|
||||
indexes []int
|
||||
names []string
|
||||
omits []bool
|
||||
noOmit bool
|
||||
common.Common
|
||||
}
|
||||
|
||||
var cachemap = sync.Map{}
|
||||
|
||||
type structCalcFunc func(rv reflect.Value) (int, error)
|
||||
type structWriteFunc func(rv reflect.Value, offset int) int
|
||||
|
||||
func (e *encoder) getStructCalc(typ reflect.Type) structCalcFunc {
|
||||
|
||||
for j := range extCoders {
|
||||
if extCoders[j].Type() == typ {
|
||||
return extCoders[j].CalcByteSize
|
||||
}
|
||||
}
|
||||
if e.asArray {
|
||||
return e.calcStructArray
|
||||
}
|
||||
return e.calcStructMap
|
||||
|
||||
}
|
||||
|
||||
func (e *encoder) calcStruct(rv reflect.Value) (int, error) {
|
||||
|
||||
//if isTime, tm := e.isDateTime(rv); isTime {
|
||||
// size := e.calcTime(tm)
|
||||
// return size, nil
|
||||
//}
|
||||
|
||||
for i := range extCoders {
|
||||
if extCoders[i].Type() == rv.Type() {
|
||||
return extCoders[i].CalcByteSize(rv)
|
||||
}
|
||||
}
|
||||
|
||||
if e.asArray {
|
||||
return e.calcStructArray(rv)
|
||||
}
|
||||
return e.calcStructMap(rv)
|
||||
}
|
||||
|
||||
func (e *encoder) calcStructArray(rv reflect.Value) (int, error) {
|
||||
ret := 0
|
||||
t := rv.Type()
|
||||
cache, find := cachemap.Load(t)
|
||||
var c *structCache
|
||||
if !find {
|
||||
num := rv.NumField()
|
||||
c = &structCache{
|
||||
indexes: make([]int, 0, num),
|
||||
names: make([]string, 0, num),
|
||||
omits: make([]bool, 0, num),
|
||||
}
|
||||
omitCount := 0
|
||||
for i := 0; i < num; i++ {
|
||||
field := t.Field(i)
|
||||
if ok, omit, name := e.CheckField(field); ok {
|
||||
size, err := e.calcSize(rv.Field(i))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
ret += size
|
||||
c.indexes = append(c.indexes, i)
|
||||
c.names = append(c.names, name)
|
||||
c.omits = append(c.omits, omit)
|
||||
if omit {
|
||||
omitCount++
|
||||
}
|
||||
}
|
||||
}
|
||||
c.noOmit = omitCount == 0
|
||||
cachemap.Store(t, c)
|
||||
} else {
|
||||
c = cache.(*structCache)
|
||||
for i := 0; i < len(c.indexes); i++ {
|
||||
size, err := e.calcSize(rv.Field(c.indexes[i]))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
ret += size
|
||||
}
|
||||
}
|
||||
|
||||
// format size
|
||||
size, err := e.calcLength(len(c.indexes))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
ret += size
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (e *encoder) calcStructMap(rv reflect.Value) (int, error) {
|
||||
ret := 0
|
||||
t := rv.Type()
|
||||
cache, find := cachemap.Load(t)
|
||||
var c *structCache
|
||||
var l int
|
||||
if !find {
|
||||
num := rv.NumField()
|
||||
c = &structCache{
|
||||
indexes: make([]int, 0, num),
|
||||
names: make([]string, 0, num),
|
||||
omits: make([]bool, 0, num),
|
||||
}
|
||||
omitCount := 0
|
||||
for i := 0; i < num; i++ {
|
||||
if ok, omit, name := e.CheckField(rv.Type().Field(i)); ok {
|
||||
size, err := e.calcSizeWithOmitEmpty(rv.Field(i), name, omit)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
ret += size
|
||||
c.indexes = append(c.indexes, i)
|
||||
c.names = append(c.names, name)
|
||||
c.omits = append(c.omits, omit)
|
||||
if omit {
|
||||
omitCount++
|
||||
}
|
||||
if size > 0 {
|
||||
l++
|
||||
}
|
||||
}
|
||||
}
|
||||
c.noOmit = omitCount == 0
|
||||
cachemap.Store(t, c)
|
||||
} else {
|
||||
c = cache.(*structCache)
|
||||
for i := 0; i < len(c.indexes); i++ {
|
||||
size, err := e.calcSizeWithOmitEmpty(rv.Field(c.indexes[i]), c.names[i], c.omits[i])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
ret += size
|
||||
if size > 0 {
|
||||
l++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// format size
|
||||
size, err := e.calcLength(len(c.indexes))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
ret += size
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (e *encoder) calcSizeWithOmitEmpty(rv reflect.Value, name string, omit bool) (int, error) {
|
||||
keySize := 0
|
||||
valueSize := 0
|
||||
if !omit || !rv.IsZero() {
|
||||
keySize = e.calcString(name)
|
||||
vSize, err := e.calcSize(rv)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
valueSize = vSize
|
||||
}
|
||||
return keySize + valueSize, nil
|
||||
}
|
||||
|
||||
func (e *encoder) getStructWriter(typ reflect.Type) structWriteFunc {
|
||||
|
||||
for i := range extCoders {
|
||||
if extCoders[i].Type() == typ {
|
||||
return func(rv reflect.Value, offset int) int {
|
||||
return extCoders[i].WriteToBytes(rv, offset, &e.d)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if e.asArray {
|
||||
return e.writeStructArray
|
||||
}
|
||||
return e.writeStructMap
|
||||
}
|
||||
|
||||
func (e *encoder) writeStruct(rv reflect.Value, offset int) int {
|
||||
/*
|
||||
if isTime, tm := e.isDateTime(rv); isTime {
|
||||
return e.writeTime(tm, offset)
|
||||
}
|
||||
*/
|
||||
|
||||
for i := range extCoders {
|
||||
if extCoders[i].Type() == rv.Type() {
|
||||
return extCoders[i].WriteToBytes(rv, offset, &e.d)
|
||||
}
|
||||
}
|
||||
|
||||
if e.asArray {
|
||||
return e.writeStructArray(rv, offset)
|
||||
}
|
||||
return e.writeStructMap(rv, offset)
|
||||
}
|
||||
|
||||
func (e *encoder) writeStructArray(rv reflect.Value, offset int) int {
|
||||
|
||||
cache, _ := cachemap.Load(rv.Type())
|
||||
c := cache.(*structCache)
|
||||
|
||||
// write format
|
||||
num := len(c.indexes)
|
||||
if num <= 0x0f {
|
||||
offset = e.setByte1Int(def.FixArray+num, offset)
|
||||
} else if num <= math.MaxUint16 {
|
||||
offset = e.setByte1Int(def.Array16, offset)
|
||||
offset = e.setByte2Int(num, offset)
|
||||
} else if uint(num) <= math.MaxUint32 {
|
||||
offset = e.setByte1Int(def.Array32, offset)
|
||||
offset = e.setByte4Int(num, offset)
|
||||
}
|
||||
|
||||
for i := 0; i < num; i++ {
|
||||
offset = e.create(rv.Field(c.indexes[i]), offset)
|
||||
}
|
||||
return offset
|
||||
}
|
||||
|
||||
func (e *encoder) writeStructMap(rv reflect.Value, offset int) int {
|
||||
|
||||
cache, _ := cachemap.Load(rv.Type())
|
||||
c := cache.(*structCache)
|
||||
|
||||
// format size
|
||||
num := len(c.indexes)
|
||||
l := 0
|
||||
if c.noOmit {
|
||||
l = num
|
||||
} else {
|
||||
for i := 0; i < num; i++ {
|
||||
irv := rv.Field(c.indexes[i])
|
||||
if !c.omits[i] || !irv.IsZero() {
|
||||
l++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if l <= 0x0f {
|
||||
offset = e.setByte1Int(def.FixMap+l, offset)
|
||||
} else if l <= math.MaxUint16 {
|
||||
offset = e.setByte1Int(def.Map16, offset)
|
||||
offset = e.setByte2Int(l, offset)
|
||||
} else if uint(l) <= math.MaxUint32 {
|
||||
offset = e.setByte1Int(def.Map32, offset)
|
||||
offset = e.setByte4Int(l, offset)
|
||||
}
|
||||
|
||||
for i := 0; i < num; i++ {
|
||||
irv := rv.Field(c.indexes[i])
|
||||
if !c.omits[i] || !irv.IsZero() {
|
||||
offset = e.writeString(c.names[i], offset)
|
||||
offset = e.create(irv, offset)
|
||||
}
|
||||
}
|
||||
return offset
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
package encoding
|
||||
|
||||
import (
|
||||
"math"
|
||||
|
||||
"github.com/shamaton/msgpack/v2/def"
|
||||
)
|
||||
|
||||
func (e *encoder) calcUint(v uint64) int {
|
||||
if v <= math.MaxInt8 {
|
||||
// format code only
|
||||
return def.Byte1
|
||||
} else if v <= math.MaxUint8 {
|
||||
return def.Byte1 + def.Byte1
|
||||
} else if v <= math.MaxUint16 {
|
||||
return def.Byte1 + def.Byte2
|
||||
} else if v <= math.MaxUint32 {
|
||||
return def.Byte1 + def.Byte4
|
||||
}
|
||||
return def.Byte1 + def.Byte8
|
||||
}
|
||||
|
||||
func (e *encoder) writeUint(v uint64, offset int) int {
|
||||
if v <= math.MaxInt8 {
|
||||
offset = e.setByte1Uint64(v, offset)
|
||||
} else if v <= math.MaxUint8 {
|
||||
offset = e.setByte1Int(def.Uint8, offset)
|
||||
offset = e.setByte1Uint64(v, offset)
|
||||
} else if v <= math.MaxUint16 {
|
||||
offset = e.setByte1Int(def.Uint16, offset)
|
||||
offset = e.setByte2Uint64(v, offset)
|
||||
} else if v <= math.MaxUint32 {
|
||||
offset = e.setByte1Int(def.Uint32, offset)
|
||||
offset = e.setByte4Uint64(v, offset)
|
||||
} else {
|
||||
offset = e.setByte1Int(def.Uint64, offset)
|
||||
offset = e.setByte8Uint64(v, offset)
|
||||
}
|
||||
return offset
|
||||
}
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
package decoding
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"reflect"
|
||||
"unsafe"
|
||||
|
||||
"github.com/shamaton/msgpack/v2/def"
|
||||
)
|
||||
|
||||
func (d *decoder) isCodeBin(v byte) bool {
|
||||
switch v {
|
||||
case def.Bin8, def.Bin16, def.Bin32:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (d *decoder) asBinWithCode(code byte, k reflect.Kind) ([]byte, error) {
|
||||
|
||||
switch code {
|
||||
case def.Bin8:
|
||||
l, err := d.readSize1()
|
||||
if err != nil {
|
||||
return emptyBytes, err
|
||||
}
|
||||
// avoid common buffer reference
|
||||
return d.copySizeN(int(l))
|
||||
|
||||
case def.Bin16:
|
||||
bs, err := d.readSize2()
|
||||
if err != nil {
|
||||
return emptyBytes, err
|
||||
}
|
||||
// avoid common buffer reference
|
||||
return d.copySizeN(int(binary.BigEndian.Uint16(bs)))
|
||||
|
||||
case def.Bin32:
|
||||
bs, err := d.readSize4()
|
||||
if err != nil {
|
||||
return emptyBytes, err
|
||||
}
|
||||
// avoid common buffer reference
|
||||
return d.copySizeN(int(binary.BigEndian.Uint32(bs)))
|
||||
}
|
||||
|
||||
return emptyBytes, d.errorTemplate(code, k)
|
||||
}
|
||||
|
||||
func (d *decoder) asBinStringWithCode(code byte, k reflect.Kind) (string, error) {
|
||||
bs, err := d.asBinWithCode(code, k)
|
||||
return *(*string)(unsafe.Pointer(&bs)), err
|
||||
}
|
||||
|
||||
func (d *decoder) copySizeN(n int) ([]byte, error) {
|
||||
bs, err := d.readSizeN(n)
|
||||
if err != nil {
|
||||
return emptyBytes, err
|
||||
}
|
||||
v := make([]byte, n)
|
||||
copy(v, bs)
|
||||
return v, nil
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
package decoding
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
|
||||
"github.com/shamaton/msgpack/v2/def"
|
||||
)
|
||||
|
||||
func (d *decoder) asBool(k reflect.Kind) (bool, error) {
|
||||
code, err := d.readSize1()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return d.asBoolWithCode(code, k)
|
||||
}
|
||||
|
||||
func (d *decoder) asBoolWithCode(code byte, k reflect.Kind) (bool, error) {
|
||||
switch code {
|
||||
case def.True:
|
||||
return true, nil
|
||||
case def.False:
|
||||
return false, nil
|
||||
}
|
||||
return false, d.errorTemplate(code, k)
|
||||
}
|
||||
+108
@@ -0,0 +1,108 @@
|
||||
package decoding
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"math"
|
||||
"reflect"
|
||||
|
||||
"github.com/shamaton/msgpack/v2/def"
|
||||
)
|
||||
|
||||
func (d *decoder) asComplex64(code byte, k reflect.Kind) (complex64, error) {
|
||||
switch code {
|
||||
case def.Fixext8:
|
||||
t, err := d.readSize1()
|
||||
if err != nil {
|
||||
return complex(0, 0), err
|
||||
}
|
||||
if int8(t) != def.ComplexTypeCode() {
|
||||
return complex(0, 0), fmt.Errorf("fixext8. complex type is diffrent %d, %d", t, def.ComplexTypeCode())
|
||||
}
|
||||
rb, err := d.readSize4()
|
||||
if err != nil {
|
||||
return complex(0, 0), err
|
||||
}
|
||||
r := math.Float32frombits(binary.BigEndian.Uint32(rb))
|
||||
|
||||
ib, err := d.readSize4()
|
||||
if err != nil {
|
||||
return complex(0, 0), err
|
||||
}
|
||||
i := math.Float32frombits(binary.BigEndian.Uint32(ib))
|
||||
return complex(r, i), nil
|
||||
|
||||
case def.Fixext16:
|
||||
t, err := d.readSize1()
|
||||
if err != nil {
|
||||
return complex(0, 0), err
|
||||
}
|
||||
if int8(t) != def.ComplexTypeCode() {
|
||||
return complex(0, 0), fmt.Errorf("fixext16. complex type is diffrent %d, %d", t, def.ComplexTypeCode())
|
||||
}
|
||||
rb, err := d.readSize8()
|
||||
if err != nil {
|
||||
return complex(0, 0), err
|
||||
}
|
||||
r := math.Float64frombits(binary.BigEndian.Uint64(rb))
|
||||
|
||||
ib, err := d.readSize8()
|
||||
if err != nil {
|
||||
return complex(0, 0), err
|
||||
}
|
||||
i := math.Float64frombits(binary.BigEndian.Uint64(ib))
|
||||
return complex64(complex(r, i)), nil
|
||||
|
||||
}
|
||||
|
||||
return complex(0, 0), d.errorTemplate(code, k)
|
||||
}
|
||||
|
||||
func (d *decoder) asComplex128(code byte, k reflect.Kind) (complex128, error) {
|
||||
switch code {
|
||||
case def.Fixext8:
|
||||
t, err := d.readSize1()
|
||||
if err != nil {
|
||||
return complex(0, 0), err
|
||||
}
|
||||
if int8(t) != def.ComplexTypeCode() {
|
||||
return complex(0, 0), fmt.Errorf("fixext8. complex type is diffrent %d, %d", t, def.ComplexTypeCode())
|
||||
}
|
||||
rb, err := d.readSize4()
|
||||
if err != nil {
|
||||
return complex(0, 0), err
|
||||
}
|
||||
r := math.Float32frombits(binary.BigEndian.Uint32(rb))
|
||||
|
||||
ib, err := d.readSize4()
|
||||
if err != nil {
|
||||
return complex(0, 0), err
|
||||
}
|
||||
i := math.Float32frombits(binary.BigEndian.Uint32(ib))
|
||||
return complex128(complex(r, i)), nil
|
||||
|
||||
case def.Fixext16:
|
||||
t, err := d.readSize1()
|
||||
if err != nil {
|
||||
return complex(0, 0), err
|
||||
}
|
||||
if int8(t) != def.ComplexTypeCode() {
|
||||
return complex(0, 0), fmt.Errorf("fixext16. complex type is diffrent %d, %d", t, def.ComplexTypeCode())
|
||||
}
|
||||
rb, err := d.readSize8()
|
||||
if err != nil {
|
||||
return complex(0, 0), err
|
||||
}
|
||||
r := math.Float64frombits(binary.BigEndian.Uint64(rb))
|
||||
|
||||
ib, err := d.readSize8()
|
||||
if err != nil {
|
||||
return complex(0, 0), err
|
||||
}
|
||||
i := math.Float64frombits(binary.BigEndian.Uint64(ib))
|
||||
return complex(r, i), nil
|
||||
|
||||
}
|
||||
|
||||
return complex(0, 0), d.errorTemplate(code, k)
|
||||
}
|
||||
Generated
Vendored
+324
@@ -0,0 +1,324 @@
|
||||
package decoding
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"reflect"
|
||||
|
||||
"github.com/shamaton/msgpack/v2/def"
|
||||
"github.com/shamaton/msgpack/v2/internal/common"
|
||||
)
|
||||
|
||||
type decoder struct {
|
||||
r io.Reader
|
||||
asArray bool
|
||||
buf *common.Buffer
|
||||
common.Common
|
||||
}
|
||||
|
||||
// Decode analyzes the MessagePack-encoded data and stores
|
||||
// the result into the pointer of v.
|
||||
func Decode(r io.Reader, v interface{}, asArray bool) error {
|
||||
if r == nil {
|
||||
return def.ErrNoData
|
||||
}
|
||||
rv := reflect.ValueOf(v)
|
||||
if rv.Kind() != reflect.Ptr {
|
||||
return fmt.Errorf("%w. v.(type): %T", def.ErrReceiverNotPointer, v)
|
||||
}
|
||||
|
||||
rv = rv.Elem()
|
||||
|
||||
d := decoder{r: r,
|
||||
buf: common.GetBuffer(),
|
||||
asArray: asArray,
|
||||
}
|
||||
err := d.decode(rv)
|
||||
common.PutBuffer(d.buf)
|
||||
return err
|
||||
}
|
||||
|
||||
func (d *decoder) decode(rv reflect.Value) error {
|
||||
code, err := d.readSize1()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return d.decodeWithCode(code, rv)
|
||||
}
|
||||
|
||||
func (d *decoder) decodeWithCode(code byte, rv reflect.Value) error {
|
||||
k := rv.Kind()
|
||||
switch k {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
v, err := d.asIntWithCode(code, k)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rv.SetInt(v)
|
||||
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
v, err := d.asUintWithCode(code, k)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rv.SetUint(v)
|
||||
|
||||
case reflect.Float32:
|
||||
v, err := d.asFloat32WithCode(code, k)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rv.SetFloat(float64(v))
|
||||
|
||||
case reflect.Float64:
|
||||
v, err := d.asFloat64WithCode(code, k)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rv.SetFloat(v)
|
||||
|
||||
case reflect.String:
|
||||
// byte slice
|
||||
if d.isCodeBin(code) {
|
||||
v, err := d.asBinStringWithCode(code, k)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rv.SetString(v)
|
||||
return nil
|
||||
}
|
||||
v, err := d.asStringWithCode(code, k)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rv.SetString(v)
|
||||
|
||||
case reflect.Bool:
|
||||
v, err := d.asBoolWithCode(code, k)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rv.SetBool(v)
|
||||
|
||||
case reflect.Slice:
|
||||
// nil
|
||||
if d.isCodeNil(code) {
|
||||
return nil
|
||||
}
|
||||
// byte slice
|
||||
if d.isCodeBin(code) {
|
||||
bs, err := d.asBinWithCode(code, k)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rv.SetBytes(bs)
|
||||
return nil
|
||||
}
|
||||
// string to bytes
|
||||
if d.isCodeString(code) {
|
||||
l, err := d.stringByteLength(code, k)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
bs, err := d.asStringByteByLength(l, k)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rv.SetBytes(bs)
|
||||
return nil
|
||||
}
|
||||
|
||||
// get slice length
|
||||
l, err := d.sliceLength(code, k)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// check fixed type
|
||||
found, err := d.asFixedSlice(rv, l)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if found {
|
||||
return nil
|
||||
}
|
||||
|
||||
// create slice dynamically
|
||||
tmpSlice := reflect.MakeSlice(rv.Type(), l, l)
|
||||
for i := 0; i < l; i++ {
|
||||
v := tmpSlice.Index(i)
|
||||
if v.Kind() == reflect.Struct {
|
||||
structCode, err := d.readSize1()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err = d.setStruct(structCode, v, k); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if err = d.decode(v); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
rv.Set(tmpSlice)
|
||||
|
||||
case reflect.Complex64:
|
||||
v, err := d.asComplex64(code, k)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rv.SetComplex(complex128(v))
|
||||
|
||||
case reflect.Complex128:
|
||||
v, err := d.asComplex128(code, k)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rv.SetComplex(v)
|
||||
|
||||
case reflect.Array:
|
||||
// nil
|
||||
if d.isCodeNil(code) {
|
||||
return nil
|
||||
}
|
||||
// byte slice
|
||||
if d.isCodeBin(code) {
|
||||
bs, err := d.asBinWithCode(code, k)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(bs) > rv.Len() {
|
||||
return fmt.Errorf("%v len is %d, but msgpack has %d elements, %w", rv.Type(), rv.Len(), len(bs), def.ErrNotMatchArrayElement)
|
||||
}
|
||||
for i, b := range bs {
|
||||
rv.Index(i).SetUint(uint64(b))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
// string to bytes
|
||||
if d.isCodeString(code) {
|
||||
l, err := d.stringByteLength(code, k)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if l > rv.Len() {
|
||||
return fmt.Errorf("%v len is %d, but msgpack has %d elements, %w", rv.Type(), rv.Len(), l, def.ErrNotMatchArrayElement)
|
||||
}
|
||||
bs, err := d.asStringByteByLength(l, k)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for i, b := range bs {
|
||||
rv.Index(i).SetUint(uint64(b))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// get slice length
|
||||
l, err := d.sliceLength(code, k)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if l > rv.Len() {
|
||||
return fmt.Errorf("%v len is %d, but msgpack has %d elements, %w", rv.Type(), rv.Len(), l, def.ErrNotMatchArrayElement)
|
||||
}
|
||||
|
||||
// create array dynamically
|
||||
for i := 0; i < l; i++ {
|
||||
err = d.decode(rv.Index(i))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
case reflect.Map:
|
||||
// nil
|
||||
if d.isCodeNil(code) {
|
||||
return nil
|
||||
}
|
||||
|
||||
// get map length
|
||||
l, err := d.mapLength(code, k)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// check fixed type
|
||||
found, err := d.asFixedMap(rv, l)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if found {
|
||||
return nil
|
||||
}
|
||||
|
||||
// create dynamically
|
||||
key := rv.Type().Key()
|
||||
value := rv.Type().Elem()
|
||||
if rv.IsNil() {
|
||||
rv.Set(reflect.MakeMapWithSize(rv.Type(), l))
|
||||
}
|
||||
for i := 0; i < l; i++ {
|
||||
k := reflect.New(key).Elem()
|
||||
v := reflect.New(value).Elem()
|
||||
err = d.decode(k)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = d.decode(v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
rv.SetMapIndex(k, v)
|
||||
}
|
||||
|
||||
case reflect.Struct:
|
||||
err := d.setStruct(code, rv, k)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
case reflect.Ptr:
|
||||
// nil
|
||||
if d.isCodeNil(code) {
|
||||
return nil
|
||||
}
|
||||
|
||||
if rv.Elem().Kind() == reflect.Invalid {
|
||||
n := reflect.New(rv.Type().Elem())
|
||||
rv.Set(n)
|
||||
}
|
||||
|
||||
err := d.decodeWithCode(code, rv.Elem())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
case reflect.Interface:
|
||||
if rv.Elem().Kind() == reflect.Ptr {
|
||||
err := d.decode(rv.Elem())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
v, err := d.asInterfaceWithCode(code, k)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if v != nil {
|
||||
rv.Set(reflect.ValueOf(v))
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
return fmt.Errorf("%v is %w type", rv.Kind(), def.ErrUnsupportedType)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *decoder) errorTemplate(code byte, k reflect.Kind) error {
|
||||
return fmt.Errorf("%w %x decoding as %v", def.ErrCanNotDecode, code, k)
|
||||
}
|
||||
+160
@@ -0,0 +1,160 @@
|
||||
package decoding
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"github.com/shamaton/msgpack/v2/def"
|
||||
"github.com/shamaton/msgpack/v2/ext"
|
||||
"github.com/shamaton/msgpack/v2/time"
|
||||
)
|
||||
|
||||
var extCoderMap = map[int8]ext.StreamDecoder{time.StreamDecoder.Code(): time.StreamDecoder}
|
||||
var extCoders = []ext.StreamDecoder{time.StreamDecoder}
|
||||
|
||||
// AddExtDecoder adds decoders for extension types.
|
||||
func AddExtDecoder(f ext.StreamDecoder) {
|
||||
// ignore time
|
||||
if f.Code() == time.Decoder.Code() {
|
||||
return
|
||||
}
|
||||
|
||||
_, ok := extCoderMap[f.Code()]
|
||||
if !ok {
|
||||
extCoderMap[f.Code()] = f
|
||||
updateExtCoders()
|
||||
}
|
||||
}
|
||||
|
||||
// RemoveExtDecoder removes decoders for extension types.
|
||||
func RemoveExtDecoder(f ext.StreamDecoder) {
|
||||
// ignore time
|
||||
if f.Code() == time.Decoder.Code() {
|
||||
return
|
||||
}
|
||||
|
||||
_, ok := extCoderMap[f.Code()]
|
||||
if ok {
|
||||
delete(extCoderMap, f.Code())
|
||||
updateExtCoders()
|
||||
}
|
||||
}
|
||||
|
||||
func updateExtCoders() {
|
||||
extCoders = make([]ext.StreamDecoder, len(extCoderMap))
|
||||
i := 0
|
||||
for k := range extCoderMap {
|
||||
extCoders[i] = extCoderMap[k]
|
||||
i++
|
||||
}
|
||||
}
|
||||
|
||||
func (d *decoder) readIfExtType(code byte) (innerType int8, data []byte, err error) {
|
||||
switch code {
|
||||
case def.Fixext1:
|
||||
typ, err := d.readSize1()
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
v, err := d.readSize1()
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
return int8(typ), []byte{v}, nil
|
||||
|
||||
case def.Fixext2:
|
||||
typ, err := d.readSize1()
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
data, err = d.readSize2()
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
return int8(typ), data, nil
|
||||
|
||||
case def.Fixext4:
|
||||
typ, err := d.readSize1()
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
data, err = d.readSize4()
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
return int8(typ), data, nil
|
||||
|
||||
case def.Fixext8:
|
||||
typ, err := d.readSize1()
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
data, err = d.readSize8()
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
return int8(typ), data, nil
|
||||
|
||||
case def.Fixext16:
|
||||
typ, err := d.readSize1()
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
data, err = d.readSize16()
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
return int8(typ), data, nil
|
||||
|
||||
case def.Ext8:
|
||||
bs, err := d.readSize1()
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
size := int(bs)
|
||||
|
||||
typ, err := d.readSize1()
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
data, err = d.readSizeN(size)
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
return int8(typ), data, nil
|
||||
|
||||
case def.Ext16:
|
||||
bs, err := d.readSize2()
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
size := int(binary.BigEndian.Uint16(bs))
|
||||
|
||||
typ, err := d.readSize1()
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
data, err = d.readSizeN(size)
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
return int8(typ), data, nil
|
||||
|
||||
case def.Ext32:
|
||||
bs, err := d.readSize4()
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
size := int(binary.BigEndian.Uint32(bs))
|
||||
|
||||
typ, err := d.readSize1()
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
data, err = d.readSizeN(size)
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
return int8(typ), data, nil
|
||||
}
|
||||
|
||||
return 0, nil, nil
|
||||
}
|
||||
+93
@@ -0,0 +1,93 @@
|
||||
package decoding
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"math"
|
||||
"reflect"
|
||||
|
||||
"github.com/shamaton/msgpack/v2/def"
|
||||
)
|
||||
|
||||
func (d *decoder) asFloat32(k reflect.Kind) (float32, error) {
|
||||
code, err := d.readSize1()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return d.asFloat32WithCode(code, k)
|
||||
}
|
||||
|
||||
func (d *decoder) asFloat32WithCode(code byte, k reflect.Kind) (float32, error) {
|
||||
switch {
|
||||
case code == def.Float32:
|
||||
bs, err := d.readSize4()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
v := math.Float32frombits(binary.BigEndian.Uint32(bs))
|
||||
return v, nil
|
||||
|
||||
case d.isPositiveFixNum(code), code == def.Uint8, code == def.Uint16, code == def.Uint32, code == def.Uint64:
|
||||
v, err := d.asUintWithCode(code, k)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return float32(v), nil
|
||||
|
||||
case d.isNegativeFixNum(code), code == def.Int8, code == def.Int16, code == def.Int32, code == def.Int64:
|
||||
v, err := d.asIntWithCode(code, k)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return float32(v), nil
|
||||
|
||||
case code == def.Nil:
|
||||
return 0, nil
|
||||
}
|
||||
return 0, d.errorTemplate(code, k)
|
||||
}
|
||||
|
||||
func (d *decoder) asFloat64(k reflect.Kind) (float64, error) {
|
||||
code, err := d.readSize1()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return d.asFloat64WithCode(code, k)
|
||||
}
|
||||
|
||||
func (d *decoder) asFloat64WithCode(code byte, k reflect.Kind) (float64, error) {
|
||||
switch {
|
||||
case code == def.Float64:
|
||||
bs, err := d.readSize8()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
v := math.Float64frombits(binary.BigEndian.Uint64(bs))
|
||||
return v, nil
|
||||
|
||||
case code == def.Float32:
|
||||
bs, err := d.readSize4()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
v := math.Float32frombits(binary.BigEndian.Uint32(bs))
|
||||
return float64(v), nil
|
||||
|
||||
case d.isPositiveFixNum(code), code == def.Uint8, code == def.Uint16, code == def.Uint32, code == def.Uint64:
|
||||
v, err := d.asUintWithCode(code, k)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return float64(v), nil
|
||||
|
||||
case d.isNegativeFixNum(code), code == def.Int8, code == def.Int16, code == def.Int32, code == def.Int64:
|
||||
v, err := d.asIntWithCode(code, k)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return float64(v), nil
|
||||
|
||||
case code == def.Nil:
|
||||
return 0, nil
|
||||
}
|
||||
return 0, d.errorTemplate(code, k)
|
||||
}
|
||||
+113
@@ -0,0 +1,113 @@
|
||||
package decoding
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"reflect"
|
||||
|
||||
"github.com/shamaton/msgpack/v2/def"
|
||||
)
|
||||
|
||||
func (d *decoder) isPositiveFixNum(v byte) bool {
|
||||
return def.PositiveFixIntMin <= v && v <= def.PositiveFixIntMax
|
||||
}
|
||||
|
||||
func (d *decoder) isNegativeFixNum(v byte) bool {
|
||||
return def.NegativeFixintMin <= int8(v) && int8(v) <= def.NegativeFixintMax
|
||||
}
|
||||
|
||||
func (d *decoder) asInt(k reflect.Kind) (int64, error) {
|
||||
code, err := d.readSize1()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return d.asIntWithCode(code, k)
|
||||
}
|
||||
|
||||
func (d *decoder) asIntWithCode(code byte, k reflect.Kind) (int64, error) {
|
||||
switch {
|
||||
case d.isPositiveFixNum(code):
|
||||
return int64(code), nil
|
||||
|
||||
case d.isNegativeFixNum(code):
|
||||
return int64(int8(code)), nil
|
||||
|
||||
case code == def.Uint8:
|
||||
b, err := d.readSize1()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return int64(b), nil
|
||||
|
||||
case code == def.Int8:
|
||||
b, err := d.readSize1()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return int64(int8(b)), nil
|
||||
|
||||
case code == def.Uint16:
|
||||
bs, err := d.readSize2()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
v := binary.BigEndian.Uint16(bs)
|
||||
return int64(v), nil
|
||||
|
||||
case code == def.Int16:
|
||||
bs, err := d.readSize2()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
v := int16(binary.BigEndian.Uint16(bs))
|
||||
return int64(v), nil
|
||||
|
||||
case code == def.Uint32:
|
||||
bs, err := d.readSize4()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
v := binary.BigEndian.Uint32(bs)
|
||||
return int64(v), nil
|
||||
|
||||
case code == def.Int32:
|
||||
bs, err := d.readSize4()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
v := int32(binary.BigEndian.Uint32(bs))
|
||||
return int64(v), nil
|
||||
|
||||
case code == def.Uint64:
|
||||
bs, err := d.readSize8()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return int64(binary.BigEndian.Uint64(bs)), nil
|
||||
|
||||
case code == def.Int64:
|
||||
bs, err := d.readSize8()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return int64(binary.BigEndian.Uint64(bs)), nil
|
||||
|
||||
case code == def.Float32:
|
||||
v, err := d.asFloat32WithCode(code, k)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return int64(v), nil
|
||||
|
||||
case code == def.Float64:
|
||||
v, err := d.asFloat64WithCode(code, k)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return int64(v), nil
|
||||
|
||||
case code == def.Nil:
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
return 0, d.errorTemplate(code, k)
|
||||
}
|
||||
Generated
Vendored
+177
@@ -0,0 +1,177 @@
|
||||
package decoding
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"github.com/shamaton/msgpack/v2/def"
|
||||
)
|
||||
|
||||
func (d *decoder) asInterface(k reflect.Kind) (interface{}, error) {
|
||||
code, err := d.readSize1()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return d.asInterfaceWithCode(code, k)
|
||||
}
|
||||
|
||||
func (d *decoder) asInterfaceWithCode(code byte, k reflect.Kind) (interface{}, error) {
|
||||
switch {
|
||||
case code == def.Nil:
|
||||
return nil, nil
|
||||
|
||||
case code == def.True, code == def.False:
|
||||
v, err := d.asBoolWithCode(code, k)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return v, nil
|
||||
|
||||
case d.isPositiveFixNum(code), code == def.Uint8:
|
||||
v, err := d.asUintWithCode(code, k)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return uint8(v), err
|
||||
case code == def.Uint16:
|
||||
v, err := d.asUintWithCode(code, k)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return uint16(v), err
|
||||
case code == def.Uint32:
|
||||
v, err := d.asUintWithCode(code, k)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return uint32(v), err
|
||||
case code == def.Uint64:
|
||||
v, err := d.asUintWithCode(code, k)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return v, err
|
||||
|
||||
case d.isNegativeFixNum(code), code == def.Int8:
|
||||
v, err := d.asIntWithCode(code, k)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return int8(v), err
|
||||
case code == def.Int16:
|
||||
v, err := d.asIntWithCode(code, k)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return int16(v), err
|
||||
case code == def.Int32:
|
||||
v, err := d.asIntWithCode(code, k)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return int32(v), err
|
||||
case code == def.Int64:
|
||||
v, err := d.asIntWithCode(code, k)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return v, err
|
||||
|
||||
case code == def.Float32:
|
||||
v, err := d.asFloat32WithCode(code, k)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return v, err
|
||||
case code == def.Float64:
|
||||
v, err := d.asFloat64WithCode(code, k)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return v, err
|
||||
|
||||
case d.isFixString(code), code == def.Str8, code == def.Str16, code == def.Str32:
|
||||
v, err := d.asStringWithCode(code, k)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return v, err
|
||||
|
||||
case code == def.Bin8, code == def.Bin16, code == def.Bin32:
|
||||
v, err := d.asBinWithCode(code, k)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return v, err
|
||||
|
||||
case d.isFixSlice(code), code == def.Array16, code == def.Array32:
|
||||
l, err := d.sliceLength(code, k)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
v := make([]interface{}, l)
|
||||
for i := 0; i < l; i++ {
|
||||
vv, err := d.asInterface(k)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
v[i] = vv
|
||||
}
|
||||
return v, nil
|
||||
|
||||
case d.isFixMap(code), code == def.Map16, code == def.Map32:
|
||||
l, err := d.mapLength(code, k)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
v := make(map[interface{}]interface{}, l)
|
||||
for i := 0; i < l; i++ {
|
||||
keyCode, err := d.readSize1()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
if err := d.canSetAsMapKey(keyCode); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
key, err := d.asInterfaceWithCode(keyCode, k)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
value, err := d.asInterface(k)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
v[key] = value
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// ext
|
||||
extInnerType, extData, err := d.readIfExtType(code)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for i := range extCoders {
|
||||
if extCoders[i].IsType(code, extInnerType, len(extData)) {
|
||||
v, err := extCoders[i].ToValue(code, extData, k)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
}
|
||||
return nil, d.errorTemplate(code, k)
|
||||
}
|
||||
|
||||
func (d *decoder) canSetAsMapKey(code byte) error {
|
||||
switch {
|
||||
case d.isFixSlice(code), code == def.Array16, code == def.Array32:
|
||||
return fmt.Errorf("%w. code: %x", def.ErrCanNotSetSliceAsMapKey, code)
|
||||
case d.isFixMap(code), code == def.Map16, code == def.Map32:
|
||||
return fmt.Errorf("%w. code: %x", def.ErrCanNotSetMapAsMapKey, code)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
+698
@@ -0,0 +1,698 @@
|
||||
package decoding
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"reflect"
|
||||
|
||||
"github.com/shamaton/msgpack/v2/def"
|
||||
)
|
||||
|
||||
var (
|
||||
typeMapStringInt = reflect.TypeOf(map[string]int{})
|
||||
typeMapStringInt8 = reflect.TypeOf(map[string]int8{})
|
||||
typeMapStringInt16 = reflect.TypeOf(map[string]int16{})
|
||||
typeMapStringInt32 = reflect.TypeOf(map[string]int32{})
|
||||
typeMapStringInt64 = reflect.TypeOf(map[string]int64{})
|
||||
|
||||
typeMapStringUint = reflect.TypeOf(map[string]uint{})
|
||||
typeMapStringUint8 = reflect.TypeOf(map[string]uint8{})
|
||||
typeMapStringUint16 = reflect.TypeOf(map[string]uint16{})
|
||||
typeMapStringUint32 = reflect.TypeOf(map[string]uint32{})
|
||||
typeMapStringUint64 = reflect.TypeOf(map[string]uint64{})
|
||||
|
||||
typeMapStringFloat32 = reflect.TypeOf(map[string]float32{})
|
||||
typeMapStringFloat64 = reflect.TypeOf(map[string]float64{})
|
||||
|
||||
typeMapStringBool = reflect.TypeOf(map[string]bool{})
|
||||
typeMapStringString = reflect.TypeOf(map[string]string{})
|
||||
|
||||
typeMapIntString = reflect.TypeOf(map[int]string{})
|
||||
typeMapInt8String = reflect.TypeOf(map[int8]string{})
|
||||
typeMapInt16String = reflect.TypeOf(map[int16]string{})
|
||||
typeMapInt32String = reflect.TypeOf(map[int32]string{})
|
||||
typeMapInt64String = reflect.TypeOf(map[int64]string{})
|
||||
typeMapIntBool = reflect.TypeOf(map[int]bool{})
|
||||
typeMapInt8Bool = reflect.TypeOf(map[int8]bool{})
|
||||
typeMapInt16Bool = reflect.TypeOf(map[int16]bool{})
|
||||
typeMapInt32Bool = reflect.TypeOf(map[int32]bool{})
|
||||
typeMapInt64Bool = reflect.TypeOf(map[int64]bool{})
|
||||
|
||||
typeMapUintString = reflect.TypeOf(map[uint]string{})
|
||||
typeMapUint8String = reflect.TypeOf(map[uint8]string{})
|
||||
typeMapUint16String = reflect.TypeOf(map[uint16]string{})
|
||||
typeMapUint32String = reflect.TypeOf(map[uint32]string{})
|
||||
typeMapUint64String = reflect.TypeOf(map[uint64]string{})
|
||||
typeMapUintBool = reflect.TypeOf(map[uint]bool{})
|
||||
typeMapUint8Bool = reflect.TypeOf(map[uint8]bool{})
|
||||
typeMapUint16Bool = reflect.TypeOf(map[uint16]bool{})
|
||||
typeMapUint32Bool = reflect.TypeOf(map[uint32]bool{})
|
||||
typeMapUint64Bool = reflect.TypeOf(map[uint64]bool{})
|
||||
|
||||
typeMapFloat32String = reflect.TypeOf(map[float32]string{})
|
||||
typeMapFloat64String = reflect.TypeOf(map[float64]string{})
|
||||
typeMapFloat32Bool = reflect.TypeOf(map[float32]bool{})
|
||||
typeMapFloat64Bool = reflect.TypeOf(map[float64]bool{})
|
||||
)
|
||||
|
||||
func (d *decoder) isFixMap(v byte) bool {
|
||||
return def.FixMap <= v && v <= def.FixMap+0x0f
|
||||
}
|
||||
|
||||
func (d *decoder) mapLength(code byte, k reflect.Kind) (int, error) {
|
||||
switch {
|
||||
case d.isFixMap(code):
|
||||
return int(code - def.FixMap), nil
|
||||
case code == def.Map16:
|
||||
bs, err := d.readSize2()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return int(binary.BigEndian.Uint16(bs)), nil
|
||||
case code == def.Map32:
|
||||
bs, err := d.readSize4()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return int(binary.BigEndian.Uint32(bs)), nil
|
||||
}
|
||||
|
||||
return 0, d.errorTemplate(code, k)
|
||||
}
|
||||
|
||||
func (d *decoder) asFixedMap(rv reflect.Value, l int) (bool, error) {
|
||||
t := rv.Type()
|
||||
|
||||
keyKind := t.Key().Kind()
|
||||
valueKind := t.Elem().Kind()
|
||||
|
||||
switch t {
|
||||
case typeMapStringInt:
|
||||
m := make(map[string]int, l)
|
||||
for i := 0; i < l; i++ {
|
||||
k, err := d.asString(keyKind)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
v, err := d.asInt(valueKind)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
m[k] = int(v)
|
||||
}
|
||||
rv.Set(reflect.ValueOf(m))
|
||||
return true, nil
|
||||
|
||||
case typeMapStringUint:
|
||||
m := make(map[string]uint, l)
|
||||
for i := 0; i < l; i++ {
|
||||
k, err := d.asString(keyKind)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
v, err := d.asUint(valueKind)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
m[k] = uint(v)
|
||||
}
|
||||
rv.Set(reflect.ValueOf(m))
|
||||
return true, nil
|
||||
|
||||
case typeMapStringFloat32:
|
||||
m := make(map[string]float32, l)
|
||||
for i := 0; i < l; i++ {
|
||||
k, err := d.asString(keyKind)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
v, err := d.asFloat32(valueKind)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
m[k] = v
|
||||
}
|
||||
rv.Set(reflect.ValueOf(m))
|
||||
return true, nil
|
||||
|
||||
case typeMapStringFloat64:
|
||||
m := make(map[string]float64, l)
|
||||
for i := 0; i < l; i++ {
|
||||
k, err := d.asString(keyKind)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
v, err := d.asFloat64(valueKind)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
m[k] = v
|
||||
}
|
||||
rv.Set(reflect.ValueOf(m))
|
||||
return true, nil
|
||||
|
||||
case typeMapStringBool:
|
||||
m := make(map[string]bool, l)
|
||||
for i := 0; i < l; i++ {
|
||||
k, err := d.asString(keyKind)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
v, err := d.asBool(valueKind)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
m[k] = v
|
||||
}
|
||||
rv.Set(reflect.ValueOf(m))
|
||||
return true, nil
|
||||
|
||||
case typeMapStringString:
|
||||
m := make(map[string]string, l)
|
||||
for i := 0; i < l; i++ {
|
||||
k, err := d.asString(keyKind)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
v, err := d.asString(valueKind)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
m[k] = v
|
||||
}
|
||||
rv.Set(reflect.ValueOf(m))
|
||||
return true, nil
|
||||
|
||||
case typeMapStringInt8:
|
||||
m := make(map[string]int8, l)
|
||||
for i := 0; i < l; i++ {
|
||||
k, err := d.asString(keyKind)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
v, err := d.asInt(valueKind)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
m[k] = int8(v)
|
||||
}
|
||||
rv.Set(reflect.ValueOf(m))
|
||||
return true, nil
|
||||
|
||||
case typeMapStringInt16:
|
||||
m := make(map[string]int16, l)
|
||||
for i := 0; i < l; i++ {
|
||||
k, err := d.asString(keyKind)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
v, err := d.asInt(valueKind)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
m[k] = int16(v)
|
||||
}
|
||||
rv.Set(reflect.ValueOf(m))
|
||||
return true, nil
|
||||
|
||||
case typeMapStringInt32:
|
||||
m := make(map[string]int32, l)
|
||||
for i := 0; i < l; i++ {
|
||||
k, err := d.asString(keyKind)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
v, err := d.asInt(valueKind)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
m[k] = int32(v)
|
||||
}
|
||||
rv.Set(reflect.ValueOf(m))
|
||||
return true, nil
|
||||
|
||||
case typeMapStringInt64:
|
||||
m := make(map[string]int64, l)
|
||||
for i := 0; i < l; i++ {
|
||||
k, err := d.asString(keyKind)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
v, err := d.asInt(valueKind)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
m[k] = v
|
||||
}
|
||||
rv.Set(reflect.ValueOf(m))
|
||||
return true, nil
|
||||
|
||||
case typeMapStringUint8:
|
||||
m := make(map[string]uint8, l)
|
||||
for i := 0; i < l; i++ {
|
||||
k, err := d.asString(keyKind)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
v, err := d.asUint(valueKind)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
m[k] = uint8(v)
|
||||
}
|
||||
rv.Set(reflect.ValueOf(m))
|
||||
return true, nil
|
||||
case typeMapStringUint16:
|
||||
m := make(map[string]uint16, l)
|
||||
for i := 0; i < l; i++ {
|
||||
k, err := d.asString(keyKind)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
v, err := d.asUint(valueKind)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
m[k] = uint16(v)
|
||||
}
|
||||
rv.Set(reflect.ValueOf(m))
|
||||
return true, nil
|
||||
|
||||
case typeMapStringUint32:
|
||||
m := make(map[string]uint32, l)
|
||||
for i := 0; i < l; i++ {
|
||||
k, err := d.asString(keyKind)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
v, err := d.asUint(valueKind)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
m[k] = uint32(v)
|
||||
}
|
||||
rv.Set(reflect.ValueOf(m))
|
||||
return true, nil
|
||||
|
||||
case typeMapStringUint64:
|
||||
m := make(map[string]uint64, l)
|
||||
for i := 0; i < l; i++ {
|
||||
k, err := d.asString(keyKind)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
v, err := d.asUint(valueKind)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
m[k] = v
|
||||
}
|
||||
rv.Set(reflect.ValueOf(m))
|
||||
return true, nil
|
||||
|
||||
case typeMapIntString:
|
||||
m := make(map[int]string, l)
|
||||
for i := 0; i < l; i++ {
|
||||
k, err := d.asInt(keyKind)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
v, err := d.asString(valueKind)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
m[int(k)] = v
|
||||
}
|
||||
rv.Set(reflect.ValueOf(m))
|
||||
return true, nil
|
||||
|
||||
case typeMapInt8String:
|
||||
m := make(map[int8]string, l)
|
||||
for i := 0; i < l; i++ {
|
||||
k, err := d.asInt(keyKind)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
v, err := d.asString(valueKind)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
m[int8(k)] = v
|
||||
}
|
||||
rv.Set(reflect.ValueOf(m))
|
||||
return true, nil
|
||||
|
||||
case typeMapInt16String:
|
||||
m := make(map[int16]string, l)
|
||||
for i := 0; i < l; i++ {
|
||||
k, err := d.asInt(keyKind)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
v, err := d.asString(valueKind)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
m[int16(k)] = v
|
||||
}
|
||||
rv.Set(reflect.ValueOf(m))
|
||||
return true, nil
|
||||
|
||||
case typeMapInt32String:
|
||||
m := make(map[int32]string, l)
|
||||
for i := 0; i < l; i++ {
|
||||
k, err := d.asInt(keyKind)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
v, err := d.asString(valueKind)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
m[int32(k)] = v
|
||||
}
|
||||
rv.Set(reflect.ValueOf(m))
|
||||
return true, nil
|
||||
|
||||
case typeMapInt64String:
|
||||
m := make(map[int64]string, l)
|
||||
for i := 0; i < l; i++ {
|
||||
k, err := d.asInt(keyKind)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
v, err := d.asString(valueKind)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
m[k] = v
|
||||
}
|
||||
rv.Set(reflect.ValueOf(m))
|
||||
return true, nil
|
||||
|
||||
case typeMapIntBool:
|
||||
m := make(map[int]bool, l)
|
||||
for i := 0; i < l; i++ {
|
||||
k, err := d.asInt(keyKind)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
v, err := d.asBool(valueKind)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
m[int(k)] = v
|
||||
}
|
||||
rv.Set(reflect.ValueOf(m))
|
||||
return true, nil
|
||||
|
||||
case typeMapInt8Bool:
|
||||
m := make(map[int8]bool, l)
|
||||
for i := 0; i < l; i++ {
|
||||
k, err := d.asInt(keyKind)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
v, err := d.asBool(valueKind)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
m[int8(k)] = v
|
||||
}
|
||||
rv.Set(reflect.ValueOf(m))
|
||||
return true, nil
|
||||
|
||||
case typeMapInt16Bool:
|
||||
m := make(map[int16]bool, l)
|
||||
for i := 0; i < l; i++ {
|
||||
k, err := d.asInt(keyKind)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
v, err := d.asBool(valueKind)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
m[int16(k)] = v
|
||||
}
|
||||
rv.Set(reflect.ValueOf(m))
|
||||
return true, nil
|
||||
|
||||
case typeMapInt32Bool:
|
||||
m := make(map[int32]bool, l)
|
||||
for i := 0; i < l; i++ {
|
||||
k, err := d.asInt(keyKind)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
v, err := d.asBool(valueKind)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
m[int32(k)] = v
|
||||
}
|
||||
rv.Set(reflect.ValueOf(m))
|
||||
return true, nil
|
||||
|
||||
case typeMapInt64Bool:
|
||||
m := make(map[int64]bool, l)
|
||||
for i := 0; i < l; i++ {
|
||||
k, err := d.asInt(keyKind)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
v, err := d.asBool(valueKind)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
m[k] = v
|
||||
}
|
||||
rv.Set(reflect.ValueOf(m))
|
||||
return true, nil
|
||||
|
||||
case typeMapUintString:
|
||||
m := make(map[uint]string, l)
|
||||
for i := 0; i < l; i++ {
|
||||
k, err := d.asUint(keyKind)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
v, err := d.asString(valueKind)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
m[uint(k)] = v
|
||||
}
|
||||
rv.Set(reflect.ValueOf(m))
|
||||
return true, nil
|
||||
|
||||
case typeMapUint8String:
|
||||
m := make(map[uint8]string, l)
|
||||
for i := 0; i < l; i++ {
|
||||
k, err := d.asUint(keyKind)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
v, err := d.asString(valueKind)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
m[uint8(k)] = v
|
||||
}
|
||||
rv.Set(reflect.ValueOf(m))
|
||||
return true, nil
|
||||
|
||||
case typeMapUint16String:
|
||||
m := make(map[uint16]string, l)
|
||||
for i := 0; i < l; i++ {
|
||||
k, err := d.asUint(keyKind)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
v, err := d.asString(valueKind)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
m[uint16(k)] = v
|
||||
}
|
||||
rv.Set(reflect.ValueOf(m))
|
||||
return true, nil
|
||||
|
||||
case typeMapUint32String:
|
||||
m := make(map[uint32]string, l)
|
||||
for i := 0; i < l; i++ {
|
||||
k, err := d.asUint(keyKind)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
v, err := d.asString(valueKind)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
m[uint32(k)] = v
|
||||
}
|
||||
rv.Set(reflect.ValueOf(m))
|
||||
return true, nil
|
||||
|
||||
case typeMapUint64String:
|
||||
m := make(map[uint64]string, l)
|
||||
for i := 0; i < l; i++ {
|
||||
k, err := d.asUint(keyKind)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
v, err := d.asString(valueKind)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
m[k] = v
|
||||
}
|
||||
rv.Set(reflect.ValueOf(m))
|
||||
return true, nil
|
||||
|
||||
case typeMapUintBool:
|
||||
m := make(map[uint]bool, l)
|
||||
for i := 0; i < l; i++ {
|
||||
k, err := d.asUint(keyKind)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
v, err := d.asBool(valueKind)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
m[uint(k)] = v
|
||||
}
|
||||
rv.Set(reflect.ValueOf(m))
|
||||
return true, nil
|
||||
|
||||
case typeMapUint8Bool:
|
||||
m := make(map[uint8]bool, l)
|
||||
for i := 0; i < l; i++ {
|
||||
k, err := d.asUint(keyKind)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
v, err := d.asBool(valueKind)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
m[uint8(k)] = v
|
||||
}
|
||||
rv.Set(reflect.ValueOf(m))
|
||||
return true, nil
|
||||
|
||||
case typeMapUint16Bool:
|
||||
m := make(map[uint16]bool, l)
|
||||
for i := 0; i < l; i++ {
|
||||
k, err := d.asUint(keyKind)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
v, err := d.asBool(valueKind)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
m[uint16(k)] = v
|
||||
}
|
||||
rv.Set(reflect.ValueOf(m))
|
||||
return true, nil
|
||||
|
||||
case typeMapUint32Bool:
|
||||
m := make(map[uint32]bool, l)
|
||||
for i := 0; i < l; i++ {
|
||||
k, err := d.asUint(keyKind)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
v, err := d.asBool(valueKind)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
m[uint32(k)] = v
|
||||
}
|
||||
rv.Set(reflect.ValueOf(m))
|
||||
return true, nil
|
||||
|
||||
case typeMapUint64Bool:
|
||||
m := make(map[uint64]bool, l)
|
||||
for i := 0; i < l; i++ {
|
||||
k, err := d.asUint(keyKind)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
v, err := d.asBool(valueKind)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
m[k] = v
|
||||
}
|
||||
rv.Set(reflect.ValueOf(m))
|
||||
return true, nil
|
||||
|
||||
case typeMapFloat32String:
|
||||
m := make(map[float32]string, l)
|
||||
for i := 0; i < l; i++ {
|
||||
k, err := d.asFloat32(keyKind)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
v, err := d.asString(valueKind)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
m[k] = v
|
||||
}
|
||||
rv.Set(reflect.ValueOf(m))
|
||||
return true, nil
|
||||
|
||||
case typeMapFloat64String:
|
||||
m := make(map[float64]string, l)
|
||||
for i := 0; i < l; i++ {
|
||||
k, err := d.asFloat64(keyKind)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
v, err := d.asString(valueKind)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
m[k] = v
|
||||
}
|
||||
rv.Set(reflect.ValueOf(m))
|
||||
return true, nil
|
||||
|
||||
case typeMapFloat32Bool:
|
||||
m := make(map[float32]bool, l)
|
||||
for i := 0; i < l; i++ {
|
||||
k, err := d.asFloat32(keyKind)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
v, err := d.asBool(valueKind)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
m[k] = v
|
||||
}
|
||||
rv.Set(reflect.ValueOf(m))
|
||||
return true, nil
|
||||
|
||||
case typeMapFloat64Bool:
|
||||
m := make(map[float64]bool, l)
|
||||
for i := 0; i < l; i++ {
|
||||
k, err := d.asFloat64(keyKind)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
v, err := d.asBool(valueKind)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
m[k] = v
|
||||
}
|
||||
rv.Set(reflect.ValueOf(m))
|
||||
return true, nil
|
||||
}
|
||||
|
||||
return false, nil
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package decoding
|
||||
|
||||
import "github.com/shamaton/msgpack/v2/def"
|
||||
|
||||
func (d *decoder) isCodeNil(v byte) bool {
|
||||
return def.Nil == v
|
||||
}
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
package decoding
|
||||
|
||||
func (d *decoder) readSize1() (byte, error) {
|
||||
if _, err := d.r.Read(d.buf.B1); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return d.buf.B1[0], nil
|
||||
}
|
||||
|
||||
func (d *decoder) readSize2() ([]byte, error) {
|
||||
if _, err := d.r.Read(d.buf.B2); err != nil {
|
||||
return emptyBytes, err
|
||||
}
|
||||
return d.buf.B2, nil
|
||||
}
|
||||
|
||||
func (d *decoder) readSize4() ([]byte, error) {
|
||||
if _, err := d.r.Read(d.buf.B4); err != nil {
|
||||
return emptyBytes, err
|
||||
}
|
||||
return d.buf.B4, nil
|
||||
}
|
||||
|
||||
func (d *decoder) readSize8() ([]byte, error) {
|
||||
if _, err := d.r.Read(d.buf.B8); err != nil {
|
||||
return emptyBytes, err
|
||||
}
|
||||
return d.buf.B8, nil
|
||||
}
|
||||
|
||||
func (d *decoder) readSize16() ([]byte, error) {
|
||||
if _, err := d.r.Read(d.buf.B16); err != nil {
|
||||
return emptyBytes, err
|
||||
}
|
||||
return d.buf.B16, nil
|
||||
}
|
||||
|
||||
func (d *decoder) readSizeN(n int) ([]byte, error) {
|
||||
var b []byte
|
||||
if n <= len(d.buf.Data) {
|
||||
b = d.buf.Data[:n]
|
||||
} else {
|
||||
d.buf.Data = append(d.buf.Data, make([]byte, n-len(d.buf.Data))...)
|
||||
b = d.buf.Data
|
||||
}
|
||||
if _, err := d.r.Read(b); err != nil {
|
||||
return emptyBytes, err
|
||||
}
|
||||
return b, nil
|
||||
}
|
||||
+230
@@ -0,0 +1,230 @@
|
||||
package decoding
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"reflect"
|
||||
|
||||
"github.com/shamaton/msgpack/v2/def"
|
||||
)
|
||||
|
||||
var (
|
||||
typeIntSlice = reflect.TypeOf([]int{})
|
||||
typeInt8Slice = reflect.TypeOf([]int8{})
|
||||
typeInt16Slice = reflect.TypeOf([]int16{})
|
||||
typeInt32Slice = reflect.TypeOf([]int32{})
|
||||
typeInt64Slice = reflect.TypeOf([]int64{})
|
||||
|
||||
typeUintSlice = reflect.TypeOf([]uint{})
|
||||
typeUint8Slice = reflect.TypeOf([]uint8{})
|
||||
typeUint16Slice = reflect.TypeOf([]uint16{})
|
||||
typeUint32Slice = reflect.TypeOf([]uint32{})
|
||||
typeUint64Slice = reflect.TypeOf([]uint64{})
|
||||
|
||||
typeFloat32Slice = reflect.TypeOf([]float32{})
|
||||
typeFloat64Slice = reflect.TypeOf([]float64{})
|
||||
|
||||
typeStringSlice = reflect.TypeOf([]string{})
|
||||
|
||||
typeBoolSlice = reflect.TypeOf([]bool{})
|
||||
)
|
||||
|
||||
func (d *decoder) isFixSlice(v byte) bool {
|
||||
return def.FixArray <= v && v <= def.FixArray+0x0f
|
||||
}
|
||||
|
||||
func (d *decoder) sliceLength(code byte, k reflect.Kind) (int, error) {
|
||||
switch {
|
||||
case d.isFixSlice(code):
|
||||
return int(code - def.FixArray), nil
|
||||
case code == def.Array16:
|
||||
bs, err := d.readSize2()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return int(binary.BigEndian.Uint16(bs)), nil
|
||||
case code == def.Array32:
|
||||
bs, err := d.readSize4()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return int(binary.BigEndian.Uint32(bs)), nil
|
||||
}
|
||||
return 0, d.errorTemplate(code, k)
|
||||
}
|
||||
|
||||
func (d *decoder) asFixedSlice(rv reflect.Value, l int) (bool, error) {
|
||||
t := rv.Type()
|
||||
k := t.Elem().Kind()
|
||||
|
||||
switch t {
|
||||
case typeIntSlice:
|
||||
sli := make([]int, l)
|
||||
for i := range sli {
|
||||
v, err := d.asInt(k)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
sli[i] = int(v)
|
||||
}
|
||||
rv.Set(reflect.ValueOf(sli))
|
||||
return true, nil
|
||||
|
||||
case typeUintSlice:
|
||||
sli := make([]uint, l)
|
||||
for i := range sli {
|
||||
v, err := d.asUint(k)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
sli[i] = uint(v)
|
||||
}
|
||||
rv.Set(reflect.ValueOf(sli))
|
||||
return true, nil
|
||||
|
||||
case typeStringSlice:
|
||||
sli := make([]string, l)
|
||||
for i := range sli {
|
||||
v, err := d.asString(k)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
sli[i] = v
|
||||
}
|
||||
rv.Set(reflect.ValueOf(sli))
|
||||
return true, nil
|
||||
|
||||
case typeBoolSlice:
|
||||
sli := make([]bool, l)
|
||||
for i := range sli {
|
||||
v, err := d.asBool(k)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
sli[i] = v
|
||||
}
|
||||
rv.Set(reflect.ValueOf(sli))
|
||||
return true, nil
|
||||
|
||||
case typeFloat32Slice:
|
||||
sli := make([]float32, l)
|
||||
for i := range sli {
|
||||
v, err := d.asFloat32(k)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
sli[i] = v
|
||||
}
|
||||
rv.Set(reflect.ValueOf(sli))
|
||||
return true, nil
|
||||
|
||||
case typeFloat64Slice:
|
||||
sli := make([]float64, l)
|
||||
for i := range sli {
|
||||
v, err := d.asFloat64(k)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
sli[i] = v
|
||||
}
|
||||
rv.Set(reflect.ValueOf(sli))
|
||||
return true, nil
|
||||
|
||||
case typeInt8Slice:
|
||||
sli := make([]int8, l)
|
||||
for i := range sli {
|
||||
v, err := d.asInt(k)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
sli[i] = int8(v)
|
||||
}
|
||||
rv.Set(reflect.ValueOf(sli))
|
||||
return true, nil
|
||||
|
||||
case typeInt16Slice:
|
||||
sli := make([]int16, l)
|
||||
for i := range sli {
|
||||
v, err := d.asInt(k)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
sli[i] = int16(v)
|
||||
}
|
||||
rv.Set(reflect.ValueOf(sli))
|
||||
return true, nil
|
||||
|
||||
case typeInt32Slice:
|
||||
sli := make([]int32, l)
|
||||
for i := range sli {
|
||||
v, err := d.asInt(k)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
sli[i] = int32(v)
|
||||
}
|
||||
rv.Set(reflect.ValueOf(sli))
|
||||
return true, nil
|
||||
|
||||
case typeInt64Slice:
|
||||
sli := make([]int64, l)
|
||||
for i := range sli {
|
||||
v, err := d.asInt(k)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
sli[i] = v
|
||||
}
|
||||
rv.Set(reflect.ValueOf(sli))
|
||||
return true, nil
|
||||
|
||||
case typeUint8Slice:
|
||||
sli := make([]uint8, l)
|
||||
for i := range sli {
|
||||
v, err := d.asUint(k)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
sli[i] = uint8(v)
|
||||
}
|
||||
rv.Set(reflect.ValueOf(sli))
|
||||
return true, nil
|
||||
|
||||
case typeUint16Slice:
|
||||
sli := make([]uint16, l)
|
||||
for i := range sli {
|
||||
v, err := d.asUint(k)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
sli[i] = uint16(v)
|
||||
}
|
||||
rv.Set(reflect.ValueOf(sli))
|
||||
return true, nil
|
||||
|
||||
case typeUint32Slice:
|
||||
sli := make([]uint32, l)
|
||||
for i := range sli {
|
||||
v, err := d.asUint(k)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
sli[i] = uint32(v)
|
||||
}
|
||||
rv.Set(reflect.ValueOf(sli))
|
||||
return true, nil
|
||||
|
||||
case typeUint64Slice:
|
||||
sli := make([]uint64, l)
|
||||
for i := range sli {
|
||||
v, err := d.asUint(k)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
sli[i] = v
|
||||
}
|
||||
rv.Set(reflect.ValueOf(sli))
|
||||
return true, nil
|
||||
}
|
||||
|
||||
return false, nil
|
||||
}
|
||||
+89
@@ -0,0 +1,89 @@
|
||||
package decoding
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"reflect"
|
||||
|
||||
"github.com/shamaton/msgpack/v2/def"
|
||||
)
|
||||
|
||||
var emptyString = ""
|
||||
var emptyBytes = []byte{}
|
||||
|
||||
func (d *decoder) isCodeString(code byte) bool {
|
||||
return d.isFixString(code) || code == def.Str8 || code == def.Str16 || code == def.Str32
|
||||
}
|
||||
|
||||
func (d *decoder) isFixString(v byte) bool {
|
||||
return def.FixStr <= v && v <= def.FixStr+0x1f
|
||||
}
|
||||
|
||||
func (d *decoder) stringByteLength(code byte, k reflect.Kind) (int, error) {
|
||||
if def.FixStr <= code && code <= def.FixStr+0x1f {
|
||||
l := int(code - def.FixStr)
|
||||
return l, nil
|
||||
} else if code == def.Str8 {
|
||||
b, err := d.readSize1()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return int(b), nil
|
||||
} else if code == def.Str16 {
|
||||
b, err := d.readSize2()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return int(binary.BigEndian.Uint16(b)), nil
|
||||
} else if code == def.Str32 {
|
||||
b, err := d.readSize4()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return int(binary.BigEndian.Uint32(b)), nil
|
||||
} else if code == def.Nil {
|
||||
return 0, nil
|
||||
}
|
||||
return 0, d.errorTemplate(code, k)
|
||||
}
|
||||
|
||||
func (d *decoder) asString(k reflect.Kind) (string, error) {
|
||||
code, err := d.readSize1()
|
||||
if err != nil {
|
||||
return emptyString, err
|
||||
}
|
||||
return d.asStringWithCode(code, k)
|
||||
}
|
||||
|
||||
func (d *decoder) asStringWithCode(code byte, k reflect.Kind) (string, error) {
|
||||
bs, err := d.asStringByteWithCode(code, k)
|
||||
if err != nil {
|
||||
return emptyString, err
|
||||
}
|
||||
return string(bs), nil
|
||||
}
|
||||
|
||||
func (d *decoder) asStringByte(k reflect.Kind) ([]byte, error) {
|
||||
code, err := d.readSize1()
|
||||
if err != nil {
|
||||
return emptyBytes, err
|
||||
}
|
||||
return d.asStringByteWithCode(code, k)
|
||||
}
|
||||
|
||||
func (d *decoder) asStringByteWithCode(code byte, k reflect.Kind) ([]byte, error) {
|
||||
l, err := d.stringByteLength(code, k)
|
||||
if err != nil {
|
||||
return emptyBytes, err
|
||||
}
|
||||
|
||||
return d.asStringByteByLength(l, k)
|
||||
}
|
||||
|
||||
func (d *decoder) asStringByteByLength(l int, _ reflect.Kind) ([]byte, error) {
|
||||
if l < 1 {
|
||||
return emptyBytes, nil
|
||||
}
|
||||
|
||||
// avoid common buffer reference
|
||||
return d.copySizeN(l)
|
||||
}
|
||||
+302
@@ -0,0 +1,302 @@
|
||||
package decoding
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"reflect"
|
||||
"sync"
|
||||
|
||||
"github.com/shamaton/msgpack/v2/def"
|
||||
)
|
||||
|
||||
type structCacheTypeMap struct {
|
||||
keys [][]byte
|
||||
indexes []int
|
||||
}
|
||||
|
||||
type structCacheTypeArray struct {
|
||||
m []int
|
||||
}
|
||||
|
||||
// struct cache map
|
||||
var mapSCTM = sync.Map{}
|
||||
var mapSCTA = sync.Map{}
|
||||
|
||||
func (d *decoder) setStruct(code byte, rv reflect.Value, k reflect.Kind) error {
|
||||
if len(extCoders) > 0 {
|
||||
innerType, data, err := d.readIfExtType(code)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if data != nil {
|
||||
for i := range extCoders {
|
||||
if extCoders[i].IsType(code, innerType, len(data)) {
|
||||
v, err := extCoders[i].ToValue(code, data, k)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Validate that the receptacle is of the right value type.
|
||||
if rv.Type() == reflect.TypeOf(v) {
|
||||
rv.Set(reflect.ValueOf(v))
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if d.asArray {
|
||||
return d.setStructFromArray(code, rv, k)
|
||||
}
|
||||
return d.setStructFromMap(code, rv, k)
|
||||
}
|
||||
|
||||
func (d *decoder) setStructFromArray(code byte, rv reflect.Value, k reflect.Kind) error {
|
||||
// get length
|
||||
l, err := d.sliceLength(code, k)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// find or create reference
|
||||
var scta *structCacheTypeArray
|
||||
cache, findCache := mapSCTA.Load(rv.Type())
|
||||
if !findCache {
|
||||
scta = &structCacheTypeArray{}
|
||||
for i := 0; i < rv.NumField(); i++ {
|
||||
if ok, _, _ := d.CheckField(rv.Type().Field(i)); ok {
|
||||
scta.m = append(scta.m, i)
|
||||
}
|
||||
}
|
||||
mapSCTA.Store(rv.Type(), scta)
|
||||
} else {
|
||||
scta = cache.(*structCacheTypeArray)
|
||||
}
|
||||
// set value
|
||||
for i := 0; i < l; i++ {
|
||||
if i < len(scta.m) {
|
||||
err = d.decode(rv.Field(scta.m[i]))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
err = d.jumpOffset()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *decoder) setStructFromMap(code byte, rv reflect.Value, k reflect.Kind) error {
|
||||
// get length
|
||||
l, err := d.mapLength(code, k)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var sctm *structCacheTypeMap
|
||||
cache, cacheFind := mapSCTM.Load(rv.Type())
|
||||
if !cacheFind {
|
||||
sctm = &structCacheTypeMap{}
|
||||
for i := 0; i < rv.NumField(); i++ {
|
||||
if ok, _, name := d.CheckField(rv.Type().Field(i)); ok {
|
||||
sctm.keys = append(sctm.keys, []byte(name))
|
||||
sctm.indexes = append(sctm.indexes, i)
|
||||
}
|
||||
}
|
||||
mapSCTM.Store(rv.Type(), sctm)
|
||||
} else {
|
||||
sctm = cache.(*structCacheTypeMap)
|
||||
}
|
||||
|
||||
for i := 0; i < l; i++ {
|
||||
dataKey, err := d.asStringByte(k)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fieldIndex := -1
|
||||
for keyIndex, keyBytes := range sctm.keys {
|
||||
if len(keyBytes) != len(dataKey) {
|
||||
continue
|
||||
}
|
||||
|
||||
fieldIndex = sctm.indexes[keyIndex]
|
||||
for dataIndex := range dataKey {
|
||||
if dataKey[dataIndex] != keyBytes[dataIndex] {
|
||||
fieldIndex = -1
|
||||
break
|
||||
}
|
||||
}
|
||||
if fieldIndex >= 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if fieldIndex >= 0 {
|
||||
err = d.decode(rv.Field(fieldIndex))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
err = d.jumpOffset()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *decoder) jumpOffset() error {
|
||||
code, err := d.readSize1()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch {
|
||||
case code == def.True, code == def.False, code == def.Nil:
|
||||
// do nothing
|
||||
|
||||
case d.isPositiveFixNum(code) || d.isNegativeFixNum(code):
|
||||
// do nothing
|
||||
case code == def.Uint8, code == def.Int8:
|
||||
_, err = d.readSize1()
|
||||
return err
|
||||
case code == def.Uint16, code == def.Int16:
|
||||
_, err = d.readSize2()
|
||||
return err
|
||||
case code == def.Uint32, code == def.Int32, code == def.Float32:
|
||||
_, err = d.readSize4()
|
||||
return err
|
||||
case code == def.Uint64, code == def.Int64, code == def.Float64:
|
||||
_, err = d.readSize8()
|
||||
return err
|
||||
|
||||
case d.isFixString(code):
|
||||
_, err = d.readSizeN(int(code - def.FixStr))
|
||||
return err
|
||||
case code == def.Str8, code == def.Bin8:
|
||||
b, err := d.readSize1()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = d.readSizeN(int(b))
|
||||
return err
|
||||
case code == def.Str16, code == def.Bin16:
|
||||
bs, err := d.readSize2()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = d.readSizeN(int(binary.BigEndian.Uint16(bs)))
|
||||
return err
|
||||
case code == def.Str32, code == def.Bin32:
|
||||
bs, err := d.readSize4()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = d.readSizeN(int(binary.BigEndian.Uint32(bs)))
|
||||
return err
|
||||
|
||||
case d.isFixSlice(code):
|
||||
l := int(code - def.FixArray)
|
||||
for i := 0; i < l; i++ {
|
||||
if err = d.jumpOffset(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
case code == def.Array16:
|
||||
bs, err := d.readSize2()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
l := int(binary.BigEndian.Uint16(bs))
|
||||
for i := 0; i < l; i++ {
|
||||
if err = d.jumpOffset(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
case code == def.Array32:
|
||||
bs, err := d.readSize4()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
l := int(binary.BigEndian.Uint32(bs))
|
||||
for i := 0; i < l; i++ {
|
||||
if err = d.jumpOffset(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
case d.isFixMap(code):
|
||||
l := int(code - def.FixMap)
|
||||
for i := 0; i < l*2; i++ {
|
||||
if err = d.jumpOffset(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
case code == def.Map16:
|
||||
bs, err := d.readSize2()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
l := int(binary.BigEndian.Uint16(bs))
|
||||
for i := 0; i < l*2; i++ {
|
||||
if err = d.jumpOffset(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
case code == def.Map32:
|
||||
bs, err := d.readSize4()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
l := int(binary.BigEndian.Uint32(bs))
|
||||
for i := 0; i < l*2; i++ {
|
||||
if err = d.jumpOffset(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
case code == def.Fixext1:
|
||||
_, err = d.readSizeN(def.Byte1 + def.Byte1)
|
||||
return err
|
||||
case code == def.Fixext2:
|
||||
_, err = d.readSizeN(def.Byte1 + def.Byte2)
|
||||
return err
|
||||
case code == def.Fixext4:
|
||||
_, err = d.readSizeN(def.Byte1 + def.Byte4)
|
||||
return err
|
||||
case code == def.Fixext8:
|
||||
_, err = d.readSizeN(def.Byte1 + def.Byte8)
|
||||
return err
|
||||
case code == def.Fixext16:
|
||||
_, err = d.readSizeN(def.Byte1 + def.Byte16)
|
||||
return err
|
||||
|
||||
case code == def.Ext8:
|
||||
b, err := d.readSize1()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = d.readSizeN(def.Byte1 + int(b))
|
||||
return err
|
||||
case code == def.Ext16:
|
||||
bs, err := d.readSize2()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = d.readSizeN(def.Byte1 + int(binary.BigEndian.Uint16(bs)))
|
||||
return err
|
||||
case code == def.Ext32:
|
||||
bs, err := d.readSize4()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = d.readSizeN(def.Byte1 + int(binary.BigEndian.Uint32(bs)))
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
+91
@@ -0,0 +1,91 @@
|
||||
package decoding
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"reflect"
|
||||
|
||||
"github.com/shamaton/msgpack/v2/def"
|
||||
)
|
||||
|
||||
func (d *decoder) asUint(k reflect.Kind) (uint64, error) {
|
||||
code, err := d.readSize1()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return d.asUintWithCode(code, k)
|
||||
}
|
||||
|
||||
func (d *decoder) asUintWithCode(code byte, k reflect.Kind) (uint64, error) {
|
||||
switch {
|
||||
case d.isPositiveFixNum(code):
|
||||
return uint64(code), nil
|
||||
|
||||
case d.isNegativeFixNum(code):
|
||||
return uint64(int8(code)), nil
|
||||
|
||||
case code == def.Uint8:
|
||||
b, err := d.readSize1()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return uint64(b), nil
|
||||
|
||||
case code == def.Int8:
|
||||
b, err := d.readSize1()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return uint64(int8(b)), nil
|
||||
|
||||
case code == def.Uint16:
|
||||
bs, err := d.readSize2()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
v := binary.BigEndian.Uint16(bs)
|
||||
return uint64(v), nil
|
||||
|
||||
case code == def.Int16:
|
||||
bs, err := d.readSize2()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
v := int16(binary.BigEndian.Uint16(bs))
|
||||
return uint64(v), nil
|
||||
|
||||
case code == def.Uint32:
|
||||
bs, err := d.readSize4()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
v := binary.BigEndian.Uint32(bs)
|
||||
return uint64(v), nil
|
||||
|
||||
case code == def.Int32:
|
||||
bs, err := d.readSize4()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
v := int32(binary.BigEndian.Uint32(bs))
|
||||
return uint64(v), nil
|
||||
|
||||
case code == def.Uint64:
|
||||
bs, err := d.readSize8()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return binary.BigEndian.Uint64(bs), nil
|
||||
|
||||
case code == def.Int64:
|
||||
bs, err := d.readSize8()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return binary.BigEndian.Uint64(bs), nil
|
||||
|
||||
case code == def.Nil:
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
return 0, d.errorTemplate(code, k)
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
package encoding
|
||||
|
||||
import "github.com/shamaton/msgpack/v2/def"
|
||||
|
||||
func (e *encoder) writeBool(v bool) error {
|
||||
if v {
|
||||
return e.setByte1Int(def.True)
|
||||
}
|
||||
return e.setByte1Int(def.False)
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
package encoding
|
||||
|
||||
import (
|
||||
"math"
|
||||
"reflect"
|
||||
|
||||
"github.com/shamaton/msgpack/v2/def"
|
||||
)
|
||||
|
||||
var typeByte = reflect.TypeOf(byte(0))
|
||||
|
||||
func (e *encoder) isByteSlice(rv reflect.Value) bool {
|
||||
return rv.Type().Elem() == typeByte
|
||||
}
|
||||
|
||||
func (e *encoder) writeByteSliceLength(l int) error {
|
||||
if l <= math.MaxUint8 {
|
||||
if err := e.setByte1Int(def.Bin8); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := e.setByte1Int(l); err != nil {
|
||||
return err
|
||||
}
|
||||
} else if l <= math.MaxUint16 {
|
||||
if err := e.setByte1Int(def.Bin16); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := e.setByte2Int(l); err != nil {
|
||||
return err
|
||||
}
|
||||
} else if uint(l) <= math.MaxUint32 {
|
||||
if err := e.setByte1Int(def.Bin32); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := e.setByte4Int(l); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
package encoding
|
||||
|
||||
import (
|
||||
"math"
|
||||
|
||||
"github.com/shamaton/msgpack/v2/def"
|
||||
)
|
||||
|
||||
func (e *encoder) writeComplex64(v complex64) error {
|
||||
if err := e.setByte1Int(def.Fixext8); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := e.setByte1Int(int(def.ComplexTypeCode())); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := e.setByte4Uint64(uint64(math.Float32bits(real(v)))); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := e.setByte4Uint64(uint64(math.Float32bits(imag(v)))); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *encoder) writeComplex128(v complex128) error {
|
||||
if err := e.setByte1Int(def.Fixext16); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := e.setByte1Int(int(def.ComplexTypeCode())); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := e.setByte8Uint64(math.Float64bits(real(v))); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := e.setByte8Uint64(math.Float64bits(imag(v))); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Generated
Vendored
+195
@@ -0,0 +1,195 @@
|
||||
package encoding
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"reflect"
|
||||
|
||||
"github.com/shamaton/msgpack/v2/def"
|
||||
"github.com/shamaton/msgpack/v2/internal/common"
|
||||
)
|
||||
|
||||
type encoder struct {
|
||||
w io.Writer
|
||||
asArray bool
|
||||
buf *common.Buffer
|
||||
common.Common
|
||||
}
|
||||
|
||||
// Encode writes MessagePack-encoded byte array of v to writer.
|
||||
func Encode(w io.Writer, v any, asArray bool) error {
|
||||
e := encoder{
|
||||
w: w,
|
||||
buf: common.GetBuffer(),
|
||||
asArray: asArray,
|
||||
}
|
||||
|
||||
rv := reflect.ValueOf(v)
|
||||
if rv.Kind() == reflect.Ptr {
|
||||
rv = rv.Elem()
|
||||
if rv.Kind() == reflect.Ptr {
|
||||
rv = rv.Elem()
|
||||
}
|
||||
}
|
||||
|
||||
err := e.create(rv)
|
||||
if err == nil {
|
||||
err = e.buf.Flush(e.w)
|
||||
}
|
||||
common.PutBuffer(e.buf)
|
||||
return err
|
||||
}
|
||||
|
||||
func (e *encoder) create(rv reflect.Value) error {
|
||||
|
||||
switch rv.Kind() {
|
||||
case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
|
||||
v := rv.Uint()
|
||||
return e.writeUint(v)
|
||||
|
||||
case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
|
||||
v := rv.Int()
|
||||
return e.writeInt(v)
|
||||
|
||||
case reflect.Float32:
|
||||
return e.writeFloat32(rv.Float())
|
||||
|
||||
case reflect.Float64:
|
||||
return e.writeFloat64(rv.Float())
|
||||
|
||||
case reflect.Bool:
|
||||
return e.writeBool(rv.Bool())
|
||||
|
||||
case reflect.String:
|
||||
return e.writeString(rv.String())
|
||||
|
||||
case reflect.Complex64:
|
||||
return e.writeComplex64(complex64(rv.Complex()))
|
||||
|
||||
case reflect.Complex128:
|
||||
return e.writeComplex128(rv.Complex())
|
||||
|
||||
case reflect.Slice:
|
||||
if rv.IsNil() {
|
||||
return e.writeNil()
|
||||
}
|
||||
l := rv.Len()
|
||||
// bin format
|
||||
if e.isByteSlice(rv) {
|
||||
if err := e.writeByteSliceLength(l); err != nil {
|
||||
return err
|
||||
}
|
||||
return e.setBytes(rv.Bytes())
|
||||
}
|
||||
|
||||
// format
|
||||
if err := e.writeSliceLength(l); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if find, err := e.writeFixedSlice(rv); err != nil {
|
||||
return err
|
||||
} else if find {
|
||||
return nil
|
||||
}
|
||||
|
||||
// func
|
||||
elem := rv.Type().Elem()
|
||||
var f structWriteFunc
|
||||
if elem.Kind() == reflect.Struct {
|
||||
f = e.getStructWriter(elem)
|
||||
} else {
|
||||
f = e.create
|
||||
}
|
||||
|
||||
// objects
|
||||
for i := 0; i < l; i++ {
|
||||
if err := f(rv.Index(i)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
case reflect.Array:
|
||||
l := rv.Len()
|
||||
// bin format
|
||||
if e.isByteSlice(rv) {
|
||||
if err := e.writeByteSliceLength(l); err != nil {
|
||||
return err
|
||||
}
|
||||
// objects
|
||||
for i := 0; i < l; i++ {
|
||||
if err := e.setByte1Uint64(rv.Index(i).Uint()); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// format
|
||||
if err := e.writeSliceLength(l); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// func
|
||||
elem := rv.Type().Elem()
|
||||
var f structWriteFunc
|
||||
if elem.Kind() == reflect.Struct {
|
||||
f = e.getStructWriter(elem)
|
||||
} else {
|
||||
f = e.create
|
||||
}
|
||||
|
||||
// objects
|
||||
for i := 0; i < l; i++ {
|
||||
if err := f(rv.Index(i)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
case reflect.Map:
|
||||
if rv.IsNil() {
|
||||
return e.writeNil()
|
||||
}
|
||||
|
||||
l := rv.Len()
|
||||
if err := e.writeMapLength(l); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if find, err := e.writeFixedMap(rv); err != nil {
|
||||
return err
|
||||
} else if find {
|
||||
return nil
|
||||
}
|
||||
|
||||
// key-value
|
||||
keys := rv.MapKeys()
|
||||
for _, k := range keys {
|
||||
if err := e.create(k); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := e.create(rv.MapIndex(k)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
case reflect.Struct:
|
||||
return e.writeStruct(rv)
|
||||
|
||||
case reflect.Ptr:
|
||||
if rv.IsNil() {
|
||||
return e.writeNil()
|
||||
}
|
||||
|
||||
return e.create(rv.Elem())
|
||||
|
||||
case reflect.Interface:
|
||||
return e.create(rv.Elem())
|
||||
|
||||
case reflect.Invalid:
|
||||
return e.writeNil()
|
||||
default:
|
||||
return fmt.Errorf("%v is %w type", rv.Kind(), def.ErrUnsupportedType)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
package encoding
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
|
||||
"github.com/shamaton/msgpack/v2/ext"
|
||||
"github.com/shamaton/msgpack/v2/time"
|
||||
)
|
||||
|
||||
var extCoderMap = map[reflect.Type]ext.StreamEncoder{time.StreamEncoder.Type(): time.StreamEncoder}
|
||||
var extCoders = []ext.StreamEncoder{time.StreamEncoder}
|
||||
|
||||
// AddExtEncoder adds encoders for extension types.
|
||||
func AddExtEncoder(f ext.StreamEncoder) {
|
||||
// ignore time
|
||||
if f.Type() == time.Encoder.Type() {
|
||||
return
|
||||
}
|
||||
|
||||
_, ok := extCoderMap[f.Type()]
|
||||
if !ok {
|
||||
extCoderMap[f.Type()] = f
|
||||
updateExtCoders()
|
||||
}
|
||||
}
|
||||
|
||||
// RemoveExtEncoder removes encoders for extension types.
|
||||
func RemoveExtEncoder(f ext.StreamEncoder) {
|
||||
// ignore time
|
||||
if f.Type() == time.Encoder.Type() {
|
||||
return
|
||||
}
|
||||
|
||||
_, ok := extCoderMap[f.Type()]
|
||||
if ok {
|
||||
delete(extCoderMap, f.Type())
|
||||
updateExtCoders()
|
||||
}
|
||||
}
|
||||
|
||||
func updateExtCoders() {
|
||||
extCoders = make([]ext.StreamEncoder, len(extCoderMap))
|
||||
i := 0
|
||||
for k := range extCoderMap {
|
||||
extCoders[i] = extCoderMap[k]
|
||||
i++
|
||||
}
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
package encoding
|
||||
|
||||
import (
|
||||
"math"
|
||||
|
||||
"github.com/shamaton/msgpack/v2/def"
|
||||
)
|
||||
|
||||
func (e *encoder) writeFloat32(v float64) error {
|
||||
if err := e.setByte1Int(def.Float32); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := e.setByte4Uint64(uint64(math.Float32bits(float32(v)))); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *encoder) writeFloat64(v float64) error {
|
||||
if err := e.setByte1Int(def.Float64); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := e.setByte8Uint64(math.Float64bits(v)); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
package encoding
|
||||
|
||||
import (
|
||||
"math"
|
||||
|
||||
"github.com/shamaton/msgpack/v2/def"
|
||||
)
|
||||
|
||||
func (e *encoder) isNegativeFixInt64(v int64) bool {
|
||||
return def.NegativeFixintMin <= v && v <= def.NegativeFixintMax
|
||||
}
|
||||
|
||||
func (e *encoder) writeInt(v int64) error {
|
||||
if v >= 0 {
|
||||
if err := e.writeUint(uint64(v)); err != nil {
|
||||
return err
|
||||
}
|
||||
} else if e.isNegativeFixInt64(v) {
|
||||
if err := e.setByte1Int64(v); err != nil {
|
||||
return err
|
||||
}
|
||||
} else if v >= math.MinInt8 {
|
||||
if err := e.setByte1Int(def.Int8); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := e.setByte1Int64(v); err != nil {
|
||||
return err
|
||||
}
|
||||
} else if v >= math.MinInt16 {
|
||||
if err := e.setByte1Int(def.Int16); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := e.setByte2Int64(v); err != nil {
|
||||
return err
|
||||
}
|
||||
} else if v >= math.MinInt32 {
|
||||
if err := e.setByte1Int(def.Int32); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := e.setByte4Int64(v); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if err := e.setByte1Int(def.Int64); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := e.setByte8Int64(v); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
+433
@@ -0,0 +1,433 @@
|
||||
package encoding
|
||||
|
||||
import (
|
||||
"math"
|
||||
"reflect"
|
||||
|
||||
"github.com/shamaton/msgpack/v2/def"
|
||||
)
|
||||
|
||||
func (e *encoder) writeMapLength(l int) error {
|
||||
|
||||
// format
|
||||
if l <= 0x0f {
|
||||
if err := e.setByte1Int(def.FixMap + l); err != nil {
|
||||
return err
|
||||
}
|
||||
} else if l <= math.MaxUint16 {
|
||||
if err := e.setByte1Int(def.Map16); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := e.setByte2Int(l); err != nil {
|
||||
return err
|
||||
}
|
||||
} else if uint(l) <= math.MaxUint32 {
|
||||
if err := e.setByte1Int(def.Map32); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := e.setByte4Int(l); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *encoder) writeFixedMap(rv reflect.Value) (bool, error) {
|
||||
switch m := rv.Interface().(type) {
|
||||
case map[string]int:
|
||||
for k, v := range m {
|
||||
if err := e.writeString(k); err != nil {
|
||||
return false, err
|
||||
}
|
||||
if err := e.writeInt(int64(v)); err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
|
||||
case map[string]uint:
|
||||
for k, v := range m {
|
||||
if err := e.writeString(k); err != nil {
|
||||
return false, err
|
||||
}
|
||||
if err := e.writeUint(uint64(v)); err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
|
||||
case map[string]float32:
|
||||
for k, v := range m {
|
||||
if err := e.writeString(k); err != nil {
|
||||
return false, err
|
||||
}
|
||||
if err := e.writeFloat32(float64(v)); err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
|
||||
case map[string]float64:
|
||||
for k, v := range m {
|
||||
if err := e.writeString(k); err != nil {
|
||||
return false, err
|
||||
}
|
||||
if err := e.writeFloat64(v); err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
|
||||
case map[string]bool:
|
||||
for k, v := range m {
|
||||
if err := e.writeString(k); err != nil {
|
||||
return false, err
|
||||
}
|
||||
if err := e.writeBool(v); err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
|
||||
case map[string]string:
|
||||
for k, v := range m {
|
||||
if err := e.writeString(k); err != nil {
|
||||
return false, err
|
||||
}
|
||||
if err := e.writeString(v); err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
|
||||
case map[string]int8:
|
||||
for k, v := range m {
|
||||
if err := e.writeString(k); err != nil {
|
||||
return false, err
|
||||
}
|
||||
if err := e.writeInt(int64(v)); err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
case map[string]int16:
|
||||
for k, v := range m {
|
||||
if err := e.writeString(k); err != nil {
|
||||
return false, err
|
||||
}
|
||||
if err := e.writeInt(int64(v)); err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
case map[string]int32:
|
||||
for k, v := range m {
|
||||
if err := e.writeString(k); err != nil {
|
||||
return false, err
|
||||
}
|
||||
if err := e.writeInt(int64(v)); err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
case map[string]int64:
|
||||
for k, v := range m {
|
||||
if err := e.writeString(k); err != nil {
|
||||
return false, err
|
||||
}
|
||||
if err := e.writeInt(int64(v)); err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
|
||||
case map[string]uint8:
|
||||
for k, v := range m {
|
||||
if err := e.writeString(k); err != nil {
|
||||
return false, err
|
||||
}
|
||||
if err := e.writeUint(uint64(v)); err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
case map[string]uint16:
|
||||
for k, v := range m {
|
||||
if err := e.writeString(k); err != nil {
|
||||
return false, err
|
||||
}
|
||||
if err := e.writeUint(uint64(v)); err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
case map[string]uint32:
|
||||
for k, v := range m {
|
||||
if err := e.writeString(k); err != nil {
|
||||
return false, err
|
||||
}
|
||||
if err := e.writeUint(uint64(v)); err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
case map[string]uint64:
|
||||
for k, v := range m {
|
||||
if err := e.writeString(k); err != nil {
|
||||
return false, err
|
||||
}
|
||||
if err := e.writeUint(uint64(v)); err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
|
||||
case map[int]string:
|
||||
for k, v := range m {
|
||||
if err := e.writeInt(int64(k)); err != nil {
|
||||
return false, err
|
||||
}
|
||||
if err := e.writeString(v); err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
case map[int]bool:
|
||||
for k, v := range m {
|
||||
if err := e.writeInt(int64(k)); err != nil {
|
||||
return false, err
|
||||
}
|
||||
if err := e.writeBool(v); err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
|
||||
case map[uint]string:
|
||||
for k, v := range m {
|
||||
if err := e.writeUint(uint64(k)); err != nil {
|
||||
return false, err
|
||||
}
|
||||
if err := e.writeString(v); err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
case map[uint]bool:
|
||||
for k, v := range m {
|
||||
if err := e.writeUint(uint64(k)); err != nil {
|
||||
return false, err
|
||||
}
|
||||
if err := e.writeBool(v); err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
|
||||
case map[float32]string:
|
||||
for k, v := range m {
|
||||
if err := e.writeFloat32(float64(k)); err != nil {
|
||||
return false, err
|
||||
}
|
||||
if err := e.writeString(v); err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
case map[float32]bool:
|
||||
for k, v := range m {
|
||||
if err := e.writeFloat32(float64(k)); err != nil {
|
||||
return false, err
|
||||
}
|
||||
if err := e.writeBool(v); err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
|
||||
case map[float64]string:
|
||||
for k, v := range m {
|
||||
if err := e.writeFloat64(k); err != nil {
|
||||
return false, err
|
||||
}
|
||||
if err := e.writeString(v); err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
case map[float64]bool:
|
||||
for k, v := range m {
|
||||
if err := e.writeFloat64(k); err != nil {
|
||||
return false, err
|
||||
}
|
||||
if err := e.writeBool(v); err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
|
||||
case map[int8]string:
|
||||
for k, v := range m {
|
||||
if err := e.writeInt(int64(k)); err != nil {
|
||||
return false, err
|
||||
}
|
||||
if err := e.writeString(v); err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
case map[int8]bool:
|
||||
for k, v := range m {
|
||||
if err := e.writeInt(int64(k)); err != nil {
|
||||
return false, err
|
||||
}
|
||||
if err := e.writeBool(v); err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
case map[int16]string:
|
||||
for k, v := range m {
|
||||
if err := e.writeInt(int64(k)); err != nil {
|
||||
return false, err
|
||||
}
|
||||
if err := e.writeString(v); err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
case map[int16]bool:
|
||||
for k, v := range m {
|
||||
if err := e.writeInt(int64(k)); err != nil {
|
||||
return false, err
|
||||
}
|
||||
if err := e.writeBool(v); err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
case map[int32]string:
|
||||
for k, v := range m {
|
||||
if err := e.writeInt(int64(k)); err != nil {
|
||||
return false, err
|
||||
}
|
||||
if err := e.writeString(v); err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
case map[int32]bool:
|
||||
for k, v := range m {
|
||||
if err := e.writeInt(int64(k)); err != nil {
|
||||
return false, err
|
||||
}
|
||||
if err := e.writeBool(v); err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
case map[int64]string:
|
||||
for k, v := range m {
|
||||
if err := e.writeInt(k); err != nil {
|
||||
return false, err
|
||||
}
|
||||
if err := e.writeString(v); err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
case map[int64]bool:
|
||||
for k, v := range m {
|
||||
if err := e.writeInt(k); err != nil {
|
||||
return false, err
|
||||
}
|
||||
if err := e.writeBool(v); err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
|
||||
case map[uint8]string:
|
||||
for k, v := range m {
|
||||
if err := e.writeUint(uint64(k)); err != nil {
|
||||
return false, err
|
||||
}
|
||||
if err := e.writeString(v); err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
case map[uint8]bool:
|
||||
for k, v := range m {
|
||||
if err := e.writeUint(uint64(k)); err != nil {
|
||||
return false, err
|
||||
}
|
||||
if err := e.writeBool(v); err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
case map[uint16]string:
|
||||
for k, v := range m {
|
||||
if err := e.writeUint(uint64(k)); err != nil {
|
||||
return false, err
|
||||
}
|
||||
if err := e.writeString(v); err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
case map[uint16]bool:
|
||||
for k, v := range m {
|
||||
if err := e.writeUint(uint64(k)); err != nil {
|
||||
return false, err
|
||||
}
|
||||
if err := e.writeBool(v); err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
case map[uint32]string:
|
||||
for k, v := range m {
|
||||
if err := e.writeUint(uint64(k)); err != nil {
|
||||
return false, err
|
||||
}
|
||||
if err := e.writeString(v); err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
case map[uint32]bool:
|
||||
for k, v := range m {
|
||||
if err := e.writeUint(uint64(k)); err != nil {
|
||||
return false, err
|
||||
}
|
||||
if err := e.writeBool(v); err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
case map[uint64]string:
|
||||
for k, v := range m {
|
||||
if err := e.writeUint(k); err != nil {
|
||||
return false, err
|
||||
}
|
||||
if err := e.writeString(v); err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
case map[uint64]bool:
|
||||
for k, v := range m {
|
||||
if err := e.writeUint(k); err != nil {
|
||||
return false, err
|
||||
}
|
||||
if err := e.writeBool(v); err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package encoding
|
||||
|
||||
import "github.com/shamaton/msgpack/v2/def"
|
||||
|
||||
func (e *encoder) writeNil() error {
|
||||
return e.setByte1Int(def.Nil)
|
||||
}
|
||||
+93
@@ -0,0 +1,93 @@
|
||||
package encoding
|
||||
|
||||
func (e *encoder) setByte1Int64(value int64) error {
|
||||
return e.buf.Write(e.w, byte(value))
|
||||
}
|
||||
|
||||
func (e *encoder) setByte2Int64(value int64) error {
|
||||
return e.buf.Write(e.w,
|
||||
byte(value>>8),
|
||||
byte(value),
|
||||
)
|
||||
}
|
||||
|
||||
func (e *encoder) setByte4Int64(value int64) error {
|
||||
return e.buf.Write(e.w,
|
||||
byte(value>>24),
|
||||
byte(value>>16),
|
||||
byte(value>>8),
|
||||
byte(value),
|
||||
)
|
||||
}
|
||||
|
||||
func (e *encoder) setByte8Int64(value int64) error {
|
||||
return e.buf.Write(e.w,
|
||||
byte(value>>56),
|
||||
byte(value>>48),
|
||||
byte(value>>40),
|
||||
byte(value>>32),
|
||||
byte(value>>24),
|
||||
byte(value>>16),
|
||||
byte(value>>8),
|
||||
byte(value),
|
||||
)
|
||||
}
|
||||
|
||||
func (e *encoder) setByte1Uint64(value uint64) error {
|
||||
return e.buf.Write(e.w, byte(value))
|
||||
}
|
||||
|
||||
func (e *encoder) setByte2Uint64(value uint64) error {
|
||||
return e.buf.Write(e.w,
|
||||
byte(value>>8),
|
||||
byte(value),
|
||||
)
|
||||
}
|
||||
|
||||
func (e *encoder) setByte4Uint64(value uint64) error {
|
||||
return e.buf.Write(e.w,
|
||||
byte(value>>24),
|
||||
byte(value>>16),
|
||||
byte(value>>8),
|
||||
byte(value),
|
||||
)
|
||||
}
|
||||
|
||||
func (e *encoder) setByte8Uint64(value uint64) error {
|
||||
return e.buf.Write(e.w,
|
||||
byte(value>>56),
|
||||
byte(value>>48),
|
||||
byte(value>>40),
|
||||
byte(value>>32),
|
||||
byte(value>>24),
|
||||
byte(value>>16),
|
||||
byte(value>>8),
|
||||
byte(value),
|
||||
)
|
||||
}
|
||||
|
||||
func (e *encoder) setByte1Int(value int) error {
|
||||
return e.buf.Write(e.w,
|
||||
byte(value),
|
||||
)
|
||||
}
|
||||
|
||||
func (e *encoder) setByte2Int(value int) error {
|
||||
return e.buf.Write(e.w,
|
||||
byte(value>>8),
|
||||
byte(value),
|
||||
)
|
||||
}
|
||||
|
||||
func (e *encoder) setByte4Int(value int) error {
|
||||
return e.buf.Write(e.w,
|
||||
byte(value>>24),
|
||||
byte(value>>16),
|
||||
byte(value>>8),
|
||||
byte(value),
|
||||
)
|
||||
}
|
||||
|
||||
func (e *encoder) setBytes(bs []byte) error {
|
||||
return e.buf.Write(e.w, bs...)
|
||||
}
|
||||
+151
@@ -0,0 +1,151 @@
|
||||
package encoding
|
||||
|
||||
import (
|
||||
"math"
|
||||
"reflect"
|
||||
|
||||
"github.com/shamaton/msgpack/v2/def"
|
||||
)
|
||||
|
||||
func (e *encoder) writeSliceLength(l int) error {
|
||||
// format size
|
||||
if l <= 0x0f {
|
||||
if err := e.setByte1Int(def.FixArray + l); err != nil {
|
||||
return err
|
||||
}
|
||||
} else if l <= math.MaxUint16 {
|
||||
if err := e.setByte1Int(def.Array16); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := e.setByte2Int(l); err != nil {
|
||||
return err
|
||||
}
|
||||
} else if uint(l) <= math.MaxUint32 {
|
||||
if err := e.setByte1Int(def.Array32); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := e.setByte4Int(l); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *encoder) writeFixedSlice(rv reflect.Value) (bool, error) {
|
||||
|
||||
switch sli := rv.Interface().(type) {
|
||||
case []int:
|
||||
for _, v := range sli {
|
||||
if err := e.writeInt(int64(v)); err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
|
||||
case []uint:
|
||||
for _, v := range sli {
|
||||
if err := e.writeUint(uint64(v)); err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
|
||||
case []string:
|
||||
for _, v := range sli {
|
||||
if err := e.writeString(v); err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
|
||||
case []float32:
|
||||
for _, v := range sli {
|
||||
if err := e.writeFloat32(float64(v)); err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
|
||||
case []float64:
|
||||
for _, v := range sli {
|
||||
if err := e.writeFloat64(float64(v)); err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
|
||||
case []bool:
|
||||
for _, v := range sli {
|
||||
if err := e.writeBool(v); err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
|
||||
case []int8:
|
||||
for _, v := range sli {
|
||||
if err := e.writeInt(int64(v)); err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
|
||||
case []int16:
|
||||
for _, v := range sli {
|
||||
if err := e.writeInt(int64(v)); err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
|
||||
case []int32:
|
||||
for _, v := range sli {
|
||||
if err := e.writeInt(int64(v)); err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
|
||||
case []int64:
|
||||
for _, v := range sli {
|
||||
if err := e.writeInt(v); err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
|
||||
case []uint8:
|
||||
for _, v := range sli {
|
||||
if err := e.writeUint(uint64(v)); err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
|
||||
case []uint16:
|
||||
for _, v := range sli {
|
||||
if err := e.writeUint(uint64(v)); err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
|
||||
case []uint32:
|
||||
for _, v := range sli {
|
||||
if err := e.writeUint(uint64(v)); err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
|
||||
case []uint64:
|
||||
for _, v := range sli {
|
||||
if err := e.writeUint(v); err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
return false, nil
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
package encoding
|
||||
|
||||
import (
|
||||
"math"
|
||||
"unsafe"
|
||||
|
||||
"github.com/shamaton/msgpack/v2/def"
|
||||
)
|
||||
|
||||
func (e *encoder) writeString(str string) error {
|
||||
// NOTE : unsafe
|
||||
strBytes := *(*[]byte)(unsafe.Pointer(&str))
|
||||
l := len(strBytes)
|
||||
if l < 32 {
|
||||
if err := e.setByte1Int(def.FixStr + l); err != nil {
|
||||
return err
|
||||
}
|
||||
} else if l <= math.MaxUint8 {
|
||||
if err := e.setByte1Int(def.Str8); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := e.setByte1Int(l); err != nil {
|
||||
return err
|
||||
}
|
||||
} else if l <= math.MaxUint16 {
|
||||
if err := e.setByte1Int(def.Str16); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := e.setByte2Int(l); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if err := e.setByte1Int(def.Str32); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := e.setByte4Int(l); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return e.setBytes(strBytes)
|
||||
}
|
||||
+168
@@ -0,0 +1,168 @@
|
||||
package encoding
|
||||
|
||||
import (
|
||||
"math"
|
||||
"reflect"
|
||||
"sync"
|
||||
|
||||
"github.com/shamaton/msgpack/v2/def"
|
||||
"github.com/shamaton/msgpack/v2/ext"
|
||||
"github.com/shamaton/msgpack/v2/internal/common"
|
||||
)
|
||||
|
||||
type structCache struct {
|
||||
indexes []int
|
||||
names []string
|
||||
omits []bool
|
||||
noOmit bool
|
||||
common.Common
|
||||
}
|
||||
|
||||
var cachemap = sync.Map{}
|
||||
|
||||
type structWriteFunc func(rv reflect.Value) error
|
||||
|
||||
func (e *encoder) getStructWriter(typ reflect.Type) structWriteFunc {
|
||||
|
||||
for i := range extCoders {
|
||||
if extCoders[i].Type() == typ {
|
||||
return func(rv reflect.Value) error {
|
||||
w := ext.CreateStreamWriter(e.w, e.buf)
|
||||
return extCoders[i].Write(w, rv)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if e.asArray {
|
||||
return e.writeStructArray
|
||||
}
|
||||
return e.writeStructMap
|
||||
}
|
||||
|
||||
func (e *encoder) writeStruct(rv reflect.Value) error {
|
||||
|
||||
for i := range extCoders {
|
||||
if extCoders[i].Type() == rv.Type() {
|
||||
w := ext.CreateStreamWriter(e.w, e.buf)
|
||||
return extCoders[i].Write(w, rv)
|
||||
}
|
||||
}
|
||||
|
||||
if e.asArray {
|
||||
return e.writeStructArray(rv)
|
||||
}
|
||||
return e.writeStructMap(rv)
|
||||
}
|
||||
|
||||
func (e *encoder) writeStructArray(rv reflect.Value) error {
|
||||
c := e.getStructCache(rv)
|
||||
|
||||
// write format
|
||||
num := len(c.indexes)
|
||||
if num <= 0x0f {
|
||||
if err := e.setByte1Int(def.FixArray + num); err != nil {
|
||||
return err
|
||||
}
|
||||
} else if num <= math.MaxUint16 {
|
||||
if err := e.setByte1Int(def.Array16); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := e.setByte2Int(num); err != nil {
|
||||
return err
|
||||
}
|
||||
} else if uint(num) <= math.MaxUint32 {
|
||||
if err := e.setByte1Int(def.Array32); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := e.setByte4Int(num); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
for i := 0; i < num; i++ {
|
||||
if err := e.create(rv.Field(c.indexes[i])); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *encoder) writeStructMap(rv reflect.Value) error {
|
||||
c := e.getStructCache(rv)
|
||||
|
||||
num := len(c.indexes)
|
||||
l := 0
|
||||
if c.noOmit {
|
||||
l = num
|
||||
} else {
|
||||
for i := 0; i < num; i++ {
|
||||
irv := rv.Field(c.indexes[i])
|
||||
if !c.omits[i] || !irv.IsZero() {
|
||||
l++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// format size
|
||||
if l <= 0x0f {
|
||||
if err := e.setByte1Int(def.FixMap + l); err != nil {
|
||||
return err
|
||||
}
|
||||
} else if l <= math.MaxUint16 {
|
||||
if err := e.setByte1Int(def.Map16); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := e.setByte2Int(l); err != nil {
|
||||
return err
|
||||
}
|
||||
} else if uint(l) <= math.MaxUint32 {
|
||||
if err := e.setByte1Int(def.Map32); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := e.setByte4Int(l); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
for i := 0; i < num; i++ {
|
||||
irv := rv.Field(c.indexes[i])
|
||||
if !c.omits[i] || !irv.IsZero() {
|
||||
if err := e.writeString(c.names[i]); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := e.create(irv); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *encoder) getStructCache(rv reflect.Value) *structCache {
|
||||
t := rv.Type()
|
||||
cache, find := cachemap.Load(t)
|
||||
if find {
|
||||
return cache.(*structCache)
|
||||
}
|
||||
|
||||
num := rv.NumField()
|
||||
c := &structCache{
|
||||
indexes: make([]int, 0, num),
|
||||
names: make([]string, 0, num),
|
||||
omits: make([]bool, 0, num),
|
||||
}
|
||||
omitCount := 0
|
||||
for i := 0; i < num; i++ {
|
||||
if ok, omit, name := e.CheckField(rv.Type().Field(i)); ok {
|
||||
c.indexes = append(c.indexes, i)
|
||||
c.names = append(c.names, name)
|
||||
c.omits = append(c.omits, omit)
|
||||
if omit {
|
||||
omitCount++
|
||||
}
|
||||
}
|
||||
}
|
||||
c.noOmit = omitCount == 0
|
||||
cachemap.Store(t, c)
|
||||
return c
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
package encoding
|
||||
|
||||
import (
|
||||
"math"
|
||||
|
||||
"github.com/shamaton/msgpack/v2/def"
|
||||
)
|
||||
|
||||
func (e *encoder) writeUint(v uint64) error {
|
||||
if v <= math.MaxInt8 {
|
||||
if err := e.setByte1Uint64(v); err != nil {
|
||||
return err
|
||||
}
|
||||
} else if v <= math.MaxUint8 {
|
||||
if err := e.setByte1Int(def.Uint8); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := e.setByte1Uint64(v); err != nil {
|
||||
return err
|
||||
}
|
||||
} else if v <= math.MaxUint16 {
|
||||
if err := e.setByte1Int(def.Uint16); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := e.setByte2Uint64(v); err != nil {
|
||||
return err
|
||||
}
|
||||
} else if v <= math.MaxUint32 {
|
||||
if err := e.setByte1Int(def.Uint32); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := e.setByte4Uint64(v); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if err := e.setByte1Int(def.Uint64); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := e.setByte8Uint64(v); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
+95
@@ -0,0 +1,95 @@
|
||||
package msgpack
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/shamaton/msgpack/v2/def"
|
||||
"github.com/shamaton/msgpack/v2/ext"
|
||||
"github.com/shamaton/msgpack/v2/internal/decoding"
|
||||
"github.com/shamaton/msgpack/v2/internal/encoding"
|
||||
streamdecoding "github.com/shamaton/msgpack/v2/internal/stream/decoding"
|
||||
streamencoding "github.com/shamaton/msgpack/v2/internal/stream/encoding"
|
||||
"github.com/shamaton/msgpack/v2/time"
|
||||
)
|
||||
|
||||
// StructAsArray is encoding option.
|
||||
// If this option sets true, default encoding sets to array-format.
|
||||
var StructAsArray = false
|
||||
|
||||
// Marshal returns the MessagePack-encoded byte array of v.
|
||||
func Marshal(v interface{}) ([]byte, error) {
|
||||
return encoding.Encode(v, StructAsArray)
|
||||
}
|
||||
|
||||
// MarshalWrite writes MessagePack-encoded byte array of v to writer.
|
||||
func MarshalWrite(w io.Writer, v interface{}) error {
|
||||
return streamencoding.Encode(w, v, StructAsArray)
|
||||
}
|
||||
|
||||
// Unmarshal analyzes the MessagePack-encoded data and stores
|
||||
// the result into the pointer of v.
|
||||
func Unmarshal(data []byte, v interface{}) error {
|
||||
return decoding.Decode(data, v, StructAsArray)
|
||||
}
|
||||
|
||||
// UnmarshalRead reads the MessagePack-encoded data from reader and stores
|
||||
// the result into the pointer of v.
|
||||
func UnmarshalRead(r io.Reader, v interface{}) error {
|
||||
return streamdecoding.Decode(r, v, StructAsArray)
|
||||
}
|
||||
|
||||
// AddExtCoder adds encoders for extension types.
|
||||
func AddExtCoder(e ext.Encoder, d ext.Decoder) error {
|
||||
if e.Code() != d.Code() {
|
||||
return fmt.Errorf("code different %d:%d", e.Code(), d.Code())
|
||||
}
|
||||
encoding.AddExtEncoder(e)
|
||||
decoding.AddExtDecoder(d)
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddExtStreamCoder adds stream encoders for extension types.
|
||||
func AddExtStreamCoder(e ext.StreamEncoder, d ext.StreamDecoder) error {
|
||||
if e.Code() != d.Code() {
|
||||
return fmt.Errorf("code different %d:%d", e.Code(), d.Code())
|
||||
}
|
||||
streamencoding.AddExtEncoder(e)
|
||||
streamdecoding.AddExtDecoder(d)
|
||||
return nil
|
||||
}
|
||||
|
||||
// RemoveExtCoder removes encoders for extension types.
|
||||
func RemoveExtCoder(e ext.Encoder, d ext.Decoder) error {
|
||||
if e.Code() != d.Code() {
|
||||
return fmt.Errorf("code different %d:%d", e.Code(), d.Code())
|
||||
}
|
||||
encoding.RemoveExtEncoder(e)
|
||||
decoding.RemoveExtDecoder(d)
|
||||
return nil
|
||||
}
|
||||
|
||||
// RemoveExtStreamCoder removes stream encoders for extension types.
|
||||
func RemoveExtStreamCoder(e ext.StreamEncoder, d ext.StreamDecoder) error {
|
||||
if e.Code() != d.Code() {
|
||||
return fmt.Errorf("code different %d:%d", e.Code(), d.Code())
|
||||
}
|
||||
streamencoding.RemoveExtEncoder(e)
|
||||
streamdecoding.RemoveExtDecoder(d)
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetComplexTypeCode sets def.complexTypeCode
|
||||
func SetComplexTypeCode(code int8) {
|
||||
def.SetComplexTypeCode(code)
|
||||
}
|
||||
|
||||
// SetDecodedTimeAsUTC sets decoded time.Time values to UTC timezone.
|
||||
func SetDecodedTimeAsUTC() {
|
||||
time.SetDecodedAsLocal(false)
|
||||
}
|
||||
|
||||
// SetDecodedTimeAsLocal sets decoded time.Time values to local timezone.
|
||||
func SetDecodedTimeAsLocal() {
|
||||
time.SetDecodedAsLocal(true)
|
||||
}
|
||||
+89
@@ -0,0 +1,89 @@
|
||||
package time
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"time"
|
||||
|
||||
"github.com/shamaton/msgpack/v2/def"
|
||||
"github.com/shamaton/msgpack/v2/ext"
|
||||
)
|
||||
|
||||
var zero = time.Unix(0, 0)
|
||||
|
||||
var Decoder = new(timeDecoder)
|
||||
|
||||
type timeDecoder struct {
|
||||
ext.DecoderCommon
|
||||
}
|
||||
|
||||
var _ ext.Decoder = (*timeDecoder)(nil)
|
||||
|
||||
func (td *timeDecoder) Code() int8 {
|
||||
return def.TimeStamp
|
||||
}
|
||||
|
||||
func (td *timeDecoder) IsType(offset int, d *[]byte) bool {
|
||||
code, offset := td.ReadSize1(offset, d)
|
||||
|
||||
if code == def.Fixext4 {
|
||||
t, _ := td.ReadSize1(offset, d)
|
||||
return int8(t) == td.Code()
|
||||
} else if code == def.Fixext8 {
|
||||
t, _ := td.ReadSize1(offset, d)
|
||||
return int8(t) == td.Code()
|
||||
} else if code == def.Ext8 {
|
||||
l, offset := td.ReadSize1(offset, d)
|
||||
t, _ := td.ReadSize1(offset, d)
|
||||
return l == 12 && int8(t) == td.Code()
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (td *timeDecoder) AsValue(offset int, k reflect.Kind, d *[]byte) (interface{}, int, error) {
|
||||
code, offset := td.ReadSize1(offset, d)
|
||||
|
||||
switch code {
|
||||
case def.Fixext4:
|
||||
_, offset = td.ReadSize1(offset, d)
|
||||
bs, offset := td.ReadSize4(offset, d)
|
||||
v := time.Unix(int64(binary.BigEndian.Uint32(bs)), 0)
|
||||
if decodeAsLocal {
|
||||
return v, offset, nil
|
||||
}
|
||||
return v.UTC(), offset, nil
|
||||
|
||||
case def.Fixext8:
|
||||
_, offset = td.ReadSize1(offset, d)
|
||||
bs, offset := td.ReadSize8(offset, d)
|
||||
data64 := binary.BigEndian.Uint64(bs)
|
||||
nano := int64(data64 >> 34)
|
||||
if nano > 999999999 {
|
||||
return zero, 0, fmt.Errorf("in timestamp 64 formats, nanoseconds must not be larger than 999999999 : %d", nano)
|
||||
}
|
||||
v := time.Unix(int64(data64&0x00000003ffffffff), nano)
|
||||
if decodeAsLocal {
|
||||
return v, offset, nil
|
||||
}
|
||||
return v.UTC(), offset, nil
|
||||
|
||||
case def.Ext8:
|
||||
_, offset = td.ReadSize1(offset, d)
|
||||
_, offset = td.ReadSize1(offset, d)
|
||||
nanobs, offset := td.ReadSize4(offset, d)
|
||||
secbs, offset := td.ReadSize8(offset, d)
|
||||
nano := binary.BigEndian.Uint32(nanobs)
|
||||
if nano > 999999999 {
|
||||
return zero, 0, fmt.Errorf("in timestamp 96 formats, nanoseconds must not be larger than 999999999 : %d", nano)
|
||||
}
|
||||
sec := binary.BigEndian.Uint64(secbs)
|
||||
v := time.Unix(int64(sec), int64(nano))
|
||||
if decodeAsLocal {
|
||||
return v, offset, nil
|
||||
}
|
||||
return v.UTC(), offset, nil
|
||||
}
|
||||
|
||||
return zero, 0, fmt.Errorf("should not reach this line!! code %x decoding %v", code, k)
|
||||
}
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
package time
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"time"
|
||||
|
||||
"github.com/shamaton/msgpack/v2/def"
|
||||
"github.com/shamaton/msgpack/v2/ext"
|
||||
)
|
||||
|
||||
var StreamDecoder = new(timeStreamDecoder)
|
||||
|
||||
type timeStreamDecoder struct{}
|
||||
|
||||
var _ ext.StreamDecoder = (*timeStreamDecoder)(nil)
|
||||
|
||||
func (td *timeStreamDecoder) Code() int8 {
|
||||
return def.TimeStamp
|
||||
}
|
||||
|
||||
func (td *timeStreamDecoder) IsType(code byte, innerType int8, dataLength int) bool {
|
||||
switch code {
|
||||
case def.Fixext4, def.Fixext8:
|
||||
return innerType == td.Code()
|
||||
case def.Ext8:
|
||||
return innerType == td.Code() && dataLength == 12
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (td *timeStreamDecoder) ToValue(code byte, data []byte, k reflect.Kind) (interface{}, error) {
|
||||
switch code {
|
||||
case def.Fixext4:
|
||||
v := time.Unix(int64(binary.BigEndian.Uint32(data)), 0)
|
||||
if decodeAsLocal {
|
||||
return v, nil
|
||||
}
|
||||
return v.UTC(), nil
|
||||
|
||||
case def.Fixext8:
|
||||
data64 := binary.BigEndian.Uint64(data)
|
||||
nano := int64(data64 >> 34)
|
||||
if nano > 999999999 {
|
||||
return zero, fmt.Errorf("in timestamp 64 formats, nanoseconds must not be larger than 999999999 : %d", nano)
|
||||
}
|
||||
v := time.Unix(int64(data64&0x00000003ffffffff), nano)
|
||||
if decodeAsLocal {
|
||||
return v, nil
|
||||
}
|
||||
return v.UTC(), nil
|
||||
|
||||
case def.Ext8:
|
||||
nano := binary.BigEndian.Uint32(data[:4])
|
||||
if nano > 999999999 {
|
||||
return zero, fmt.Errorf("in timestamp 96 formats, nanoseconds must not be larger than 999999999 : %d", nano)
|
||||
}
|
||||
sec := binary.BigEndian.Uint64(data[4:12])
|
||||
v := time.Unix(int64(sec), int64(nano))
|
||||
if decodeAsLocal {
|
||||
return v, nil
|
||||
}
|
||||
return v.UTC(), nil
|
||||
}
|
||||
|
||||
return zero, fmt.Errorf("should not reach this line!! code %x decoding %v", code, k)
|
||||
}
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
package time
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"time"
|
||||
|
||||
"github.com/shamaton/msgpack/v2/def"
|
||||
"github.com/shamaton/msgpack/v2/ext"
|
||||
)
|
||||
|
||||
var Encoder = new(timeEncoder)
|
||||
|
||||
type timeEncoder struct {
|
||||
ext.EncoderCommon
|
||||
}
|
||||
|
||||
var typeOf = reflect.TypeOf(time.Time{})
|
||||
|
||||
func (td *timeEncoder) Code() int8 {
|
||||
return def.TimeStamp
|
||||
}
|
||||
|
||||
func (s *timeEncoder) Type() reflect.Type {
|
||||
return typeOf
|
||||
}
|
||||
|
||||
func (s *timeEncoder) CalcByteSize(value reflect.Value) (int, error) {
|
||||
t := value.Interface().(time.Time)
|
||||
secs := uint64(t.Unix())
|
||||
if secs>>34 == 0 {
|
||||
data := uint64(t.Nanosecond())<<34 | secs
|
||||
if data&0xffffffff00000000 == 0 {
|
||||
return def.Byte1 + def.Byte1 + def.Byte4, nil
|
||||
}
|
||||
return def.Byte1 + def.Byte1 + def.Byte8, nil
|
||||
}
|
||||
|
||||
return def.Byte1 + def.Byte1 + def.Byte1 + def.Byte4 + def.Byte8, nil
|
||||
}
|
||||
|
||||
func (s *timeEncoder) WriteToBytes(value reflect.Value, offset int, bytes *[]byte) int {
|
||||
t := value.Interface().(time.Time)
|
||||
|
||||
secs := uint64(t.Unix())
|
||||
if secs>>34 == 0 {
|
||||
data := uint64(t.Nanosecond())<<34 | secs
|
||||
if data&0xffffffff00000000 == 0 {
|
||||
offset = s.SetByte1Int(def.Fixext4, offset, bytes)
|
||||
offset = s.SetByte1Int(def.TimeStamp, offset, bytes)
|
||||
offset = s.SetByte4Uint64(data, offset, bytes)
|
||||
return offset
|
||||
}
|
||||
|
||||
offset = s.SetByte1Int(def.Fixext8, offset, bytes)
|
||||
offset = s.SetByte1Int(def.TimeStamp, offset, bytes)
|
||||
offset = s.SetByte8Uint64(data, offset, bytes)
|
||||
return offset
|
||||
}
|
||||
|
||||
offset = s.SetByte1Int(def.Ext8, offset, bytes)
|
||||
offset = s.SetByte1Int(12, offset, bytes)
|
||||
offset = s.SetByte1Int(def.TimeStamp, offset, bytes)
|
||||
offset = s.SetByte4Int(t.Nanosecond(), offset, bytes)
|
||||
offset = s.SetByte8Uint64(secs, offset, bytes)
|
||||
return offset
|
||||
}
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
package time
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"time"
|
||||
|
||||
"github.com/shamaton/msgpack/v2/def"
|
||||
"github.com/shamaton/msgpack/v2/ext"
|
||||
)
|
||||
|
||||
var StreamEncoder = new(timeStreamEncoder)
|
||||
|
||||
type timeStreamEncoder struct{}
|
||||
|
||||
var _ ext.StreamEncoder = (*timeStreamEncoder)(nil)
|
||||
|
||||
func (timeStreamEncoder) Code() int8 {
|
||||
return def.TimeStamp
|
||||
}
|
||||
|
||||
func (timeStreamEncoder) Type() reflect.Type {
|
||||
return typeOf
|
||||
}
|
||||
|
||||
func (e timeStreamEncoder) Write(w ext.StreamWriter, value reflect.Value) error {
|
||||
t := value.Interface().(time.Time)
|
||||
|
||||
secs := uint64(t.Unix())
|
||||
if secs>>34 == 0 {
|
||||
data := uint64(t.Nanosecond())<<34 | secs
|
||||
if data&0xffffffff00000000 == 0 {
|
||||
if err := w.WriteByte1Int(def.Fixext4); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := w.WriteByte1Int(def.TimeStamp); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := w.WriteByte4Uint64(data); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := w.WriteByte1Int(def.Fixext8); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := w.WriteByte1Int(def.TimeStamp); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := w.WriteByte8Uint64(data); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := w.WriteByte1Int(def.Ext8); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := w.WriteByte1Int(12); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := w.WriteByte1Int(def.TimeStamp); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := w.WriteByte4Int(t.Nanosecond()); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := w.WriteByte8Uint64(secs); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
package time
|
||||
|
||||
var decodeAsLocal = true
|
||||
|
||||
// SetDecodedAsLocal sets the decoded time to local time.
|
||||
func SetDecodedAsLocal(b bool) {
|
||||
decodeAsLocal = b
|
||||
}
|
||||
Reference in New Issue
Block a user