switch to go vendoring

This commit is contained in:
Michael Barz
2023-04-19 20:24:34 +02:00
parent 632fa05ef9
commit afc6ed1e41
8527 changed files with 3004916 additions and 2 deletions
+19
View File
@@ -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
+28
View File
@@ -0,0 +1,28 @@
language: go
services:
- docker
go:
- "1.9.x"
- "1.10.x"
- "1.11.x"
- "1.12.x"
- "1.13.x"
- "1.14.x"
- "1.15.x"
- tip
before_install:
- go get github.com/axw/gocov/gocov
- go get github.com/mattn/goveralls
- if ! go get code.google.com/p/go.tools/cmd/cover; then go get golang.org/x/tools/cmd/cover; fi
- docker pull i386/golang:1.12-alpine
- docker run -dit --name test i386/golang:1.12-alpine sh
- docker exec test sh -c "apk add --no-cache git"
- docker exec test sh -c "go get github.com/shamaton/msgpack"
- docker exec test sh -c "cd /go/src/github.com/shamaton/msgpack && git checkout `git rev-parse --abbrev-ref HEAD`"
script:
- docker exec test sh -c "cd /go/src/github.com/shamaton/msgpack && go test -v ."
- $GOPATH/bin/goveralls -service=travis-ci
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2018 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.
+62
View File
@@ -0,0 +1,62 @@
# MessagePack for Golang
[![Go Reference](https://pkg.go.dev/badge/github.com/shamaton/msgpack.svg)](https://pkg.go.dev/github.com/shamaton/msgpack)
![test](https://github.com/shamaton/msgpack/workflows/test/badge.svg)
[![Go Report Card](https://goreportcard.com/badge/github.com/shamaton/msgpack)](https://goreportcard.com/report/github.com/shamaton/msgpack)
[![codecov](https://codecov.io/gh/shamaton/msgpack/branch/master/graph/badge.svg?token=9PD2JUK5V3)](https://codecov.io/gh/shamaton/msgpack)
[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fshamaton%2Fmsgpack.svg?type=shield)](https://app.fossa.com/projects/git%2Bgithub.com%2Fshamaton%2Fmsgpack?ref=badge_shield)
## 📣 Notice
If your application serializes only primitive types, array, map and struct, code generation is also recommended.
You can get the fastest performance with [msgpackgen](https://github.com/shamaton/msgpackgen).
## Features
* Supported types : primitive / array / slice / struct / map / interface{} and time.Time
* Renaming fields via `msgpack:"field_name"`
* Omitting fields via `msgpack:"-"`
* Supports extend encoder / decoder
* Can also Encoding / Decoding struct as array
This package requires more than version **1.13**
## 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"
)
func main() {
type Struct struct {
String string
}
v := Struct{String: "msgpack"}
d, err := msgpack.Marshal(v)
if err != nil {
panic(err)
}
r := Struct{}
err = msgpack.Unmarshal(d, &r)
if err != nil {
panic(err)
}
}
```
## Benchmark
This result made from [shamaton/msgpack_bench](https://github.com/shamaton/msgpack_bench)
![msgpack_bench](https://user-images.githubusercontent.com/4637556/128299009-4823e79b-d70b-4d11-8f35-10a4758dfeca.png)
## License
This library is under the MIT License.
+15
View File
@@ -0,0 +1,15 @@
package msgpack
import "github.com/shamaton/msgpack/v2/internal/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)
}
+87
View File
@@ -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
}
+17
View File
@@ -0,0 +1,17 @@
package msgpack
import (
"github.com/shamaton/msgpack/v2/internal/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)
}
+40
View File
@@ -0,0 +1,40 @@
package ext
import (
"reflect"
"github.com/shamaton/msgpack/v2/def"
)
type Decoder interface {
Code() int8
IsType(offset int, d *[]byte) bool
AsValue(offset int, k reflect.Kind, d *[]byte) (interface{}, int, error)
}
type DecoderCommon struct {
}
func (cd *DecoderCommon) ReadSize1(index int, d *[]byte) (byte, int) {
rb := def.Byte1
return (*d)[index], index + rb
}
func (cd *DecoderCommon) ReadSize2(index int, d *[]byte) ([]byte, int) {
rb := def.Byte2
return (*d)[index : index+rb], index + rb
}
func (cd *DecoderCommon) ReadSize4(index int, d *[]byte) ([]byte, int) {
rb := def.Byte4
return (*d)[index : index+rb], index + rb
}
func (cd *DecoderCommon) ReadSize8(index int, d *[]byte) ([]byte, int) {
rb := def.Byte8
return (*d)[index : index+rb], index + rb
}
func (cd *DecoderCommon) ReadSizeN(index, n int, d *[]byte) ([]byte, int) {
return (*d)[index : index+n], index + n
}
+111
View File
@@ -0,0 +1,111 @@
package ext
import (
"reflect"
)
type Encoder interface {
Code() int8
Type() reflect.Type
CalcByteSize(value reflect.Value) (int, error)
WriteToBytes(value reflect.Value, offset int, bytes *[]byte) int
}
type EncoderCommon struct {
}
func (c *EncoderCommon) SetByte1Int64(value int64, offset int, d *[]byte) int {
(*d)[offset] = byte(value)
return offset + 1
}
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
}
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
}
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
}
func (c *EncoderCommon) SetByte1Uint64(value uint64, offset int, d *[]byte) int {
(*d)[offset] = byte(value)
return offset + 1
}
func (c *EncoderCommon) SetByte2Uint64(value uint64, offset int, d *[]byte) int {
(*d)[offset] = byte(value >> 8)
(*d)[offset+1] = byte(value)
return offset + 2
}
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
}
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
}
func (c *EncoderCommon) SetByte1Int(code, offset int, d *[]byte) int {
(*d)[offset] = byte(code)
return offset + 1
}
func (c *EncoderCommon) SetByte2Int(value int, offset int, d *[]byte) int {
(*d)[offset] = byte(value >> 8)
(*d)[offset+1] = byte(value)
return offset + 2
}
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
}
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
}
func (c *EncoderCommon) SetBytes(bs []byte, offset int, d *[]byte) int {
for i := range bs {
(*d)[offset+i] = bs[i]
}
return offset + len(bs)
}
+25
View File
@@ -0,0 +1,25 @@
package common
import "reflect"
// 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) (bool, string) {
// A to Z
if c.isPublic(field.Name) {
if tag := field.Tag.Get("msgpack"); tag == "-" {
return false, ""
} else if len(tag) > 0 {
return true, tag
}
return true, field.Name
}
return false, ""
}
func (c *Common) isPublic(name string) bool {
return 0x41 <= name[0] && name[0] <= 0x5a
}
+55
View File
@@ -0,0 +1,55 @@
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
}
o := offset + int(uint8(l))
return d.data[offset:o], o, nil
case def.Bin16:
bs, offset, err := d.readSize2(offset)
o := offset + int(binary.BigEndian.Uint16(bs))
if err != nil {
return emptyBytes, 0, err
}
return d.data[offset:o], o, nil
case def.Bin32:
bs, offset, err := d.readSize4(offset)
o := offset + int(binary.BigEndian.Uint32(bs))
if err != nil {
return emptyBytes, 0, err
}
return d.data[offset:o], o, 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
}
+20
View File
@@ -0,0 +1,20 @@
package decoding
import (
"reflect"
"github.com/shamaton/msgpack/v2/def"
)
func (d *decoder) asBool(offset int, k reflect.Kind) (bool, int, error) {
code := d.data[offset]
offset++
switch code {
case def.True:
return true, offset, nil
case def.False:
return false, offset, nil
}
return false, 0, d.errorTemplate(code, k)
}
+114
View File
@@ -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, fmt.Errorf("should not reach this line!! code %x decoding %v", 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, fmt.Errorf("should not reach this line!! code %x decoding %v", code, k)
}
+342
View File
@@ -0,0 +1,342 @@
package decoding
import (
"fmt"
"reflect"
"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 fmt.Errorf("data is empty")
}
rv := reflect.ValueOf(v)
if rv.Kind() != reflect.Ptr {
return fmt.Errorf("holder must set pointer value. but got: %t", v)
}
rv = rv.Elem()
last, err := d.decode(rv, 0)
if err != nil {
return err
}
if len(data) != last {
return fmt.Errorf("failed deserialization size=%d, last=%d", 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", rv.Type(), rv.Len(), len(bs))
}
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", rv.Type(), rv.Len(), l)
}
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", rv.Type(), rv.Len(), l)
}
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("type(%v) is unsupported", rv.Kind())
}
return offset, nil
}
func (d *decoder) errorTemplate(code byte, k reflect.Kind) error {
return fmt.Errorf("msgpack : invalid code %x decoding %v", code, k)
}
+102
View File
@@ -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
View File
@@ -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 {
break
}
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 {
break
}
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 {
break
}
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 {
break
}
return float64(v), offset, nil
case code == def.Nil:
offset++
return 0, offset, nil
}
return 0, 0, d.errorTemplate(code, k)
}
+128
View File
@@ -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
View File
@@ -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 d.canSetAsMapKey(o) != 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("can not use slice code for map key/ code: %x", code)
case d.isFixMap(code), code == def.Map16, code == def.Map32:
return fmt.Errorf("can not use map code for map key/ code: %x", code)
}
return nil
}
+750
View File
@@ -0,0 +1,750 @@
package decoding
import (
"encoding/binary"
"errors"
"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 errors.New("data length lacks to create map")
}
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
View File
@@ -0,0 +1,7 @@
package decoding
import "github.com/shamaton/msgpack/v2/def"
func (d *decoder) isCodeNil(v byte) bool {
return def.Nil == v
}
+34
View File
@@ -0,0 +1,34 @@
package decoding
import (
"errors"
"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, errors.New("too short bytes")
}
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, errors.New("too short bytes")
}
return d.data[index : index+n], index + n, nil
}
+258
View File
@@ -0,0 +1,258 @@
package decoding
import (
"encoding/binary"
"errors"
"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 errors.New("data length lacks to create map")
}
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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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 + l, nil
} else if l <= math.MaxUint16 {
return def.Byte2 + l, nil
} else if uint(l) <= math.MaxUint32 {
return def.Byte4 + l, nil
}
// not supported error
return 0, fmt.Errorf("not support this array length : %d", 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
View File
@@ -0,0 +1,31 @@
package encoding
import (
"math"
"github.com/shamaton/msgpack/v2/def"
)
func (e *encoder) calcComplex64() int {
return def.Byte1 + def.Byte8
}
func (e *encoder) calcComplex128() int {
return 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
}
+399
View File
@@ -0,0 +1,399 @@
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("failed serialization size=%d, lastIdx=%d", 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) {
ret := def.Byte1
switch rv.Kind() {
case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
v := rv.Uint()
ret += e.calcUint(v)
case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
v := rv.Int()
ret += e.calcInt(int64(v))
case reflect.Float32:
ret += e.calcFloat32(0)
case reflect.Float64:
ret += e.calcFloat64(0)
case reflect.String:
ret += e.calcString(rv.String())
case reflect.Bool:
// do nothing
case reflect.Complex64:
ret += e.calcComplex64()
case reflect.Complex128:
ret += e.calcComplex128()
case reflect.Slice:
if rv.IsNil() {
return ret, nil
}
l := rv.Len()
// bin format
if e.isByteSlice(rv) {
r, err := e.calcByteSlice(l)
if err != nil {
return 0, err
}
ret += r
return ret, nil
}
// format size
if l <= 0x0f {
// format code only
} else if l <= math.MaxUint16 {
ret += def.Byte2
} else if uint(l) <= math.MaxUint32 {
ret += def.Byte4
} else {
// not supported error
return 0, fmt.Errorf("not support this array length : %d", l)
}
if size, find := e.calcFixedSlice(rv); find {
ret += size
return ret, nil
}
// func
elem := rv.Type().Elem()
var f structCalcFunc
if elem.Kind() == reflect.Struct {
f = e.getStructCalc(elem)
ret += def.Byte1 * l
} else {
f = e.calcSize
}
// objects size
for i := 0; i < l; i++ {
size, err := f(rv.Index(i))
if err != nil {
return 0, err
}
ret += size
}
case reflect.Array:
l := rv.Len()
// bin format
if e.isByteSlice(rv) {
r, err := e.calcByteSlice(l)
if err != nil {
return 0, err
}
ret += r
return ret, nil
}
// format size
if l <= 0x0f {
// format code only
} else if l <= math.MaxUint16 {
ret += def.Byte2
} else if uint(l) <= math.MaxUint32 {
ret += def.Byte4
} else {
// not supported error
return 0, fmt.Errorf("not support this array length : %d", l)
}
// func
elem := rv.Type().Elem()
var f structCalcFunc
if elem.Kind() == reflect.Struct {
f = e.getStructCalc(elem)
ret += def.Byte1 * l
} else {
f = e.calcSize
}
// objects size
for i := 0; i < l; i++ {
size, err := f(rv.Index(i))
if err != nil {
return 0, err
}
ret += size
}
case reflect.Map:
if rv.IsNil() {
return ret, nil
}
l := rv.Len()
// format
if l <= 0x0f {
// do nothing
} else if l <= math.MaxUint16 {
ret += def.Byte2
} else if uint(l) <= math.MaxUint32 {
ret += def.Byte4
} else {
// not supported error
return 0, fmt.Errorf("not support this map length : %d", l)
}
if size, find := e.calcFixedMap(rv); find {
ret += size
return ret, nil
}
if e.mk == nil {
e.mk = map[uintptr][]reflect.Value{}
e.mv = map[uintptr][]reflect.Value{}
}
// key-value
keys := rv.MapKeys()
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
}
ret += keySize + valueSize
mv[i] = value
i++
}
e.mk[rv.Pointer()], e.mv[rv.Pointer()] = keys, mv
case reflect.Struct:
size, err := e.calcStruct(rv)
if err != nil {
return 0, err
}
ret += size
case reflect.Ptr:
if rv.IsNil() {
return ret, nil
}
size, err := e.calcSize(rv.Elem())
if err != nil {
return 0, err
}
ret = size
case reflect.Interface:
size, err := e.calcSize(rv.Elem())
if err != nil {
return 0, err
}
ret = size
case reflect.Invalid:
// do nothing (return nil)
default:
return 0, fmt.Errorf("type(%v) is unsupported", rv.Kind())
}
return ret, nil
}
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)
}
l := rv.Len()
// bin format
if e.isByteSlice(rv) {
offset = e.writeByteSliceLength(l, offset)
offset = e.setBytes(rv.Bytes(), offset)
return offset
}
// format
offset = e.writeSliceLength(l, 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
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
View File
@@ -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
View File
@@ -0,0 +1,27 @@
package encoding
import (
"math"
"github.com/shamaton/msgpack/v2/def"
)
func (e *encoder) calcFloat32(v float64) int {
return def.Byte4
}
func (e *encoder) calcFloat64(v float64) int {
return 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
View File
@@ -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 0
} else if v >= math.MinInt8 {
return def.Byte1
} else if v >= math.MinInt16 {
return def.Byte2
} else if v >= math.MinInt32 {
return def.Byte4
}
return 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
}
+520
View File
@@ -0,0 +1,520 @@
package encoding
import (
"math"
"reflect"
"github.com/shamaton/msgpack/v2/def"
)
func (e *encoder) calcFixedMap(rv reflect.Value) (int, bool) {
size := 0
switch m := rv.Interface().(type) {
case map[string]int:
for k, v := range m {
size += def.Byte1 + e.calcString(k)
size += def.Byte1 + e.calcInt(int64(v))
}
return size, true
case map[string]uint:
for k, v := range m {
size += def.Byte1 + e.calcString(k)
size += def.Byte1 + e.calcUint(uint64(v))
}
return size, true
case map[string]string:
for k, v := range m {
size += def.Byte1 + e.calcString(k)
size += def.Byte1 + e.calcString(v)
}
return size, true
case map[string]float32:
for k := range m {
size += def.Byte1 + e.calcString(k)
size += def.Byte1 + e.calcFloat32(0)
}
return size, true
case map[string]float64:
for k := range m {
size += def.Byte1 + e.calcString(k)
size += def.Byte1 + e.calcFloat64(0)
}
return size, true
case map[string]bool:
for k := range m {
size += def.Byte1 + e.calcString(k)
size += def.Byte1 /*+ e.calcBool()*/
}
return size, true
case map[string]int8:
for k, v := range m {
size += def.Byte1 + e.calcString(k)
size += def.Byte1 + e.calcInt(int64(v))
}
return size, true
case map[string]int16:
for k, v := range m {
size += def.Byte1 + e.calcString(k)
size += def.Byte1 + e.calcInt(int64(v))
}
return size, true
case map[string]int32:
for k, v := range m {
size += def.Byte1 + e.calcString(k)
size += def.Byte1 + e.calcInt(int64(v))
}
return size, true
case map[string]int64:
for k, v := range m {
size += def.Byte1 + e.calcString(k)
size += def.Byte1 + e.calcInt(v)
}
return size, true
case map[string]uint8:
for k, v := range m {
size += def.Byte1 + e.calcString(k)
size += def.Byte1 + e.calcUint(uint64(v))
}
return size, true
case map[string]uint16:
for k, v := range m {
size += def.Byte1 + e.calcString(k)
size += def.Byte1 + e.calcUint(uint64(v))
}
return size, true
case map[string]uint32:
for k, v := range m {
size += def.Byte1 + e.calcString(k)
size += def.Byte1 + e.calcUint(uint64(v))
}
return size, true
case map[string]uint64:
for k, v := range m {
size += def.Byte1 + e.calcString(k)
size += def.Byte1 + e.calcUint(v)
}
return size, true
case map[int]string:
for k, v := range m {
size += def.Byte1 + e.calcInt(int64(k))
size += def.Byte1 + e.calcString(v)
}
return size, true
case map[int]bool:
for k := range m {
size += def.Byte1 + e.calcInt(int64(k))
size += def.Byte1 /* + e.calcBool()*/
}
return size, true
case map[uint]string:
for k, v := range m {
size += def.Byte1 + e.calcUint(uint64(k))
size += def.Byte1 + e.calcString(v)
}
return size, true
case map[uint]bool:
for k := range m {
size += def.Byte1 + e.calcUint(uint64(k))
size += def.Byte1 /* + e.calcBool()*/
}
return size, true
case map[float32]string:
for k, v := range m {
size += def.Byte1 + e.calcFloat32(float64(k))
size += def.Byte1 + e.calcString(v)
}
return size, true
case map[float32]bool:
for k := range m {
size += def.Byte1 + e.calcFloat32(float64(k))
size += def.Byte1 /* + e.calcBool()*/
}
return size, true
case map[float64]string:
for k, v := range m {
size += def.Byte1 + e.calcFloat64(k)
size += def.Byte1 + e.calcString(v)
}
return size, true
case map[float64]bool:
for k := range m {
size += def.Byte1 + e.calcFloat64(k)
size += def.Byte1 /* + e.calcBool()*/
}
return size, true
case map[int8]string:
for k, v := range m {
size += def.Byte1 + e.calcInt(int64(k))
size += def.Byte1 + e.calcString(v)
}
return size, true
case map[int8]bool:
for k := range m {
size += def.Byte1 + e.calcInt(int64(k))
size += def.Byte1 /* + e.calcBool()*/
}
return size, true
case map[int16]string:
for k, v := range m {
size += def.Byte1 + e.calcInt(int64(k))
size += def.Byte1 + e.calcString(v)
}
return size, true
case map[int16]bool:
for k := range m {
size += def.Byte1 + e.calcInt(int64(k))
size += def.Byte1 /* + e.calcBool()*/
}
return size, true
case map[int32]string:
for k, v := range m {
size += def.Byte1 + e.calcInt(int64(k))
size += def.Byte1 + e.calcString(v)
}
return size, true
case map[int32]bool:
for k := range m {
size += def.Byte1 + e.calcInt(int64(k))
size += def.Byte1 /* + e.calcBool()*/
}
return size, true
case map[int64]string:
for k, v := range m {
size += def.Byte1 + e.calcInt(k)
size += def.Byte1 + e.calcString(v)
}
return size, true
case map[int64]bool:
for k := range m {
size += def.Byte1 + e.calcInt(k)
size += def.Byte1 /* + e.calcBool()*/
}
return size, true
case map[uint8]string:
for k, v := range m {
size += def.Byte1 + e.calcUint(uint64(k))
size += def.Byte1 + e.calcString(v)
}
return size, true
case map[uint8]bool:
for k := range m {
size += def.Byte1 + e.calcUint(uint64(k))
size += def.Byte1 /* + e.calcBool()*/
}
return size, true
case map[uint16]string:
for k, v := range m {
size += def.Byte1 + e.calcUint(uint64(k))
size += def.Byte1 + e.calcString(v)
}
return size, true
case map[uint16]bool:
for k := range m {
size += def.Byte1 + e.calcUint(uint64(k))
size += def.Byte1 /* + e.calcBool()*/
}
return size, true
case map[uint32]string:
for k, v := range m {
size += def.Byte1 + e.calcUint(uint64(k))
size += def.Byte1 + e.calcString(v)
}
return size, true
case map[uint32]bool:
for k := range m {
size += def.Byte1 + e.calcUint(uint64(k))
size += def.Byte1 /* + e.calcBool()*/
}
return size, true
case map[uint64]string:
for k, v := range m {
size += def.Byte1 + e.calcUint(k)
size += def.Byte1 + e.calcString(v)
}
return size, true
case map[uint64]bool:
for k := range m {
size += def.Byte1 + e.calcUint(k)
size += def.Byte1 /* + e.calcBool()*/
}
return size, true
}
return size, 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
View File
@@ -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
View File
@@ -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)
}
+203
View File
@@ -0,0 +1,203 @@
package encoding
import (
"math"
"reflect"
"github.com/shamaton/msgpack/v2/def"
)
func (e *encoder) calcFixedSlice(rv reflect.Value) (int, bool) {
size := 0
switch sli := rv.Interface().(type) {
case []int:
for _, v := range sli {
size += def.Byte1 + e.calcInt(int64(v))
}
return size, true
case []uint:
for _, v := range sli {
size += def.Byte1 + e.calcUint(uint64(v))
}
return size, true
case []string:
for _, v := range sli {
size += def.Byte1 + e.calcString(v)
}
return size, true
case []float32:
for _, v := range sli {
size += def.Byte1 + e.calcFloat32(float64(v))
}
return size, true
case []float64:
for _, v := range sli {
size += def.Byte1 + e.calcFloat64(v)
}
return size, true
case []bool:
size += def.Byte1 * len(sli)
return size, true
case []int8:
for _, v := range sli {
size += def.Byte1 + e.calcInt(int64(v))
}
return size, true
case []int16:
for _, v := range sli {
size += def.Byte1 + e.calcInt(int64(v))
}
return size, true
case []int32:
for _, v := range sli {
size += def.Byte1 + e.calcInt(int64(v))
}
return size, true
case []int64:
for _, v := range sli {
size += def.Byte1 + e.calcInt(v)
}
return size, true
case []uint8:
for _, v := range sli {
size += def.Byte1 + e.calcUint(uint64(v))
}
return size, true
case []uint16:
for _, v := range sli {
size += def.Byte1 + e.calcUint(uint64(v))
}
return size, true
case []uint32:
for _, v := range sli {
size += def.Byte1 + e.calcUint(uint64(v))
}
return size, true
case []uint64:
for _, v := range sli {
size += def.Byte1 + e.calcUint(v)
}
return size, true
}
return size, 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:
for _, v := range sli {
offset = e.writeInt(int64(v), offset)
}
return offset, true
case []uint:
for _, v := range sli {
offset = e.writeUint(uint64(v), offset)
}
return offset, true
case []string:
for _, v := range sli {
offset = e.writeString(v, offset)
}
return offset, true
case []float32:
for _, v := range sli {
offset = e.writeFloat32(float64(v), offset)
}
return offset, true
case []float64:
for _, v := range sli {
offset = e.writeFloat64(float64(v), offset)
}
return offset, true
case []bool:
for _, v := range sli {
offset = e.writeBool(v, offset)
}
return offset, true
case []int8:
for _, v := range sli {
offset = e.writeInt(int64(v), offset)
}
return offset, true
case []int16:
for _, v := range sli {
offset = e.writeInt(int64(v), offset)
}
return offset, true
case []int32:
for _, v := range sli {
offset = e.writeInt(int64(v), offset)
}
return offset, true
case []int64:
for _, v := range sli {
offset = e.writeInt(v, offset)
}
return offset, true
case []uint8:
for _, v := range sli {
offset = e.writeUint(uint64(v), offset)
}
return offset, true
case []uint16:
for _, v := range sli {
offset = e.writeUint(uint64(v), offset)
}
return offset, true
case []uint32:
for _, v := range sli {
offset = e.writeUint(uint64(v), offset)
}
return offset, true
case []uint64:
for _, v := range sli {
offset = e.writeUint(v, offset)
}
return offset, true
}
return offset, false
}
+43
View File
@@ -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 l
} else if l <= math.MaxUint8 {
return def.Byte1 + l
} else if l <= math.MaxUint16 {
return def.Byte2 + l
}
return 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
}
+230
View File
@@ -0,0 +1,230 @@
package encoding
import (
"fmt"
"math"
"reflect"
"sync"
"github.com/shamaton/msgpack/v2/def"
"github.com/shamaton/msgpack/v2/internal/common"
)
type structCache struct {
indexes []int
names []string
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 {
c = &structCache{}
for i := 0; i < rv.NumField(); i++ {
field := t.Field(i)
if ok, 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)
}
}
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
l := len(c.indexes)
if l <= 0x0f {
// format code only
} else if l <= math.MaxUint16 {
ret += def.Byte2
} else if uint(l) <= math.MaxUint32 {
ret += def.Byte4
} else {
// not supported error
return 0, fmt.Errorf("not support this array length : %d", l)
}
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
if !find {
c = &structCache{}
for i := 0; i < rv.NumField(); i++ {
if ok, name := e.CheckField(rv.Type().Field(i)); ok {
keySize := def.Byte1 + e.calcString(name)
valueSize, err := e.calcSize(rv.Field(i))
if err != nil {
return 0, err
}
ret += keySize + valueSize
c.indexes = append(c.indexes, i)
c.names = append(c.names, name)
}
}
cachemap.Store(t, c)
} else {
c = cache.(*structCache)
for i := 0; i < len(c.indexes); i++ {
keySize := def.Byte1 + e.calcString(c.names[i])
valueSize, err := e.calcSize(rv.Field(c.indexes[i]))
if err != nil {
return 0, err
}
ret += keySize + valueSize
}
}
// format size
l := len(c.indexes)
if l <= 0x0f {
// format code only
} else if l <= math.MaxUint16 {
ret += def.Byte2
} else if uint(l) <= math.MaxUint32 {
ret += def.Byte4
} else {
// not supported error
return 0, fmt.Errorf("not support this array length : %d", l)
}
return ret, 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)
if num <= 0x0f {
offset = e.setByte1Int(def.FixMap+num, offset)
} else if num <= math.MaxUint16 {
offset = e.setByte1Int(def.Map16, offset)
offset = e.setByte2Int(num, offset)
} else if uint(num) <= math.MaxUint32 {
offset = e.setByte1Int(def.Map32, offset)
offset = e.setByte4Int(num, offset)
}
for i := 0; i < num; i++ {
offset = e.writeString(c.names[i], offset)
offset = e.create(rv.Field(c.indexes[i]), offset)
}
return offset
}
+40
View File
@@ -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 0
} else if v <= math.MaxUint8 {
return def.Byte1
} else if v <= math.MaxUint16 {
return def.Byte2
} else if v <= math.MaxUint32 {
return def.Byte4
}
return 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
}
+50
View File
@@ -0,0 +1,50 @@
package msgpack
import (
"fmt"
"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"
)
// 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)
}
// 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)
}
// 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
}
// 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
}
// SetComplexTypeCode sets def.complexTypeCode
func SetComplexTypeCode(code int8) {
def.SetComplexTypeCode(code)
}
+75
View File
@@ -0,0 +1,75 @@
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
}
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)
return time.Unix(int64(binary.BigEndian.Uint32(bs)), 0), 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)
}
return time.Unix(int64(data64&0x00000003ffffffff), nano), 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)
return time.Unix(int64(sec), int64(nano)), offset, nil
}
return zero, 0, fmt.Errorf("should not reach this line!! code %x decoding %v", code, k)
}
+66
View File
@@ -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.Byte4, nil
}
return def.Byte1 + def.Byte8, nil
}
return 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
}