build(deps): bump github.com/shamaton/msgpack/v2 from 2.1.1 to 2.2.0

Bumps [github.com/shamaton/msgpack/v2](https://github.com/shamaton/msgpack) from 2.1.1 to 2.2.0.
- [Release notes](https://github.com/shamaton/msgpack/releases)
- [Commits](https://github.com/shamaton/msgpack/compare/v2.1.1...v2.2.0)

---
updated-dependencies:
- dependency-name: github.com/shamaton/msgpack/v2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
This commit is contained in:
dependabot[bot]
2024-03-20 06:32:46 +00:00
committed by Ralf Haferkamp
parent 09fad45811
commit c2c740592d
43 changed files with 4306 additions and 14 deletions

2
go.mod
View File

@@ -78,7 +78,7 @@ require (
github.com/riandyrn/otelchi v0.5.1
github.com/rogpeppe/go-internal v1.12.0
github.com/rs/zerolog v1.32.0
github.com/shamaton/msgpack/v2 v2.1.1
github.com/shamaton/msgpack/v2 v2.2.0
github.com/sirupsen/logrus v1.9.3
github.com/spf13/afero v1.11.0
github.com/spf13/cobra v1.8.0

4
go.sum
View File

@@ -1928,8 +1928,8 @@ github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NF
github.com/sethgrid/pester v1.2.0/go.mod h1:hEUINb4RqvDxtoCaU0BNT/HV4ig5kfgOasrf1xcvr0A=
github.com/sethvargo/go-password v0.2.0 h1:BTDl4CC/gjf/axHMaDQtw507ogrXLci6XRiLc7i/UHI=
github.com/sethvargo/go-password v0.2.0/go.mod h1:Ym4Mr9JXLBycr02MFuVQ/0JHidNetSgbzutTr3zsYXE=
github.com/shamaton/msgpack/v2 v2.1.1 h1:gAMxOtVJz93R0EwewwUc8tx30n34aV6BzJuwHE8ogAk=
github.com/shamaton/msgpack/v2 v2.1.1/go.mod h1:aTUEmh31ziGX1Ml7wMPLVY0f4vT3CRsCvZRoSCs+VGg=
github.com/shamaton/msgpack/v2 v2.2.0 h1:IP1m01pHwCrMa6ZccP9B3bqxEMKMSmMVAVKk54g3L/Y=
github.com/shamaton/msgpack/v2 v2.2.0/go.mod h1:6khjYnkx73f7VQU7wjcFS9DFjs+59naVWJv1TB7qdOI=
github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749 h1:bUGsEnyNbVPw06Bs80sCeARAlK8lhwqGyi6UT8ymuGk=
github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=

View File

@@ -1,6 +1,6 @@
MIT License
Copyright (c) 2018 Masayuki Shamoto
Copyright (c) 2024 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

View File

@@ -17,8 +17,6 @@ You can get the fastest performance with [msgpackgen](https://github.com/shamato
* 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**.
@@ -32,12 +30,15 @@ package main
import (
"github.com/shamaton/msgpack/v2"
"net/http"
)
type Struct struct {
String string
}
// simple
func main() {
type Struct struct {
String string
}
v := Struct{String: "msgpack"}
d, err := msgpack.Marshal(v)
@@ -45,11 +46,21 @@ func main() {
panic(err)
}
r := Struct{}
err = msgpack.Unmarshal(d, &r)
if err != nil {
if err = msgpack.Unmarshal(d, &r); err != nil {
panic(err)
}
}
// streaming
func handle(w http.ResponseWriter, r *http.Request) {
var body Struct
if err := msgpack.UnmarshalRead(r, &body); err != nil {
panic(err)
}
if err := msgpack.MarshalWrite(w, body); err != nil {
panic(err)
}
}
```
## Benchmark

View File

@@ -1,6 +1,11 @@
package msgpack
import "github.com/shamaton/msgpack/v2/internal/decoding"
import (
"io"
"github.com/shamaton/msgpack/v2/internal/decoding"
streamdecoding "github.com/shamaton/msgpack/v2/internal/stream/decoding"
)
// UnmarshalAsMap decodes data that is encoded as map format.
// This is the same thing that StructAsArray sets false.
@@ -13,3 +18,15 @@ func UnmarshalAsMap(data []byte, v interface{}) error {
func UnmarshalAsArray(data []byte, v interface{}) error {
return decoding.Decode(data, v, true)
}
// UnmarshalReadAsMap decodes from stream. stream data expects map format.
// This is the same thing that StructAsArray sets false.
func UnmarshalReadAsMap(r io.Reader, v interface{}) error {
return streamdecoding.Decode(r, v, false)
}
// UnmarshalReadAsArray decodes from stream. stream data expects array format.
// This is the same thing that StructAsArray sets true.
func UnmarshalReadAsArray(r io.Reader, v interface{}) error {
return streamdecoding.Decode(r, v, true)
}

View File

@@ -1,7 +1,10 @@
package msgpack
import (
"io"
"github.com/shamaton/msgpack/v2/internal/encoding"
streamencoding "github.com/shamaton/msgpack/v2/internal/stream/encoding"
)
// MarshalAsMap encodes data as map format.
@@ -15,3 +18,15 @@ func MarshalAsMap(v interface{}) ([]byte, error) {
func MarshalAsArray(v interface{}) ([]byte, error) {
return encoding.Encode(v, true)
}
// MarshalWriteAsMap writes map format encoded data to writer.
// This is the same thing that StructAsArray sets false.
func MarshalWriteAsMap(w io.Writer, v interface{}) error {
return streamencoding.Encode(w, v, false)
}
// MarshalWriteAsArray writes array format encoded data to writer.
// This is the same thing that StructAsArray sets true.
func MarshalWriteAsArray(w io.Writer, v interface{}) error {
return streamencoding.Encode(w, v, true)
}

View File

@@ -0,0 +1,60 @@
package ext
import (
"github.com/shamaton/msgpack/v2/internal/common"
"io"
"reflect"
)
var emptyBytes []byte
type StreamDecoder interface {
Code() int8
IsType(code byte, innerType int8, dataLength int) bool
ToValue(code byte, data []byte, k reflect.Kind) (any, error)
}
type DecoderStreamCommon struct {
}
func (d *DecoderStreamCommon) ReadSize1(r io.Reader, buf *common.Buffer) (byte, error) {
if _, err := r.Read(buf.B1); err != nil {
return 0, err
}
return buf.B1[0], nil
}
func (d *DecoderStreamCommon) ReadSize2(r io.Reader, buf *common.Buffer) ([]byte, error) {
if _, err := r.Read(buf.B2); err != nil {
return emptyBytes, err
}
return buf.B2, nil
}
func (d *DecoderStreamCommon) ReadSize4(r io.Reader, buf *common.Buffer) ([]byte, error) {
if _, err := r.Read(buf.B4); err != nil {
return emptyBytes, err
}
return buf.B4, nil
}
func (d *DecoderStreamCommon) ReadSize8(r io.Reader, buf *common.Buffer) ([]byte, error) {
if _, err := r.Read(buf.B8); err != nil {
return emptyBytes, err
}
return buf.B8, nil
}
func (d *DecoderStreamCommon) ReadSizeN(r io.Reader, buf *common.Buffer, n int) ([]byte, error) {
var b []byte
if len(buf.Data) <= n {
b = buf.Data[:n]
} else {
buf.Data = append(buf.Data, make([]byte, n-len(buf.Data))...)
b = buf.Data
}
if _, err := r.Read(b); err != nil {
return emptyBytes, err
}
return b, nil
}

View File

@@ -0,0 +1,120 @@
package ext
import (
"github.com/shamaton/msgpack/v2/internal/common"
"io"
"reflect"
)
type StreamEncoder interface {
Code() int8
Type() reflect.Type
Write(w io.Writer, value reflect.Value, buf *common.Buffer) error
}
type StreamEncoderCommon struct{}
func (c *StreamEncoderCommon) WriteByte1Int64(w io.Writer, value int64, buf *common.Buffer) error {
return buf.Write(w,
byte(value),
)
}
func (c *StreamEncoderCommon) WriteByte2Int64(w io.Writer, value int64, buf *common.Buffer) error {
return buf.Write(w,
byte(value>>8),
byte(value),
)
}
func (c *StreamEncoderCommon) WriteByte4Int64(w io.Writer, value int64, buf *common.Buffer) error {
return buf.Write(w,
byte(value>>24),
byte(value>>16),
byte(value>>8),
byte(value),
)
}
func (c *StreamEncoderCommon) WriteByte8Int64(w io.Writer, value int64, buf *common.Buffer) error {
return buf.Write(w,
byte(value>>56),
byte(value>>48),
byte(value>>40),
byte(value>>32),
byte(value>>24),
byte(value>>16),
byte(value>>8),
byte(value),
)
}
func (c *StreamEncoderCommon) WriteByte1Uint64(w io.Writer, value uint64, buf *common.Buffer) error {
return buf.Write(w,
byte(value),
)
}
func (c *StreamEncoderCommon) WriteByte2Uint64(w io.Writer, value uint64, buf *common.Buffer) error {
return buf.Write(w,
byte(value>>8),
byte(value),
)
}
func (c *StreamEncoderCommon) WriteByte4Uint64(w io.Writer, value uint64, buf *common.Buffer) error {
return buf.Write(w,
byte(value>>24),
byte(value>>16),
byte(value>>8),
byte(value),
)
}
func (c *StreamEncoderCommon) WriteByte8Uint64(w io.Writer, value uint64, buf *common.Buffer) error {
return buf.Write(w,
byte(value>>56),
byte(value>>48),
byte(value>>40),
byte(value>>32),
byte(value>>24),
byte(value>>16),
byte(value>>8),
byte(value),
)
}
func (c *StreamEncoderCommon) WriteByte1Int(w io.Writer, value int, buf *common.Buffer) error {
return buf.Write(w,
byte(value),
)
}
func (c *StreamEncoderCommon) WriteByte2Int(w io.Writer, value int, buf *common.Buffer) error {
return buf.Write(w,
byte(value>>8),
byte(value),
)
}
func (c *StreamEncoderCommon) WriteByte4Int(w io.Writer, value int, buf *common.Buffer) error {
return buf.Write(w,
byte(value>>24),
byte(value>>16),
byte(value>>8),
byte(value),
)
}
func (c *StreamEncoderCommon) WriteByte4Uint32(w io.Writer, value uint32, buf *common.Buffer) error {
return buf.Write(w,
byte(value>>24),
byte(value>>16),
byte(value>>8),
byte(value),
)
}
func (c *StreamEncoderCommon) WriteBytes(w io.Writer, bs []byte, buf *common.Buffer) error {
return buf.Write(w, bs...)
}

View File

@@ -0,0 +1,63 @@
package common
import (
"io"
"sync"
)
type Buffer struct {
Data []byte
B1 []byte
B2 []byte
B4 []byte
B8 []byte
B16 []byte
offset int
}
func (b *Buffer) Write(w io.Writer, vs ...byte) error {
if len(b.Data) < b.offset+len(vs) {
_, err := w.Write(b.Data[:b.offset])
if err != nil {
return err
}
if len(b.Data) < len(vs) {
b.Data = append(b.Data, make([]byte, len(vs)-len(b.Data))...)
}
b.offset = 0
}
for i := range vs {
b.Data[b.offset+i] = vs[i]
}
b.offset += len(vs)
return nil
}
func (b *Buffer) Flush(w io.Writer) error {
_, err := w.Write(b.Data[:b.offset])
return err
}
var bufPool = sync.Pool{
New: func() interface{} {
data := make([]byte, 64)
return &Buffer{
Data: data,
B1: data[:1],
B2: data[:2],
B4: data[:4],
B8: data[:8],
B16: data[:16],
}
},
}
func GetBuffer() *Buffer {
buf := bufPool.Get().(*Buffer)
buf.offset = 0
return buf
}
func PutBuffer(buf *Buffer) {
bufPool.Put(buf)
}

View File

@@ -0,0 +1,50 @@
package decoding
import (
"encoding/binary"
"reflect"
"unsafe"
"github.com/shamaton/msgpack/v2/def"
)
func (d *decoder) isCodeBin(v byte) bool {
switch v {
case def.Bin8, def.Bin16, def.Bin32:
return true
}
return false
}
func (d *decoder) asBinWithCode(code byte, k reflect.Kind) ([]byte, error) {
switch code {
case def.Bin8:
l, err := d.readSize1()
if err != nil {
return emptyBytes, err
}
return d.readSizeN(int(l))
case def.Bin16:
bs, err := d.readSize2()
if err != nil {
return emptyBytes, err
}
return d.readSizeN(int(binary.BigEndian.Uint16(bs)))
case def.Bin32:
bs, err := d.readSize4()
if err != nil {
return emptyBytes, err
}
return d.readSizeN(int(binary.BigEndian.Uint32(bs)))
}
return emptyBytes, d.errorTemplate(code, k)
}
func (d *decoder) asBinStringWithCode(code byte, k reflect.Kind) (string, error) {
bs, err := d.asBinWithCode(code, k)
return *(*string)(unsafe.Pointer(&bs)), err
}

View File

@@ -0,0 +1,25 @@
package decoding
import (
"reflect"
"github.com/shamaton/msgpack/v2/def"
)
func (d *decoder) asBool(k reflect.Kind) (bool, error) {
code, err := d.readSize1()
if err != nil {
return false, err
}
return d.asBoolWithCode(code, k)
}
func (d *decoder) asBoolWithCode(code byte, k reflect.Kind) (bool, error) {
switch code {
case def.True:
return true, nil
case def.False:
return false, nil
}
return false, d.errorTemplate(code, k)
}

View File

@@ -0,0 +1,108 @@
package decoding
import (
"encoding/binary"
"fmt"
"math"
"reflect"
"github.com/shamaton/msgpack/v2/def"
)
func (d *decoder) asComplex64(code byte, k reflect.Kind) (complex64, error) {
switch code {
case def.Fixext8:
t, err := d.readSize1()
if err != nil {
return complex(0, 0), err
}
if int8(t) != def.ComplexTypeCode() {
return complex(0, 0), fmt.Errorf("fixext8. complex type is diffrent %d, %d", t, def.ComplexTypeCode())
}
rb, err := d.readSize4()
if err != nil {
return complex(0, 0), err
}
r := math.Float32frombits(binary.BigEndian.Uint32(rb))
ib, err := d.readSize4()
if err != nil {
return complex(0, 0), err
}
i := math.Float32frombits(binary.BigEndian.Uint32(ib))
return complex(r, i), nil
case def.Fixext16:
t, err := d.readSize1()
if err != nil {
return complex(0, 0), err
}
if int8(t) != def.ComplexTypeCode() {
return complex(0, 0), fmt.Errorf("fixext16. complex type is diffrent %d, %d", t, def.ComplexTypeCode())
}
rb, err := d.readSize8()
if err != nil {
return complex(0, 0), err
}
r := math.Float64frombits(binary.BigEndian.Uint64(rb))
ib, err := d.readSize8()
if err != nil {
return complex(0, 0), err
}
i := math.Float64frombits(binary.BigEndian.Uint64(ib))
return complex64(complex(r, i)), nil
}
return complex(0, 0), fmt.Errorf("should not reach this line!! code %x decoding %v", code, k)
}
func (d *decoder) asComplex128(code byte, k reflect.Kind) (complex128, error) {
switch code {
case def.Fixext8:
t, err := d.readSize1()
if err != nil {
return complex(0, 0), err
}
if int8(t) != def.ComplexTypeCode() {
return complex(0, 0), fmt.Errorf("fixext8. complex type is diffrent %d, %d", t, def.ComplexTypeCode())
}
rb, err := d.readSize4()
if err != nil {
return complex(0, 0), err
}
r := math.Float32frombits(binary.BigEndian.Uint32(rb))
ib, err := d.readSize4()
if err != nil {
return complex(0, 0), err
}
i := math.Float32frombits(binary.BigEndian.Uint32(ib))
return complex128(complex(r, i)), nil
case def.Fixext16:
t, err := d.readSize1()
if err != nil {
return complex(0, 0), err
}
if int8(t) != def.ComplexTypeCode() {
return complex(0, 0), fmt.Errorf("fixext16. complex type is diffrent %d, %d", t, def.ComplexTypeCode())
}
rb, err := d.readSize8()
if err != nil {
return complex(0, 0), err
}
r := math.Float64frombits(binary.BigEndian.Uint64(rb))
ib, err := d.readSize8()
if err != nil {
return complex(0, 0), err
}
i := math.Float64frombits(binary.BigEndian.Uint64(ib))
return complex(r, i), nil
}
return complex(0, 0), fmt.Errorf("should not reach this line!! code %x decoding %v", code, k)
}

View File

@@ -0,0 +1,324 @@
package decoding
import (
"fmt"
"io"
"reflect"
"github.com/shamaton/msgpack/v2/internal/common"
)
type decoder struct {
r io.Reader
asArray bool
buf *common.Buffer
common.Common
}
// Decode analyzes the MessagePack-encoded data and stores
// the result into the pointer of v.
func Decode(r io.Reader, v interface{}, asArray bool) error {
if r == nil {
return fmt.Errorf("reader is nil")
}
rv := reflect.ValueOf(v)
if rv.Kind() != reflect.Ptr {
return fmt.Errorf("holder must set pointer value. but got: %t", v)
}
rv = rv.Elem()
d := decoder{r: r,
buf: common.GetBuffer(),
asArray: asArray,
}
err := d.decode(rv)
common.PutBuffer(d.buf)
return err
}
func (d *decoder) decode(rv reflect.Value) error {
code, err := d.readSize1()
if err != nil {
return err
}
return d.decodeWithCode(code, rv)
}
func (d *decoder) decodeWithCode(code byte, rv reflect.Value) error {
k := rv.Kind()
switch k {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
v, err := d.asIntWithCode(code, k)
if err != nil {
return err
}
rv.SetInt(v)
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
v, err := d.asUintWithCode(code, k)
if err != nil {
return err
}
rv.SetUint(v)
case reflect.Float32:
v, err := d.asFloat32WithCode(code, k)
if err != nil {
return err
}
rv.SetFloat(float64(v))
case reflect.Float64:
v, err := d.asFloat64WithCode(code, k)
if err != nil {
return err
}
rv.SetFloat(v)
case reflect.String:
// byte slice
if d.isCodeBin(code) {
v, err := d.asBinStringWithCode(code, k)
if err != nil {
return err
}
rv.SetString(v)
return nil
}
v, err := d.asStringWithCode(code, k)
if err != nil {
return err
}
rv.SetString(v)
case reflect.Bool:
v, err := d.asBoolWithCode(code, k)
if err != nil {
return err
}
rv.SetBool(v)
case reflect.Slice:
// nil
if d.isCodeNil(code) {
return nil
}
// byte slice
if d.isCodeBin(code) {
bs, err := d.asBinWithCode(code, k)
if err != nil {
return err
}
rv.SetBytes(bs)
return nil
}
// string to bytes
if d.isCodeString(code) {
l, err := d.stringByteLength(code, k)
if err != nil {
return err
}
bs, err := d.asStringByteByLength(l, k)
if err != nil {
return err
}
rv.SetBytes(bs)
return nil
}
// get slice length
l, err := d.sliceLength(code, k)
if err != nil {
return err
}
// check fixed type
found, err := d.asFixedSlice(rv, l)
if err != nil {
return err
}
if found {
return nil
}
// create slice dynamically
tmpSlice := reflect.MakeSlice(rv.Type(), l, l)
for i := 0; i < l; i++ {
v := tmpSlice.Index(i)
if v.Kind() == reflect.Struct {
structCode, err := d.readSize1()
if err != nil {
return err
}
if err = d.setStruct(structCode, v, k); err != nil {
return err
}
} else {
if err = d.decode(v); err != nil {
return err
}
}
}
rv.Set(tmpSlice)
case reflect.Complex64:
v, err := d.asComplex64(code, k)
if err != nil {
return err
}
rv.SetComplex(complex128(v))
case reflect.Complex128:
v, err := d.asComplex128(code, k)
if err != nil {
return err
}
rv.SetComplex(v)
case reflect.Array:
// nil
if d.isCodeNil(code) {
return nil
}
// byte slice
if d.isCodeBin(code) {
bs, err := d.asBinWithCode(code, k)
if err != nil {
return err
}
if len(bs) > rv.Len() {
return fmt.Errorf("%v len is %d, but msgpack has %d elements", rv.Type(), rv.Len(), len(bs))
}
for i, b := range bs {
rv.Index(i).SetUint(uint64(b))
}
return nil
}
// string to bytes
if d.isCodeString(code) {
l, err := d.stringByteLength(code, k)
if err != nil {
return err
}
if l > rv.Len() {
return fmt.Errorf("%v len is %d, but msgpack has %d elements", rv.Type(), rv.Len(), l)
}
bs, err := d.asStringByteByLength(l, k)
if err != nil {
return err
}
for i, b := range bs {
rv.Index(i).SetUint(uint64(b))
}
return nil
}
// get slice length
l, err := d.sliceLength(code, k)
if err != nil {
return err
}
if l > rv.Len() {
return fmt.Errorf("%v len is %d, but msgpack has %d elements", rv.Type(), rv.Len(), l)
}
// create array dynamically
for i := 0; i < l; i++ {
err = d.decode(rv.Index(i))
if err != nil {
return err
}
}
case reflect.Map:
// nil
if d.isCodeNil(code) {
return nil
}
// get map length
l, err := d.mapLength(code, k)
if err != nil {
return err
}
// check fixed type
found, err := d.asFixedMap(rv, l)
if err != nil {
return err
}
if found {
return nil
}
// create dynamically
key := rv.Type().Key()
value := rv.Type().Elem()
if rv.IsNil() {
rv.Set(reflect.MakeMapWithSize(rv.Type(), l))
}
for i := 0; i < l; i++ {
k := reflect.New(key).Elem()
v := reflect.New(value).Elem()
err = d.decode(k)
if err != nil {
return err
}
err = d.decode(v)
if err != nil {
return err
}
rv.SetMapIndex(k, v)
}
case reflect.Struct:
err := d.setStruct(code, rv, k)
if err != nil {
return err
}
case reflect.Ptr:
// nil
if d.isCodeNil(code) {
return nil
}
if rv.Elem().Kind() == reflect.Invalid {
n := reflect.New(rv.Type().Elem())
rv.Set(n)
}
err := d.decodeWithCode(code, rv.Elem())
if err != nil {
return err
}
case reflect.Interface:
if rv.Elem().Kind() == reflect.Ptr {
err := d.decode(rv.Elem())
if err != nil {
return err
}
} else {
v, err := d.asInterfaceWithCode(code, k)
if err != nil {
return err
}
if v != nil {
rv.Set(reflect.ValueOf(v))
}
}
default:
return fmt.Errorf("type(%v) is unsupported", rv.Kind())
}
return nil
}
func (d *decoder) errorTemplate(code byte, k reflect.Kind) error {
return fmt.Errorf("msgpack : invalid code %x decoding %v", code, k)
}

View File

@@ -0,0 +1,160 @@
package decoding
import (
"encoding/binary"
"github.com/shamaton/msgpack/v2/def"
"github.com/shamaton/msgpack/v2/ext"
"github.com/shamaton/msgpack/v2/time"
)
var extCoderMap = map[int8]ext.StreamDecoder{time.StreamDecoder.Code(): time.StreamDecoder}
var extCoders = []ext.StreamDecoder{time.StreamDecoder}
// AddExtDecoder adds decoders for extension types.
func AddExtDecoder(f ext.StreamDecoder) {
// ignore time
if f.Code() == time.Decoder.Code() {
return
}
_, ok := extCoderMap[f.Code()]
if !ok {
extCoderMap[f.Code()] = f
updateExtCoders()
}
}
// RemoveExtDecoder removes decoders for extension types.
func RemoveExtDecoder(f ext.StreamDecoder) {
// ignore time
if f.Code() == time.Decoder.Code() {
return
}
_, ok := extCoderMap[f.Code()]
if ok {
delete(extCoderMap, f.Code())
updateExtCoders()
}
}
func updateExtCoders() {
extCoders = make([]ext.StreamDecoder, len(extCoderMap))
i := 0
for k := range extCoderMap {
extCoders[i] = extCoderMap[k]
i++
}
}
func (d *decoder) readIfExtType(code byte) (innerType int8, data []byte, err error) {
switch code {
case def.Fixext1:
typ, err := d.readSize1()
if err != nil {
return 0, nil, err
}
v, err := d.readSize1()
if err != nil {
return 0, nil, err
}
return int8(typ), []byte{v}, nil
case def.Fixext2:
typ, err := d.readSize1()
if err != nil {
return 0, nil, err
}
data, err = d.readSize2()
if err != nil {
return 0, nil, err
}
return int8(typ), data, nil
case def.Fixext4:
typ, err := d.readSize1()
if err != nil {
return 0, nil, err
}
data, err = d.readSize4()
if err != nil {
return 0, nil, err
}
return int8(typ), data, nil
case def.Fixext8:
typ, err := d.readSize1()
if err != nil {
return 0, nil, err
}
data, err = d.readSize8()
if err != nil {
return 0, nil, err
}
return int8(typ), data, nil
case def.Fixext16:
typ, err := d.readSize1()
if err != nil {
return 0, nil, err
}
data, err = d.readSize16()
if err != nil {
return 0, nil, err
}
return int8(typ), data, nil
case def.Ext8:
bs, err := d.readSize1()
if err != nil {
return 0, nil, err
}
size := int(bs)
typ, err := d.readSize1()
if err != nil {
return 0, nil, err
}
data, err = d.readSizeN(size)
if err != nil {
return 0, nil, err
}
return int8(typ), data, nil
case def.Ext16:
bs, err := d.readSize2()
if err != nil {
return 0, nil, err
}
size := int(binary.BigEndian.Uint16(bs))
typ, err := d.readSize1()
if err != nil {
return 0, nil, err
}
data, err = d.readSizeN(size)
if err != nil {
return 0, nil, err
}
return int8(typ), data, nil
case def.Ext32:
bs, err := d.readSize4()
if err != nil {
return 0, nil, err
}
size := int(binary.BigEndian.Uint32(bs))
typ, err := d.readSize1()
if err != nil {
return 0, nil, err
}
data, err = d.readSizeN(size)
if err != nil {
return 0, nil, err
}
return int8(typ), data, nil
}
return 0, nil, nil
}

View File

@@ -0,0 +1,93 @@
package decoding
import (
"encoding/binary"
"math"
"reflect"
"github.com/shamaton/msgpack/v2/def"
)
func (d *decoder) asFloat32(k reflect.Kind) (float32, error) {
code, err := d.readSize1()
if err != nil {
return 0, err
}
return d.asFloat32WithCode(code, k)
}
func (d *decoder) asFloat32WithCode(code byte, k reflect.Kind) (float32, error) {
switch {
case code == def.Float32:
bs, err := d.readSize4()
if err != nil {
return 0, err
}
v := math.Float32frombits(binary.BigEndian.Uint32(bs))
return v, nil
case d.isPositiveFixNum(code), code == def.Uint8, code == def.Uint16, code == def.Uint32, code == def.Uint64:
v, err := d.asUintWithCode(code, k)
if err != nil {
break
}
return float32(v), nil
case d.isNegativeFixNum(code), code == def.Int8, code == def.Int16, code == def.Int32, code == def.Int64:
v, err := d.asIntWithCode(code, k)
if err != nil {
break
}
return float32(v), nil
case code == def.Nil:
return 0, nil
}
return 0, d.errorTemplate(code, k)
}
func (d *decoder) asFloat64(k reflect.Kind) (float64, error) {
code, err := d.readSize1()
if err != nil {
return 0, err
}
return d.asFloat64WithCode(code, k)
}
func (d *decoder) asFloat64WithCode(code byte, k reflect.Kind) (float64, error) {
switch {
case code == def.Float64:
bs, err := d.readSize8()
if err != nil {
return 0, err
}
v := math.Float64frombits(binary.BigEndian.Uint64(bs))
return v, nil
case code == def.Float32:
bs, err := d.readSize4()
if err != nil {
return 0, err
}
v := math.Float32frombits(binary.BigEndian.Uint32(bs))
return float64(v), nil
case d.isPositiveFixNum(code), code == def.Uint8, code == def.Uint16, code == def.Uint32, code == def.Uint64:
v, err := d.asUintWithCode(code, k)
if err != nil {
break
}
return float64(v), nil
case d.isNegativeFixNum(code), code == def.Int8, code == def.Int16, code == def.Int32, code == def.Int64:
v, err := d.asIntWithCode(code, k)
if err != nil {
break
}
return float64(v), nil
case code == def.Nil:
return 0, nil
}
return 0, d.errorTemplate(code, k)
}

View File

@@ -0,0 +1,113 @@
package decoding
import (
"encoding/binary"
"reflect"
"github.com/shamaton/msgpack/v2/def"
)
func (d *decoder) isPositiveFixNum(v byte) bool {
return def.PositiveFixIntMin <= v && v <= def.PositiveFixIntMax
}
func (d *decoder) isNegativeFixNum(v byte) bool {
return def.NegativeFixintMin <= int8(v) && int8(v) <= def.NegativeFixintMax
}
func (d *decoder) asInt(k reflect.Kind) (int64, error) {
code, err := d.readSize1()
if err != nil {
return 0, err
}
return d.asIntWithCode(code, k)
}
func (d *decoder) asIntWithCode(code byte, k reflect.Kind) (int64, error) {
switch {
case d.isPositiveFixNum(code):
return int64(code), nil
case d.isNegativeFixNum(code):
return int64(int8(code)), nil
case code == def.Uint8:
b, err := d.readSize1()
if err != nil {
return 0, err
}
return int64(b), nil
case code == def.Int8:
b, err := d.readSize1()
if err != nil {
return 0, err
}
return int64(int8(b)), nil
case code == def.Uint16:
bs, err := d.readSize2()
if err != nil {
return 0, err
}
v := binary.BigEndian.Uint16(bs)
return int64(v), nil
case code == def.Int16:
bs, err := d.readSize2()
if err != nil {
return 0, err
}
v := int16(binary.BigEndian.Uint16(bs))
return int64(v), nil
case code == def.Uint32:
bs, err := d.readSize4()
if err != nil {
return 0, err
}
v := binary.BigEndian.Uint32(bs)
return int64(v), nil
case code == def.Int32:
bs, err := d.readSize4()
if err != nil {
return 0, err
}
v := int32(binary.BigEndian.Uint32(bs))
return int64(v), nil
case code == def.Uint64:
bs, err := d.readSize8()
if err != nil {
return 0, err
}
return int64(binary.BigEndian.Uint64(bs)), nil
case code == def.Int64:
bs, err := d.readSize8()
if err != nil {
return 0, err
}
return int64(binary.BigEndian.Uint64(bs)), nil
case code == def.Float32:
v, err := d.asFloat32WithCode(code, k)
if err != nil {
return 0, err
}
return int64(v), nil
case code == def.Float64:
v, err := d.asFloat64WithCode(code, k)
if err != nil {
return 0, err
}
return int64(v), nil
case code == def.Nil:
return 0, nil
}
return 0, d.errorTemplate(code, k)
}

View File

@@ -0,0 +1,177 @@
package decoding
import (
"fmt"
"reflect"
"github.com/shamaton/msgpack/v2/def"
)
func (d *decoder) asInterface(k reflect.Kind) (interface{}, error) {
code, err := d.readSize1()
if err != nil {
return 0, err
}
return d.asInterfaceWithCode(code, k)
}
func (d *decoder) asInterfaceWithCode(code byte, k reflect.Kind) (interface{}, error) {
switch {
case code == def.Nil:
return nil, nil
case code == def.True, code == def.False:
v, err := d.asBoolWithCode(code, k)
if err != nil {
return nil, err
}
return v, nil
case d.isPositiveFixNum(code), code == def.Uint8:
v, err := d.asUintWithCode(code, k)
if err != nil {
return nil, err
}
return uint8(v), err
case code == def.Uint16:
v, err := d.asUintWithCode(code, k)
if err != nil {
return nil, err
}
return uint16(v), err
case code == def.Uint32:
v, err := d.asUintWithCode(code, k)
if err != nil {
return nil, err
}
return uint32(v), err
case code == def.Uint64:
v, err := d.asUintWithCode(code, k)
if err != nil {
return nil, err
}
return v, err
case d.isNegativeFixNum(code), code == def.Int8:
v, err := d.asIntWithCode(code, k)
if err != nil {
return nil, err
}
return int8(v), err
case code == def.Int16:
v, err := d.asIntWithCode(code, k)
if err != nil {
return nil, err
}
return int16(v), err
case code == def.Int32:
v, err := d.asIntWithCode(code, k)
if err != nil {
return nil, err
}
return int32(v), err
case code == def.Int64:
v, err := d.asIntWithCode(code, k)
if err != nil {
return nil, err
}
return v, err
case code == def.Float32:
v, err := d.asFloat32WithCode(code, k)
if err != nil {
return nil, err
}
return v, err
case code == def.Float64:
v, err := d.asFloat64WithCode(code, k)
if err != nil {
return nil, err
}
return v, err
case d.isFixString(code), code == def.Str8, code == def.Str16, code == def.Str32:
v, err := d.asStringWithCode(code, k)
if err != nil {
return nil, err
}
return v, err
case code == def.Bin8, code == def.Bin16, code == def.Bin32:
v, err := d.asBinWithCode(code, k)
if err != nil {
return nil, err
}
return v, err
case d.isFixSlice(code), code == def.Array16, code == def.Array32:
l, err := d.sliceLength(code, k)
if err != nil {
return nil, err
}
v := make([]interface{}, l)
for i := 0; i < l; i++ {
vv, err := d.asInterface(k)
if err != nil {
return nil, err
}
v[i] = vv
}
return v, nil
case d.isFixMap(code), code == def.Map16, code == def.Map32:
l, err := d.mapLength(code, k)
if err != nil {
return nil, err
}
v := make(map[interface{}]interface{}, l)
for i := 0; i < l; i++ {
keyCode, err := d.readSize1()
if err != nil {
return 0, err
}
if d.canSetAsMapKey(keyCode) != nil {
return nil, err
}
key, err := d.asInterfaceWithCode(keyCode, k)
if err != nil {
return nil, err
}
value, err := d.asInterface(k)
if err != nil {
return nil, err
}
v[key] = value
}
return v, nil
}
// ext
extInnerType, extData, err := d.readIfExtType(code)
if err != nil {
return nil, err
}
for i := range extCoders {
if extCoders[i].IsType(code, extInnerType, len(extData)) {
v, err := extCoders[i].ToValue(code, extData, k)
if err != nil {
return nil, err
}
return v, nil
}
}
return nil, d.errorTemplate(code, k)
}
func (d *decoder) canSetAsMapKey(code byte) error {
switch {
case d.isFixSlice(code), code == def.Array16, code == def.Array32:
return fmt.Errorf("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
}

View File

@@ -0,0 +1,698 @@
package decoding
import (
"encoding/binary"
"reflect"
"github.com/shamaton/msgpack/v2/def"
)
var (
typeMapStringInt = reflect.TypeOf(map[string]int{})
typeMapStringInt8 = reflect.TypeOf(map[string]int8{})
typeMapStringInt16 = reflect.TypeOf(map[string]int16{})
typeMapStringInt32 = reflect.TypeOf(map[string]int32{})
typeMapStringInt64 = reflect.TypeOf(map[string]int64{})
typeMapStringUint = reflect.TypeOf(map[string]uint{})
typeMapStringUint8 = reflect.TypeOf(map[string]uint8{})
typeMapStringUint16 = reflect.TypeOf(map[string]uint16{})
typeMapStringUint32 = reflect.TypeOf(map[string]uint32{})
typeMapStringUint64 = reflect.TypeOf(map[string]uint64{})
typeMapStringFloat32 = reflect.TypeOf(map[string]float32{})
typeMapStringFloat64 = reflect.TypeOf(map[string]float64{})
typeMapStringBool = reflect.TypeOf(map[string]bool{})
typeMapStringString = reflect.TypeOf(map[string]string{})
typeMapIntString = reflect.TypeOf(map[int]string{})
typeMapInt8String = reflect.TypeOf(map[int8]string{})
typeMapInt16String = reflect.TypeOf(map[int16]string{})
typeMapInt32String = reflect.TypeOf(map[int32]string{})
typeMapInt64String = reflect.TypeOf(map[int64]string{})
typeMapIntBool = reflect.TypeOf(map[int]bool{})
typeMapInt8Bool = reflect.TypeOf(map[int8]bool{})
typeMapInt16Bool = reflect.TypeOf(map[int16]bool{})
typeMapInt32Bool = reflect.TypeOf(map[int32]bool{})
typeMapInt64Bool = reflect.TypeOf(map[int64]bool{})
typeMapUintString = reflect.TypeOf(map[uint]string{})
typeMapUint8String = reflect.TypeOf(map[uint8]string{})
typeMapUint16String = reflect.TypeOf(map[uint16]string{})
typeMapUint32String = reflect.TypeOf(map[uint32]string{})
typeMapUint64String = reflect.TypeOf(map[uint64]string{})
typeMapUintBool = reflect.TypeOf(map[uint]bool{})
typeMapUint8Bool = reflect.TypeOf(map[uint8]bool{})
typeMapUint16Bool = reflect.TypeOf(map[uint16]bool{})
typeMapUint32Bool = reflect.TypeOf(map[uint32]bool{})
typeMapUint64Bool = reflect.TypeOf(map[uint64]bool{})
typeMapFloat32String = reflect.TypeOf(map[float32]string{})
typeMapFloat64String = reflect.TypeOf(map[float64]string{})
typeMapFloat32Bool = reflect.TypeOf(map[float32]bool{})
typeMapFloat64Bool = reflect.TypeOf(map[float64]bool{})
)
func (d *decoder) isFixMap(v byte) bool {
return def.FixMap <= v && v <= def.FixMap+0x0f
}
func (d *decoder) mapLength(code byte, k reflect.Kind) (int, error) {
switch {
case d.isFixMap(code):
return int(code - def.FixMap), nil
case code == def.Map16:
bs, err := d.readSize2()
if err != nil {
return 0, err
}
return int(binary.BigEndian.Uint16(bs)), nil
case code == def.Map32:
bs, err := d.readSize4()
if err != nil {
return 0, err
}
return int(binary.BigEndian.Uint32(bs)), nil
}
return 0, d.errorTemplate(code, k)
}
func (d *decoder) asFixedMap(rv reflect.Value, l int) (bool, error) {
t := rv.Type()
keyKind := t.Key().Kind()
valueKind := t.Elem().Kind()
switch t {
case typeMapStringInt:
m := make(map[string]int, l)
for i := 0; i < l; i++ {
k, err := d.asString(keyKind)
if err != nil {
return false, err
}
v, err := d.asInt(valueKind)
if err != nil {
return false, err
}
m[k] = int(v)
}
rv.Set(reflect.ValueOf(m))
return true, nil
case typeMapStringUint:
m := make(map[string]uint, l)
for i := 0; i < l; i++ {
k, err := d.asString(keyKind)
if err != nil {
return false, err
}
v, err := d.asUint(valueKind)
if err != nil {
return false, err
}
m[k] = uint(v)
}
rv.Set(reflect.ValueOf(m))
return true, nil
case typeMapStringFloat32:
m := make(map[string]float32, l)
for i := 0; i < l; i++ {
k, err := d.asString(keyKind)
if err != nil {
return false, err
}
v, err := d.asFloat32(valueKind)
if err != nil {
return false, err
}
m[k] = v
}
rv.Set(reflect.ValueOf(m))
return true, nil
case typeMapStringFloat64:
m := make(map[string]float64, l)
for i := 0; i < l; i++ {
k, err := d.asString(keyKind)
if err != nil {
return false, err
}
v, err := d.asFloat64(valueKind)
if err != nil {
return false, err
}
m[k] = v
}
rv.Set(reflect.ValueOf(m))
return true, nil
case typeMapStringBool:
m := make(map[string]bool, l)
for i := 0; i < l; i++ {
k, err := d.asString(keyKind)
if err != nil {
return false, err
}
v, err := d.asBool(valueKind)
if err != nil {
return false, err
}
m[k] = v
}
rv.Set(reflect.ValueOf(m))
return true, nil
case typeMapStringString:
m := make(map[string]string, l)
for i := 0; i < l; i++ {
k, err := d.asString(keyKind)
if err != nil {
return false, err
}
v, err := d.asString(valueKind)
if err != nil {
return false, err
}
m[k] = v
}
rv.Set(reflect.ValueOf(m))
return true, nil
case typeMapStringInt8:
m := make(map[string]int8, l)
for i := 0; i < l; i++ {
k, err := d.asString(keyKind)
if err != nil {
return false, err
}
v, err := d.asInt(valueKind)
if err != nil {
return false, err
}
m[k] = int8(v)
}
rv.Set(reflect.ValueOf(m))
return true, nil
case typeMapStringInt16:
m := make(map[string]int16, l)
for i := 0; i < l; i++ {
k, err := d.asString(keyKind)
if err != nil {
return false, err
}
v, err := d.asInt(valueKind)
if err != nil {
return false, err
}
m[k] = int16(v)
}
rv.Set(reflect.ValueOf(m))
return true, nil
case typeMapStringInt32:
m := make(map[string]int32, l)
for i := 0; i < l; i++ {
k, err := d.asString(keyKind)
if err != nil {
return false, err
}
v, err := d.asInt(valueKind)
if err != nil {
return false, err
}
m[k] = int32(v)
}
rv.Set(reflect.ValueOf(m))
return true, nil
case typeMapStringInt64:
m := make(map[string]int64, l)
for i := 0; i < l; i++ {
k, err := d.asString(keyKind)
if err != nil {
return false, err
}
v, err := d.asInt(valueKind)
if err != nil {
return false, err
}
m[k] = v
}
rv.Set(reflect.ValueOf(m))
return true, nil
case typeMapStringUint8:
m := make(map[string]uint8, l)
for i := 0; i < l; i++ {
k, err := d.asString(keyKind)
if err != nil {
return false, err
}
v, err := d.asUint(valueKind)
if err != nil {
return false, err
}
m[k] = uint8(v)
}
rv.Set(reflect.ValueOf(m))
return true, nil
case typeMapStringUint16:
m := make(map[string]uint16, l)
for i := 0; i < l; i++ {
k, err := d.asString(keyKind)
if err != nil {
return false, err
}
v, err := d.asUint(valueKind)
if err != nil {
return false, err
}
m[k] = uint16(v)
}
rv.Set(reflect.ValueOf(m))
return true, nil
case typeMapStringUint32:
m := make(map[string]uint32, l)
for i := 0; i < l; i++ {
k, err := d.asString(keyKind)
if err != nil {
return false, err
}
v, err := d.asUint(valueKind)
if err != nil {
return false, err
}
m[k] = uint32(v)
}
rv.Set(reflect.ValueOf(m))
return true, nil
case typeMapStringUint64:
m := make(map[string]uint64, l)
for i := 0; i < l; i++ {
k, err := d.asString(keyKind)
if err != nil {
return false, err
}
v, err := d.asUint(valueKind)
if err != nil {
return false, err
}
m[k] = v
}
rv.Set(reflect.ValueOf(m))
return true, nil
case typeMapIntString:
m := make(map[int]string, l)
for i := 0; i < l; i++ {
k, err := d.asInt(keyKind)
if err != nil {
return false, err
}
v, err := d.asString(valueKind)
if err != nil {
return false, err
}
m[int(k)] = v
}
rv.Set(reflect.ValueOf(m))
return true, nil
case typeMapInt8String:
m := make(map[int8]string, l)
for i := 0; i < l; i++ {
k, err := d.asInt(keyKind)
if err != nil {
return false, err
}
v, err := d.asString(valueKind)
if err != nil {
return false, err
}
m[int8(k)] = v
}
rv.Set(reflect.ValueOf(m))
return true, nil
case typeMapInt16String:
m := make(map[int16]string, l)
for i := 0; i < l; i++ {
k, err := d.asInt(keyKind)
if err != nil {
return false, err
}
v, err := d.asString(valueKind)
if err != nil {
return false, err
}
m[int16(k)] = v
}
rv.Set(reflect.ValueOf(m))
return true, nil
case typeMapInt32String:
m := make(map[int32]string, l)
for i := 0; i < l; i++ {
k, err := d.asInt(keyKind)
if err != nil {
return false, err
}
v, err := d.asString(valueKind)
if err != nil {
return false, err
}
m[int32(k)] = v
}
rv.Set(reflect.ValueOf(m))
return true, nil
case typeMapInt64String:
m := make(map[int64]string, l)
for i := 0; i < l; i++ {
k, err := d.asInt(keyKind)
if err != nil {
return false, err
}
v, err := d.asString(valueKind)
if err != nil {
return false, err
}
m[k] = v
}
rv.Set(reflect.ValueOf(m))
return true, nil
case typeMapIntBool:
m := make(map[int]bool, l)
for i := 0; i < l; i++ {
k, err := d.asInt(keyKind)
if err != nil {
return false, err
}
v, err := d.asBool(valueKind)
if err != nil {
return false, err
}
m[int(k)] = v
}
rv.Set(reflect.ValueOf(m))
return true, nil
case typeMapInt8Bool:
m := make(map[int8]bool, l)
for i := 0; i < l; i++ {
k, err := d.asInt(keyKind)
if err != nil {
return false, err
}
v, err := d.asBool(valueKind)
if err != nil {
return false, err
}
m[int8(k)] = v
}
rv.Set(reflect.ValueOf(m))
return true, nil
case typeMapInt16Bool:
m := make(map[int16]bool, l)
for i := 0; i < l; i++ {
k, err := d.asInt(keyKind)
if err != nil {
return false, err
}
v, err := d.asBool(valueKind)
if err != nil {
return false, err
}
m[int16(k)] = v
}
rv.Set(reflect.ValueOf(m))
return true, nil
case typeMapInt32Bool:
m := make(map[int32]bool, l)
for i := 0; i < l; i++ {
k, err := d.asInt(keyKind)
if err != nil {
return false, err
}
v, err := d.asBool(valueKind)
if err != nil {
return false, err
}
m[int32(k)] = v
}
rv.Set(reflect.ValueOf(m))
return true, nil
case typeMapInt64Bool:
m := make(map[int64]bool, l)
for i := 0; i < l; i++ {
k, err := d.asInt(keyKind)
if err != nil {
return false, err
}
v, err := d.asBool(valueKind)
if err != nil {
return false, err
}
m[k] = v
}
rv.Set(reflect.ValueOf(m))
return true, nil
case typeMapUintString:
m := make(map[uint]string, l)
for i := 0; i < l; i++ {
k, err := d.asUint(keyKind)
if err != nil {
return false, err
}
v, err := d.asString(valueKind)
if err != nil {
return false, err
}
m[uint(k)] = v
}
rv.Set(reflect.ValueOf(m))
return true, nil
case typeMapUint8String:
m := make(map[uint8]string, l)
for i := 0; i < l; i++ {
k, err := d.asUint(keyKind)
if err != nil {
return false, err
}
v, err := d.asString(valueKind)
if err != nil {
return false, err
}
m[uint8(k)] = v
}
rv.Set(reflect.ValueOf(m))
return true, nil
case typeMapUint16String:
m := make(map[uint16]string, l)
for i := 0; i < l; i++ {
k, err := d.asUint(keyKind)
if err != nil {
return false, err
}
v, err := d.asString(valueKind)
if err != nil {
return false, err
}
m[uint16(k)] = v
}
rv.Set(reflect.ValueOf(m))
return true, nil
case typeMapUint32String:
m := make(map[uint32]string, l)
for i := 0; i < l; i++ {
k, err := d.asUint(keyKind)
if err != nil {
return false, err
}
v, err := d.asString(valueKind)
if err != nil {
return false, err
}
m[uint32(k)] = v
}
rv.Set(reflect.ValueOf(m))
return true, nil
case typeMapUint64String:
m := make(map[uint64]string, l)
for i := 0; i < l; i++ {
k, err := d.asUint(keyKind)
if err != nil {
return false, err
}
v, err := d.asString(valueKind)
if err != nil {
return false, err
}
m[k] = v
}
rv.Set(reflect.ValueOf(m))
return true, nil
case typeMapUintBool:
m := make(map[uint]bool, l)
for i := 0; i < l; i++ {
k, err := d.asUint(keyKind)
if err != nil {
return false, err
}
v, err := d.asBool(valueKind)
if err != nil {
return false, err
}
m[uint(k)] = v
}
rv.Set(reflect.ValueOf(m))
return true, nil
case typeMapUint8Bool:
m := make(map[uint8]bool, l)
for i := 0; i < l; i++ {
k, err := d.asUint(keyKind)
if err != nil {
return false, err
}
v, err := d.asBool(valueKind)
if err != nil {
return false, err
}
m[uint8(k)] = v
}
rv.Set(reflect.ValueOf(m))
return true, nil
case typeMapUint16Bool:
m := make(map[uint16]bool, l)
for i := 0; i < l; i++ {
k, err := d.asUint(keyKind)
if err != nil {
return false, err
}
v, err := d.asBool(valueKind)
if err != nil {
return false, err
}
m[uint16(k)] = v
}
rv.Set(reflect.ValueOf(m))
return true, nil
case typeMapUint32Bool:
m := make(map[uint32]bool, l)
for i := 0; i < l; i++ {
k, err := d.asUint(keyKind)
if err != nil {
return false, err
}
v, err := d.asBool(valueKind)
if err != nil {
return false, err
}
m[uint32(k)] = v
}
rv.Set(reflect.ValueOf(m))
return true, nil
case typeMapUint64Bool:
m := make(map[uint64]bool, l)
for i := 0; i < l; i++ {
k, err := d.asUint(keyKind)
if err != nil {
return false, err
}
v, err := d.asBool(valueKind)
if err != nil {
return false, err
}
m[k] = v
}
rv.Set(reflect.ValueOf(m))
return true, nil
case typeMapFloat32String:
m := make(map[float32]string, l)
for i := 0; i < l; i++ {
k, err := d.asFloat32(keyKind)
if err != nil {
return false, err
}
v, err := d.asString(valueKind)
if err != nil {
return false, err
}
m[k] = v
}
rv.Set(reflect.ValueOf(m))
return true, nil
case typeMapFloat64String:
m := make(map[float64]string, l)
for i := 0; i < l; i++ {
k, err := d.asFloat64(keyKind)
if err != nil {
return false, err
}
v, err := d.asString(valueKind)
if err != nil {
return false, err
}
m[k] = v
}
rv.Set(reflect.ValueOf(m))
return true, nil
case typeMapFloat32Bool:
m := make(map[float32]bool, l)
for i := 0; i < l; i++ {
k, err := d.asFloat32(keyKind)
if err != nil {
return false, err
}
v, err := d.asBool(valueKind)
if err != nil {
return false, err
}
m[k] = v
}
rv.Set(reflect.ValueOf(m))
return true, nil
case typeMapFloat64Bool:
m := make(map[float64]bool, l)
for i := 0; i < l; i++ {
k, err := d.asFloat64(keyKind)
if err != nil {
return false, err
}
v, err := d.asBool(valueKind)
if err != nil {
return false, err
}
m[k] = v
}
rv.Set(reflect.ValueOf(m))
return true, nil
}
return false, nil
}

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
}

View File

@@ -0,0 +1,50 @@
package decoding
func (d *decoder) readSize1() (byte, error) {
if _, err := d.r.Read(d.buf.B1); err != nil {
return 0, err
}
return d.buf.B1[0], nil
}
func (d *decoder) readSize2() ([]byte, error) {
if _, err := d.r.Read(d.buf.B2); err != nil {
return emptyBytes, err
}
return d.buf.B2, nil
}
func (d *decoder) readSize4() ([]byte, error) {
if _, err := d.r.Read(d.buf.B4); err != nil {
return emptyBytes, err
}
return d.buf.B4, nil
}
func (d *decoder) readSize8() ([]byte, error) {
if _, err := d.r.Read(d.buf.B8); err != nil {
return emptyBytes, err
}
return d.buf.B8, nil
}
func (d *decoder) readSize16() ([]byte, error) {
if _, err := d.r.Read(d.buf.B16); err != nil {
return emptyBytes, err
}
return d.buf.B16, nil
}
func (d *decoder) readSizeN(n int) ([]byte, error) {
var b []byte
if n <= len(d.buf.Data) {
b = d.buf.Data[:n]
} else {
d.buf.Data = append(d.buf.Data, make([]byte, n-len(d.buf.Data))...)
b = d.buf.Data
}
if _, err := d.r.Read(b); err != nil {
return emptyBytes, err
}
return b, nil
}

View File

@@ -0,0 +1,230 @@
package decoding
import (
"encoding/binary"
"reflect"
"github.com/shamaton/msgpack/v2/def"
)
var (
typeIntSlice = reflect.TypeOf([]int{})
typeInt8Slice = reflect.TypeOf([]int8{})
typeInt16Slice = reflect.TypeOf([]int16{})
typeInt32Slice = reflect.TypeOf([]int32{})
typeInt64Slice = reflect.TypeOf([]int64{})
typeUintSlice = reflect.TypeOf([]uint{})
typeUint8Slice = reflect.TypeOf([]uint8{})
typeUint16Slice = reflect.TypeOf([]uint16{})
typeUint32Slice = reflect.TypeOf([]uint32{})
typeUint64Slice = reflect.TypeOf([]uint64{})
typeFloat32Slice = reflect.TypeOf([]float32{})
typeFloat64Slice = reflect.TypeOf([]float64{})
typeStringSlice = reflect.TypeOf([]string{})
typeBoolSlice = reflect.TypeOf([]bool{})
)
func (d *decoder) isFixSlice(v byte) bool {
return def.FixArray <= v && v <= def.FixArray+0x0f
}
func (d *decoder) sliceLength(code byte, k reflect.Kind) (int, error) {
switch {
case d.isFixSlice(code):
return int(code - def.FixArray), nil
case code == def.Array16:
bs, err := d.readSize2()
if err != nil {
return 0, err
}
return int(binary.BigEndian.Uint16(bs)), nil
case code == def.Array32:
bs, err := d.readSize4()
if err != nil {
return 0, err
}
return int(binary.BigEndian.Uint32(bs)), nil
}
return 0, d.errorTemplate(code, k)
}
func (d *decoder) asFixedSlice(rv reflect.Value, l int) (bool, error) {
t := rv.Type()
k := t.Elem().Kind()
switch t {
case typeIntSlice:
sli := make([]int, l)
for i := range sli {
v, err := d.asInt(k)
if err != nil {
return false, err
}
sli[i] = int(v)
}
rv.Set(reflect.ValueOf(sli))
return true, nil
case typeUintSlice:
sli := make([]uint, l)
for i := range sli {
v, err := d.asUint(k)
if err != nil {
return false, err
}
sli[i] = uint(v)
}
rv.Set(reflect.ValueOf(sli))
return true, nil
case typeStringSlice:
sli := make([]string, l)
for i := range sli {
v, err := d.asString(k)
if err != nil {
return false, err
}
sli[i] = v
}
rv.Set(reflect.ValueOf(sli))
return true, nil
case typeBoolSlice:
sli := make([]bool, l)
for i := range sli {
v, err := d.asBool(k)
if err != nil {
return false, err
}
sli[i] = v
}
rv.Set(reflect.ValueOf(sli))
return true, nil
case typeFloat32Slice:
sli := make([]float32, l)
for i := range sli {
v, err := d.asFloat32(k)
if err != nil {
return false, err
}
sli[i] = v
}
rv.Set(reflect.ValueOf(sli))
return true, nil
case typeFloat64Slice:
sli := make([]float64, l)
for i := range sli {
v, err := d.asFloat64(k)
if err != nil {
return false, err
}
sli[i] = v
}
rv.Set(reflect.ValueOf(sli))
return true, nil
case typeInt8Slice:
sli := make([]int8, l)
for i := range sli {
v, err := d.asInt(k)
if err != nil {
return false, err
}
sli[i] = int8(v)
}
rv.Set(reflect.ValueOf(sli))
return true, nil
case typeInt16Slice:
sli := make([]int16, l)
for i := range sli {
v, err := d.asInt(k)
if err != nil {
return false, err
}
sli[i] = int16(v)
}
rv.Set(reflect.ValueOf(sli))
return true, nil
case typeInt32Slice:
sli := make([]int32, l)
for i := range sli {
v, err := d.asInt(k)
if err != nil {
return false, err
}
sli[i] = int32(v)
}
rv.Set(reflect.ValueOf(sli))
return true, nil
case typeInt64Slice:
sli := make([]int64, l)
for i := range sli {
v, err := d.asInt(k)
if err != nil {
return false, err
}
sli[i] = v
}
rv.Set(reflect.ValueOf(sli))
return true, nil
case typeUint8Slice:
sli := make([]uint8, l)
for i := range sli {
v, err := d.asUint(k)
if err != nil {
return false, err
}
sli[i] = uint8(v)
}
rv.Set(reflect.ValueOf(sli))
return true, nil
case typeUint16Slice:
sli := make([]uint16, l)
for i := range sli {
v, err := d.asUint(k)
if err != nil {
return false, err
}
sli[i] = uint16(v)
}
rv.Set(reflect.ValueOf(sli))
return true, nil
case typeUint32Slice:
sli := make([]uint32, l)
for i := range sli {
v, err := d.asUint(k)
if err != nil {
return false, err
}
sli[i] = uint32(v)
}
rv.Set(reflect.ValueOf(sli))
return true, nil
case typeUint64Slice:
sli := make([]uint64, l)
for i := range sli {
v, err := d.asUint(k)
if err != nil {
return false, err
}
sli[i] = v
}
rv.Set(reflect.ValueOf(sli))
return true, nil
}
return false, nil
}

View File

@@ -0,0 +1,88 @@
package decoding
import (
"encoding/binary"
"reflect"
"github.com/shamaton/msgpack/v2/def"
)
var emptyString = ""
var emptyBytes = []byte{}
func (d *decoder) isCodeString(code byte) bool {
return d.isFixString(code) || code == def.Str8 || code == def.Str16 || code == def.Str32
}
func (d *decoder) isFixString(v byte) bool {
return def.FixStr <= v && v <= def.FixStr+0x1f
}
func (d *decoder) stringByteLength(code byte, k reflect.Kind) (int, error) {
if def.FixStr <= code && code <= def.FixStr+0x1f {
l := int(code - def.FixStr)
return l, nil
} else if code == def.Str8 {
b, err := d.readSize1()
if err != nil {
return 0, err
}
return int(b), nil
} else if code == def.Str16 {
b, err := d.readSize2()
if err != nil {
return 0, err
}
return int(binary.BigEndian.Uint16(b)), nil
} else if code == def.Str32 {
b, err := d.readSize4()
if err != nil {
return 0, err
}
return int(binary.BigEndian.Uint32(b)), nil
} else if code == def.Nil {
return 0, nil
}
return 0, d.errorTemplate(code, k)
}
func (d *decoder) asString(k reflect.Kind) (string, error) {
code, err := d.readSize1()
if err != nil {
return emptyString, err
}
return d.asStringWithCode(code, k)
}
func (d *decoder) asStringWithCode(code byte, k reflect.Kind) (string, error) {
bs, err := d.asStringByteWithCode(code, k)
if err != nil {
return emptyString, err
}
return string(bs), nil
}
func (d *decoder) asStringByte(k reflect.Kind) ([]byte, error) {
code, err := d.readSize1()
if err != nil {
return emptyBytes, err
}
return d.asStringByteWithCode(code, k)
}
func (d *decoder) asStringByteWithCode(code byte, k reflect.Kind) ([]byte, error) {
l, err := d.stringByteLength(code, k)
if err != nil {
return emptyBytes, err
}
return d.asStringByteByLength(l, k)
}
func (d *decoder) asStringByteByLength(l int, _ reflect.Kind) ([]byte, error) {
if l < 1 {
return emptyBytes, nil
}
return d.readSizeN(l)
}

View File

@@ -0,0 +1,302 @@
package decoding
import (
"encoding/binary"
"reflect"
"sync"
"github.com/shamaton/msgpack/v2/def"
)
type structCacheTypeMap struct {
keys [][]byte
indexes []int
}
type structCacheTypeArray struct {
m []int
}
// struct cache map
var mapSCTM = sync.Map{}
var mapSCTA = sync.Map{}
func (d *decoder) setStruct(code byte, rv reflect.Value, k reflect.Kind) error {
if len(extCoders) > 0 {
innerType, data, err := d.readIfExtType(code)
if err != nil {
return err
}
if data != nil {
for i := range extCoders {
if extCoders[i].IsType(code, innerType, len(data)) {
v, err := extCoders[i].ToValue(code, data, k)
if err != nil {
return err
}
// Validate that the receptacle is of the right value type.
if rv.Type() == reflect.TypeOf(v) {
rv.Set(reflect.ValueOf(v))
return nil
}
}
}
}
}
if d.asArray {
return d.setStructFromArray(code, rv, k)
}
return d.setStructFromMap(code, rv, k)
}
func (d *decoder) setStructFromArray(code byte, rv reflect.Value, k reflect.Kind) error {
// get length
l, err := d.sliceLength(code, k)
if err != nil {
return err
}
// find or create reference
var scta *structCacheTypeArray
cache, findCache := mapSCTA.Load(rv.Type())
if !findCache {
scta = &structCacheTypeArray{}
for i := 0; i < rv.NumField(); i++ {
if ok, _ := d.CheckField(rv.Type().Field(i)); ok {
scta.m = append(scta.m, i)
}
}
mapSCTA.Store(rv.Type(), scta)
} else {
scta = cache.(*structCacheTypeArray)
}
// set value
for i := 0; i < l; i++ {
if i < len(scta.m) {
err = d.decode(rv.Field(scta.m[i]))
if err != nil {
return err
}
} else {
err = d.jumpOffset()
if err != nil {
return err
}
}
}
return nil
}
func (d *decoder) setStructFromMap(code byte, rv reflect.Value, k reflect.Kind) error {
// get length
l, err := d.mapLength(code, k)
if err != nil {
return err
}
var sctm *structCacheTypeMap
cache, cacheFind := mapSCTM.Load(rv.Type())
if !cacheFind {
sctm = &structCacheTypeMap{}
for i := 0; i < rv.NumField(); i++ {
if ok, name := d.CheckField(rv.Type().Field(i)); ok {
sctm.keys = append(sctm.keys, []byte(name))
sctm.indexes = append(sctm.indexes, i)
}
}
mapSCTM.Store(rv.Type(), sctm)
} else {
sctm = cache.(*structCacheTypeMap)
}
for i := 0; i < l; i++ {
dataKey, err := d.asStringByte(k)
if err != nil {
return err
}
fieldIndex := -1
for keyIndex, keyBytes := range sctm.keys {
if len(keyBytes) != len(dataKey) {
continue
}
fieldIndex = sctm.indexes[keyIndex]
for dataIndex := range dataKey {
if dataKey[dataIndex] != keyBytes[dataIndex] {
fieldIndex = -1
break
}
}
if fieldIndex >= 0 {
break
}
}
if fieldIndex >= 0 {
err = d.decode(rv.Field(fieldIndex))
if err != nil {
return err
}
} else {
err = d.jumpOffset()
if err != nil {
return err
}
}
}
return nil
}
func (d *decoder) jumpOffset() error {
code, err := d.readSize1()
if err != nil {
return err
}
switch {
case code == def.True, code == def.False, code == def.Nil:
// do nothing
case d.isPositiveFixNum(code) || d.isNegativeFixNum(code):
// do nothing
case code == def.Uint8, code == def.Int8:
_, err = d.readSize1()
return err
case code == def.Uint16, code == def.Int16:
_, err = d.readSize2()
return err
case code == def.Uint32, code == def.Int32, code == def.Float32:
_, err = d.readSize4()
return err
case code == def.Uint64, code == def.Int64, code == def.Float64:
_, err = d.readSize8()
return err
case d.isFixString(code):
_, err = d.readSizeN(int(code - def.FixStr))
return err
case code == def.Str8, code == def.Bin8:
b, err := d.readSize1()
if err != nil {
return err
}
_, err = d.readSizeN(int(b))
return err
case code == def.Str16, code == def.Bin16:
bs, err := d.readSize2()
if err != nil {
return err
}
_, err = d.readSizeN(int(binary.BigEndian.Uint16(bs)))
return err
case code == def.Str32, code == def.Bin32:
bs, err := d.readSize4()
if err != nil {
return err
}
_, err = d.readSizeN(int(binary.BigEndian.Uint32(bs)))
return err
case d.isFixSlice(code):
l := int(code - def.FixArray)
for i := 0; i < l; i++ {
if err = d.jumpOffset(); err != nil {
return err
}
}
case code == def.Array16:
bs, err := d.readSize2()
if err != nil {
return err
}
l := int(binary.BigEndian.Uint16(bs))
for i := 0; i < l; i++ {
if err = d.jumpOffset(); err != nil {
return err
}
}
case code == def.Array32:
bs, err := d.readSize4()
if err != nil {
return err
}
l := int(binary.BigEndian.Uint32(bs))
for i := 0; i < l; i++ {
if err = d.jumpOffset(); err != nil {
return err
}
}
case d.isFixMap(code):
l := int(code - def.FixMap)
for i := 0; i < l*2; i++ {
if err = d.jumpOffset(); err != nil {
return err
}
}
case code == def.Map16:
bs, err := d.readSize2()
if err != nil {
return err
}
l := int(binary.BigEndian.Uint16(bs))
for i := 0; i < l*2; i++ {
if err = d.jumpOffset(); err != nil {
return err
}
}
case code == def.Map32:
bs, err := d.readSize4()
if err != nil {
return err
}
l := int(binary.BigEndian.Uint32(bs))
for i := 0; i < l*2; i++ {
if err = d.jumpOffset(); err != nil {
return err
}
}
case code == def.Fixext1:
_, err = d.readSizeN(def.Byte1 + def.Byte1)
return err
case code == def.Fixext2:
_, err = d.readSizeN(def.Byte1 + def.Byte2)
return err
case code == def.Fixext4:
_, err = d.readSizeN(def.Byte1 + def.Byte4)
return err
case code == def.Fixext8:
_, err = d.readSizeN(def.Byte1 + def.Byte8)
return err
case code == def.Fixext16:
_, err = d.readSizeN(def.Byte1 + def.Byte16)
return err
case code == def.Ext8:
b, err := d.readSize1()
if err != nil {
return err
}
_, err = d.readSizeN(def.Byte1 + int(b))
return err
case code == def.Ext16:
bs, err := d.readSize2()
if err != nil {
return err
}
_, err = d.readSizeN(def.Byte1 + int(binary.BigEndian.Uint16(bs)))
return err
case code == def.Ext32:
bs, err := d.readSize4()
if err != nil {
return err
}
_, err = d.readSizeN(def.Byte1 + int(binary.BigEndian.Uint32(bs)))
return err
}
return nil
}

View File

@@ -0,0 +1,91 @@
package decoding
import (
"encoding/binary"
"reflect"
"github.com/shamaton/msgpack/v2/def"
)
func (d *decoder) asUint(k reflect.Kind) (uint64, error) {
code, err := d.readSize1()
if err != nil {
return 0, err
}
return d.asUintWithCode(code, k)
}
func (d *decoder) asUintWithCode(code byte, k reflect.Kind) (uint64, error) {
switch {
case d.isPositiveFixNum(code):
return uint64(code), nil
case d.isNegativeFixNum(code):
return uint64(int8(code)), nil
case code == def.Uint8:
b, err := d.readSize1()
if err != nil {
return 0, err
}
return uint64(b), nil
case code == def.Int8:
b, err := d.readSize1()
if err != nil {
return 0, err
}
return uint64(int8(b)), nil
case code == def.Uint16:
bs, err := d.readSize2()
if err != nil {
return 0, err
}
v := binary.BigEndian.Uint16(bs)
return uint64(v), nil
case code == def.Int16:
bs, err := d.readSize2()
if err != nil {
return 0, err
}
v := int16(binary.BigEndian.Uint16(bs))
return uint64(v), nil
case code == def.Uint32:
bs, err := d.readSize4()
if err != nil {
return 0, err
}
v := binary.BigEndian.Uint32(bs)
return uint64(v), nil
case code == def.Int32:
bs, err := d.readSize4()
if err != nil {
return 0, err
}
v := int32(binary.BigEndian.Uint32(bs))
return uint64(v), nil
case code == def.Uint64:
bs, err := d.readSize8()
if err != nil {
return 0, err
}
return binary.BigEndian.Uint64(bs), nil
case code == def.Int64:
bs, err := d.readSize8()
if err != nil {
return 0, err
}
return binary.BigEndian.Uint64(bs), nil
case code == def.Nil:
return 0, nil
}
return 0, d.errorTemplate(code, k)
}

View File

@@ -0,0 +1,10 @@
package encoding
import "github.com/shamaton/msgpack/v2/def"
func (e *encoder) writeBool(v bool) error {
if v {
return e.setByte1Int(def.True)
}
return e.setByte1Int(def.False)
}

View File

@@ -0,0 +1,40 @@
package encoding
import (
"math"
"reflect"
"github.com/shamaton/msgpack/v2/def"
)
var typeByte = reflect.TypeOf(byte(0))
func (e *encoder) isByteSlice(rv reflect.Value) bool {
return rv.Type().Elem() == typeByte
}
func (e *encoder) writeByteSliceLength(l int) error {
if l <= math.MaxUint8 {
if err := e.setByte1Int(def.Bin8); err != nil {
return err
}
if err := e.setByte1Int(l); err != nil {
return err
}
} else if l <= math.MaxUint16 {
if err := e.setByte1Int(def.Bin16); err != nil {
return err
}
if err := e.setByte2Int(l); err != nil {
return err
}
} else if uint(l) <= math.MaxUint32 {
if err := e.setByte1Int(def.Bin32); err != nil {
return err
}
if err := e.setByte4Int(l); err != nil {
return err
}
}
return nil
}

View File

@@ -0,0 +1,39 @@
package encoding
import (
"math"
"github.com/shamaton/msgpack/v2/def"
)
func (e *encoder) writeComplex64(v complex64) error {
if err := e.setByte1Int(def.Fixext8); err != nil {
return err
}
if err := e.setByte1Int(int(def.ComplexTypeCode())); err != nil {
return err
}
if err := e.setByte4Uint64(uint64(math.Float32bits(real(v)))); err != nil {
return err
}
if err := e.setByte4Uint64(uint64(math.Float32bits(imag(v)))); err != nil {
return err
}
return nil
}
func (e *encoder) writeComplex128(v complex128) error {
if err := e.setByte1Int(def.Fixext16); err != nil {
return err
}
if err := e.setByte1Int(int(def.ComplexTypeCode())); err != nil {
return err
}
if err := e.setByte8Uint64(math.Float64bits(real(v))); err != nil {
return err
}
if err := e.setByte8Uint64(math.Float64bits(imag(v))); err != nil {
return err
}
return nil
}

View File

@@ -0,0 +1,194 @@
package encoding
import (
"fmt"
"io"
"reflect"
"github.com/shamaton/msgpack/v2/internal/common"
)
type encoder struct {
w io.Writer
asArray bool
buf *common.Buffer
common.Common
}
// Encode writes MessagePack-encoded byte array of v to writer.
func Encode(w io.Writer, v any, asArray bool) error {
e := encoder{
w: w,
buf: common.GetBuffer(),
asArray: asArray,
}
rv := reflect.ValueOf(v)
if rv.Kind() == reflect.Ptr {
rv = rv.Elem()
if rv.Kind() == reflect.Ptr {
rv = rv.Elem()
}
}
err := e.create(rv)
if err == nil {
err = e.buf.Flush(e.w)
}
common.PutBuffer(e.buf)
return err
}
func (e *encoder) create(rv reflect.Value) error {
switch rv.Kind() {
case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
v := rv.Uint()
return e.writeUint(v)
case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
v := rv.Int()
return e.writeInt(v)
case reflect.Float32:
return e.writeFloat32(rv.Float())
case reflect.Float64:
return e.writeFloat64(rv.Float())
case reflect.Bool:
return e.writeBool(rv.Bool())
case reflect.String:
return e.writeString(rv.String())
case reflect.Complex64:
return e.writeComplex64(complex64(rv.Complex()))
case reflect.Complex128:
return e.writeComplex128(rv.Complex())
case reflect.Slice:
if rv.IsNil() {
return e.writeNil()
}
l := rv.Len()
// bin format
if e.isByteSlice(rv) {
if err := e.writeByteSliceLength(l); err != nil {
return err
}
return e.setBytes(rv.Bytes())
}
// format
if err := e.writeSliceLength(l); err != nil {
return err
}
if find, err := e.writeFixedSlice(rv); err != nil {
return err
} else if find {
return nil
}
// func
elem := rv.Type().Elem()
var f structWriteFunc
if elem.Kind() == reflect.Struct {
f = e.getStructWriter(elem)
} else {
f = e.create
}
// objects
for i := 0; i < l; i++ {
if err := f(rv.Index(i)); err != nil {
return err
}
}
case reflect.Array:
l := rv.Len()
// bin format
if e.isByteSlice(rv) {
if err := e.writeByteSliceLength(l); err != nil {
return err
}
// objects
for i := 0; i < l; i++ {
if err := e.setByte1Uint64(rv.Index(i).Uint()); err != nil {
return err
}
}
return nil
}
// format
if err := e.writeSliceLength(l); err != nil {
return err
}
// func
elem := rv.Type().Elem()
var f structWriteFunc
if elem.Kind() == reflect.Struct {
f = e.getStructWriter(elem)
} else {
f = e.create
}
// objects
for i := 0; i < l; i++ {
if err := f(rv.Index(i)); err != nil {
return err
}
}
case reflect.Map:
if rv.IsNil() {
return e.writeNil()
}
l := rv.Len()
if err := e.writeMapLength(l); err != nil {
return err
}
if find, err := e.writeFixedMap(rv); err != nil {
return err
} else if find {
return nil
}
// key-value
keys := rv.MapKeys()
for _, k := range keys {
if err := e.create(k); err != nil {
return err
}
if err := e.create(rv.MapIndex(k)); err != nil {
return err
}
}
case reflect.Struct:
return e.writeStruct(rv)
case reflect.Ptr:
if rv.IsNil() {
return e.writeNil()
}
return e.create(rv.Elem())
case reflect.Interface:
return e.create(rv.Elem())
case reflect.Invalid:
return e.writeNil()
default:
return fmt.Errorf("type(%v) is unsupported", rv.Kind())
}
return nil
}

View File

@@ -0,0 +1,48 @@
package encoding
import (
"reflect"
"github.com/shamaton/msgpack/v2/ext"
"github.com/shamaton/msgpack/v2/time"
)
var extCoderMap = map[reflect.Type]ext.StreamEncoder{time.StreamEncoder.Type(): time.StreamEncoder}
var extCoders = []ext.StreamEncoder{time.StreamEncoder}
// AddExtEncoder adds encoders for extension types.
func AddExtEncoder(f ext.StreamEncoder) {
// ignore time
if f.Type() == time.Encoder.Type() {
return
}
_, ok := extCoderMap[f.Type()]
if !ok {
extCoderMap[f.Type()] = f
updateExtCoders()
}
}
// RemoveExtEncoder removes encoders for extension types.
func RemoveExtEncoder(f ext.StreamEncoder) {
// ignore time
if f.Type() == time.Encoder.Type() {
return
}
_, ok := extCoderMap[f.Type()]
if ok {
delete(extCoderMap, f.Type())
updateExtCoders()
}
}
func updateExtCoders() {
extCoders = make([]ext.StreamEncoder, len(extCoderMap))
i := 0
for k := range extCoderMap {
extCoders[i] = extCoderMap[k]
i++
}
}

View File

@@ -0,0 +1,27 @@
package encoding
import (
"math"
"github.com/shamaton/msgpack/v2/def"
)
func (e *encoder) writeFloat32(v float64) error {
if err := e.setByte1Int(def.Float32); err != nil {
return err
}
if err := e.setByte4Uint64(uint64(math.Float32bits(float32(v)))); err != nil {
return err
}
return nil
}
func (e *encoder) writeFloat64(v float64) error {
if err := e.setByte1Int(def.Float64); err != nil {
return err
}
if err := e.setByte8Uint64(math.Float64bits(v)); err != nil {
return err
}
return nil
}

View File

@@ -0,0 +1,52 @@
package encoding
import (
"math"
"github.com/shamaton/msgpack/v2/def"
)
func (e *encoder) isNegativeFixInt64(v int64) bool {
return def.NegativeFixintMin <= v && v <= def.NegativeFixintMax
}
func (e *encoder) writeInt(v int64) error {
if v >= 0 {
if err := e.writeUint(uint64(v)); err != nil {
return err
}
} else if e.isNegativeFixInt64(v) {
if err := e.setByte1Int64(v); err != nil {
return err
}
} else if v >= math.MinInt8 {
if err := e.setByte1Int(def.Int8); err != nil {
return err
}
if err := e.setByte1Int64(v); err != nil {
return err
}
} else if v >= math.MinInt16 {
if err := e.setByte1Int(def.Int16); err != nil {
return err
}
if err := e.setByte2Int64(v); err != nil {
return err
}
} else if v >= math.MinInt32 {
if err := e.setByte1Int(def.Int32); err != nil {
return err
}
if err := e.setByte4Int64(v); err != nil {
return err
}
} else {
if err := e.setByte1Int(def.Int64); err != nil {
return err
}
if err := e.setByte8Int64(v); err != nil {
return err
}
}
return nil
}

View File

@@ -0,0 +1,433 @@
package encoding
import (
"math"
"reflect"
"github.com/shamaton/msgpack/v2/def"
)
func (e *encoder) writeMapLength(l int) error {
// format
if l <= 0x0f {
if err := e.setByte1Int(def.FixMap + l); err != nil {
return err
}
} else if l <= math.MaxUint16 {
if err := e.setByte1Int(def.Map16); err != nil {
return err
}
if err := e.setByte2Int(l); err != nil {
return err
}
} else if uint(l) <= math.MaxUint32 {
if err := e.setByte1Int(def.Map32); err != nil {
return err
}
if err := e.setByte4Int(l); err != nil {
return err
}
}
return nil
}
func (e *encoder) writeFixedMap(rv reflect.Value) (bool, error) {
switch m := rv.Interface().(type) {
case map[string]int:
for k, v := range m {
if err := e.writeString(k); err != nil {
return false, err
}
if err := e.writeInt(int64(v)); err != nil {
return false, err
}
}
return true, nil
case map[string]uint:
for k, v := range m {
if err := e.writeString(k); err != nil {
return false, err
}
if err := e.writeUint(uint64(v)); err != nil {
return false, err
}
}
return true, nil
case map[string]float32:
for k, v := range m {
if err := e.writeString(k); err != nil {
return false, err
}
if err := e.writeFloat32(float64(v)); err != nil {
return false, err
}
}
return true, nil
case map[string]float64:
for k, v := range m {
if err := e.writeString(k); err != nil {
return false, err
}
if err := e.writeFloat64(v); err != nil {
return false, err
}
}
return true, nil
case map[string]bool:
for k, v := range m {
if err := e.writeString(k); err != nil {
return false, err
}
if err := e.writeBool(v); err != nil {
return false, err
}
}
return true, nil
case map[string]string:
for k, v := range m {
if err := e.writeString(k); err != nil {
return false, err
}
if err := e.writeString(v); err != nil {
return false, err
}
}
return true, nil
case map[string]int8:
for k, v := range m {
if err := e.writeString(k); err != nil {
return false, err
}
if err := e.writeInt(int64(v)); err != nil {
return false, err
}
}
return true, nil
case map[string]int16:
for k, v := range m {
if err := e.writeString(k); err != nil {
return false, err
}
if err := e.writeInt(int64(v)); err != nil {
return false, err
}
}
return true, nil
case map[string]int32:
for k, v := range m {
if err := e.writeString(k); err != nil {
return false, err
}
if err := e.writeInt(int64(v)); err != nil {
return false, err
}
}
return true, nil
case map[string]int64:
for k, v := range m {
if err := e.writeString(k); err != nil {
return false, err
}
if err := e.writeInt(int64(v)); err != nil {
return false, err
}
}
return true, nil
case map[string]uint8:
for k, v := range m {
if err := e.writeString(k); err != nil {
return false, err
}
if err := e.writeUint(uint64(v)); err != nil {
return false, err
}
}
return true, nil
case map[string]uint16:
for k, v := range m {
if err := e.writeString(k); err != nil {
return false, err
}
if err := e.writeUint(uint64(v)); err != nil {
return false, err
}
}
return true, nil
case map[string]uint32:
for k, v := range m {
if err := e.writeString(k); err != nil {
return false, err
}
if err := e.writeUint(uint64(v)); err != nil {
return false, err
}
}
return true, nil
case map[string]uint64:
for k, v := range m {
if err := e.writeString(k); err != nil {
return false, err
}
if err := e.writeUint(uint64(v)); err != nil {
return false, err
}
}
return true, nil
case map[int]string:
for k, v := range m {
if err := e.writeInt(int64(k)); err != nil {
return false, err
}
if err := e.writeString(v); err != nil {
return false, err
}
}
return true, nil
case map[int]bool:
for k, v := range m {
if err := e.writeInt(int64(k)); err != nil {
return false, err
}
if err := e.writeBool(v); err != nil {
return false, err
}
}
return true, nil
case map[uint]string:
for k, v := range m {
if err := e.writeUint(uint64(k)); err != nil {
return false, err
}
if err := e.writeString(v); err != nil {
return false, err
}
}
return true, nil
case map[uint]bool:
for k, v := range m {
if err := e.writeUint(uint64(k)); err != nil {
return false, err
}
if err := e.writeBool(v); err != nil {
return false, err
}
}
return true, nil
case map[float32]string:
for k, v := range m {
if err := e.writeFloat32(float64(k)); err != nil {
return false, err
}
if err := e.writeString(v); err != nil {
return false, err
}
}
return true, nil
case map[float32]bool:
for k, v := range m {
if err := e.writeFloat32(float64(k)); err != nil {
return false, err
}
if err := e.writeBool(v); err != nil {
return false, err
}
}
return true, nil
case map[float64]string:
for k, v := range m {
if err := e.writeFloat64(k); err != nil {
return false, err
}
if err := e.writeString(v); err != nil {
return false, err
}
}
return true, nil
case map[float64]bool:
for k, v := range m {
if err := e.writeFloat64(k); err != nil {
return false, err
}
if err := e.writeBool(v); err != nil {
return false, err
}
}
return true, nil
case map[int8]string:
for k, v := range m {
if err := e.writeInt(int64(k)); err != nil {
return false, err
}
if err := e.writeString(v); err != nil {
return false, err
}
}
return true, nil
case map[int8]bool:
for k, v := range m {
if err := e.writeInt(int64(k)); err != nil {
return false, err
}
if err := e.writeBool(v); err != nil {
return false, err
}
}
return true, nil
case map[int16]string:
for k, v := range m {
if err := e.writeInt(int64(k)); err != nil {
return false, err
}
if err := e.writeString(v); err != nil {
return false, err
}
}
return true, nil
case map[int16]bool:
for k, v := range m {
if err := e.writeInt(int64(k)); err != nil {
return false, err
}
if err := e.writeBool(v); err != nil {
return false, err
}
}
return true, nil
case map[int32]string:
for k, v := range m {
if err := e.writeInt(int64(k)); err != nil {
return false, err
}
if err := e.writeString(v); err != nil {
return false, err
}
}
return true, nil
case map[int32]bool:
for k, v := range m {
if err := e.writeInt(int64(k)); err != nil {
return false, err
}
if err := e.writeBool(v); err != nil {
return false, err
}
}
return true, nil
case map[int64]string:
for k, v := range m {
if err := e.writeInt(k); err != nil {
return false, err
}
if err := e.writeString(v); err != nil {
return false, err
}
}
return true, nil
case map[int64]bool:
for k, v := range m {
if err := e.writeInt(k); err != nil {
return false, err
}
if err := e.writeBool(v); err != nil {
return false, err
}
}
return true, nil
case map[uint8]string:
for k, v := range m {
if err := e.writeUint(uint64(k)); err != nil {
return false, err
}
if err := e.writeString(v); err != nil {
return false, err
}
}
return true, nil
case map[uint8]bool:
for k, v := range m {
if err := e.writeUint(uint64(k)); err != nil {
return false, err
}
if err := e.writeBool(v); err != nil {
return false, err
}
}
return true, nil
case map[uint16]string:
for k, v := range m {
if err := e.writeUint(uint64(k)); err != nil {
return false, err
}
if err := e.writeString(v); err != nil {
return false, err
}
}
return true, nil
case map[uint16]bool:
for k, v := range m {
if err := e.writeUint(uint64(k)); err != nil {
return false, err
}
if err := e.writeBool(v); err != nil {
return false, err
}
}
return true, nil
case map[uint32]string:
for k, v := range m {
if err := e.writeUint(uint64(k)); err != nil {
return false, err
}
if err := e.writeString(v); err != nil {
return false, err
}
}
return true, nil
case map[uint32]bool:
for k, v := range m {
if err := e.writeUint(uint64(k)); err != nil {
return false, err
}
if err := e.writeBool(v); err != nil {
return false, err
}
}
return true, nil
case map[uint64]string:
for k, v := range m {
if err := e.writeUint(k); err != nil {
return false, err
}
if err := e.writeString(v); err != nil {
return false, err
}
}
return true, nil
case map[uint64]bool:
for k, v := range m {
if err := e.writeUint(k); err != nil {
return false, err
}
if err := e.writeBool(v); err != nil {
return false, err
}
}
return true, nil
}
return false, nil
}

View File

@@ -0,0 +1,7 @@
package encoding
import "github.com/shamaton/msgpack/v2/def"
func (e *encoder) writeNil() error {
return e.setByte1Int(def.Nil)
}

View File

@@ -0,0 +1,93 @@
package encoding
func (e *encoder) setByte1Int64(value int64) error {
return e.buf.Write(e.w, byte(value))
}
func (e *encoder) setByte2Int64(value int64) error {
return e.buf.Write(e.w,
byte(value>>8),
byte(value),
)
}
func (e *encoder) setByte4Int64(value int64) error {
return e.buf.Write(e.w,
byte(value>>24),
byte(value>>16),
byte(value>>8),
byte(value),
)
}
func (e *encoder) setByte8Int64(value int64) error {
return e.buf.Write(e.w,
byte(value>>56),
byte(value>>48),
byte(value>>40),
byte(value>>32),
byte(value>>24),
byte(value>>16),
byte(value>>8),
byte(value),
)
}
func (e *encoder) setByte1Uint64(value uint64) error {
return e.buf.Write(e.w, byte(value))
}
func (e *encoder) setByte2Uint64(value uint64) error {
return e.buf.Write(e.w,
byte(value>>8),
byte(value),
)
}
func (e *encoder) setByte4Uint64(value uint64) error {
return e.buf.Write(e.w,
byte(value>>24),
byte(value>>16),
byte(value>>8),
byte(value),
)
}
func (e *encoder) setByte8Uint64(value uint64) error {
return e.buf.Write(e.w,
byte(value>>56),
byte(value>>48),
byte(value>>40),
byte(value>>32),
byte(value>>24),
byte(value>>16),
byte(value>>8),
byte(value),
)
}
func (e *encoder) setByte1Int(value int) error {
return e.buf.Write(e.w,
byte(value),
)
}
func (e *encoder) setByte2Int(value int) error {
return e.buf.Write(e.w,
byte(value>>8),
byte(value),
)
}
func (e *encoder) setByte4Int(value int) error {
return e.buf.Write(e.w,
byte(value>>24),
byte(value>>16),
byte(value>>8),
byte(value),
)
}
func (e *encoder) setBytes(bs []byte) error {
return e.buf.Write(e.w, bs...)
}

View File

@@ -0,0 +1,151 @@
package encoding
import (
"math"
"reflect"
"github.com/shamaton/msgpack/v2/def"
)
func (e *encoder) writeSliceLength(l int) error {
// format size
if l <= 0x0f {
if err := e.setByte1Int(def.FixArray + l); err != nil {
return err
}
} else if l <= math.MaxUint16 {
if err := e.setByte1Int(def.Array16); err != nil {
return err
}
if err := e.setByte2Int(l); err != nil {
return err
}
} else if uint(l) <= math.MaxUint32 {
if err := e.setByte1Int(def.Array32); err != nil {
return err
}
if err := e.setByte4Int(l); err != nil {
return err
}
}
return nil
}
func (e *encoder) writeFixedSlice(rv reflect.Value) (bool, error) {
switch sli := rv.Interface().(type) {
case []int:
for _, v := range sli {
if err := e.writeInt(int64(v)); err != nil {
return false, err
}
}
return true, nil
case []uint:
for _, v := range sli {
if err := e.writeUint(uint64(v)); err != nil {
return false, err
}
}
return true, nil
case []string:
for _, v := range sli {
if err := e.writeString(v); err != nil {
return false, err
}
}
return true, nil
case []float32:
for _, v := range sli {
if err := e.writeFloat32(float64(v)); err != nil {
return false, err
}
}
return true, nil
case []float64:
for _, v := range sli {
if err := e.writeFloat64(float64(v)); err != nil {
return false, err
}
}
return true, nil
case []bool:
for _, v := range sli {
if err := e.writeBool(v); err != nil {
return false, err
}
}
return true, nil
case []int8:
for _, v := range sli {
if err := e.writeInt(int64(v)); err != nil {
return false, err
}
}
return true, nil
case []int16:
for _, v := range sli {
if err := e.writeInt(int64(v)); err != nil {
return false, err
}
}
return true, nil
case []int32:
for _, v := range sli {
if err := e.writeInt(int64(v)); err != nil {
return false, err
}
}
return true, nil
case []int64:
for _, v := range sli {
if err := e.writeInt(v); err != nil {
return false, err
}
}
return true, nil
case []uint8:
for _, v := range sli {
if err := e.writeUint(uint64(v)); err != nil {
return false, err
}
}
return true, nil
case []uint16:
for _, v := range sli {
if err := e.writeUint(uint64(v)); err != nil {
return false, err
}
}
return true, nil
case []uint32:
for _, v := range sli {
if err := e.writeUint(uint64(v)); err != nil {
return false, err
}
}
return true, nil
case []uint64:
for _, v := range sli {
if err := e.writeUint(v); err != nil {
return false, err
}
}
return true, nil
}
return false, nil
}

View File

@@ -0,0 +1,41 @@
package encoding
import (
"math"
"unsafe"
"github.com/shamaton/msgpack/v2/def"
)
func (e *encoder) writeString(str string) error {
// NOTE : unsafe
strBytes := *(*[]byte)(unsafe.Pointer(&str))
l := len(strBytes)
if l < 32 {
if err := e.setByte1Int(def.FixStr + l); err != nil {
return err
}
} else if l <= math.MaxUint8 {
if err := e.setByte1Int(def.Str8); err != nil {
return err
}
if err := e.setByte1Int(l); err != nil {
return err
}
} else if l <= math.MaxUint16 {
if err := e.setByte1Int(def.Str16); err != nil {
return err
}
if err := e.setByte2Int(l); err != nil {
return err
}
} else {
if err := e.setByte1Int(def.Str32); err != nil {
return err
}
if err := e.setByte4Int(l); err != nil {
return err
}
}
return e.setBytes(strBytes)
}

View File

@@ -0,0 +1,140 @@
package encoding
import (
"math"
"reflect"
"sync"
"github.com/shamaton/msgpack/v2/def"
"github.com/shamaton/msgpack/v2/internal/common"
)
type structCache struct {
indexes []int
names []string
common.Common
}
var cachemap = sync.Map{}
type structWriteFunc func(rv reflect.Value) error
func (e *encoder) getStructWriter(typ reflect.Type) structWriteFunc {
for i := range extCoders {
if extCoders[i].Type() == typ {
return func(rv reflect.Value) error {
return extCoders[i].Write(e.w, rv, e.buf)
}
}
}
if e.asArray {
return e.writeStructArray
}
return e.writeStructMap
}
func (e *encoder) writeStruct(rv reflect.Value) error {
for i := range extCoders {
if extCoders[i].Type() == rv.Type() {
return extCoders[i].Write(e.w, rv, e.buf)
}
}
if e.asArray {
return e.writeStructArray(rv)
}
return e.writeStructMap(rv)
}
func (e *encoder) writeStructArray(rv reflect.Value) error {
c := e.getStructCache(rv)
// write format
num := len(c.indexes)
if num <= 0x0f {
if err := e.setByte1Int(def.FixArray + num); err != nil {
return err
}
} else if num <= math.MaxUint16 {
if err := e.setByte1Int(def.Array16); err != nil {
return err
}
if err := e.setByte2Int(num); err != nil {
return err
}
} else if uint(num) <= math.MaxUint32 {
if err := e.setByte1Int(def.Array32); err != nil {
return err
}
if err := e.setByte4Int(num); err != nil {
return err
}
}
for i := 0; i < num; i++ {
if err := e.create(rv.Field(c.indexes[i])); err != nil {
return err
}
}
return nil
}
func (e *encoder) writeStructMap(rv reflect.Value) error {
c := e.getStructCache(rv)
// format size
num := len(c.indexes)
if num <= 0x0f {
if err := e.setByte1Int(def.FixMap + num); err != nil {
return err
}
} else if num <= math.MaxUint16 {
if err := e.setByte1Int(def.Map16); err != nil {
return err
}
if err := e.setByte2Int(num); err != nil {
return err
}
} else if uint(num) <= math.MaxUint32 {
if err := e.setByte1Int(def.Map32); err != nil {
return err
}
if err := e.setByte4Int(num); err != nil {
return err
}
}
for i := 0; i < num; i++ {
if err := e.writeString(c.names[i]); err != nil {
return err
}
if err := e.create(rv.Field(c.indexes[i])); err != nil {
return err
}
}
return nil
}
func (e *encoder) getStructCache(rv reflect.Value) *structCache {
t := rv.Type()
cache, find := cachemap.Load(t)
if find {
return cache.(*structCache)
}
var c *structCache
if !find {
c = &structCache{}
for i := 0; i < rv.NumField(); i++ {
if ok, name := e.CheckField(rv.Type().Field(i)); ok {
c.indexes = append(c.indexes, i)
c.names = append(c.names, name)
}
}
cachemap.Store(t, c)
}
return c
}

View File

@@ -0,0 +1,44 @@
package encoding
import (
"math"
"github.com/shamaton/msgpack/v2/def"
)
func (e *encoder) writeUint(v uint64) error {
if v <= math.MaxInt8 {
if err := e.setByte1Uint64(v); err != nil {
return err
}
} else if v <= math.MaxUint8 {
if err := e.setByte1Int(def.Uint8); err != nil {
return err
}
if err := e.setByte1Uint64(v); err != nil {
return err
}
} else if v <= math.MaxUint16 {
if err := e.setByte1Int(def.Uint16); err != nil {
return err
}
if err := e.setByte2Uint64(v); err != nil {
return err
}
} else if v <= math.MaxUint32 {
if err := e.setByte1Int(def.Uint32); err != nil {
return err
}
if err := e.setByte4Uint64(v); err != nil {
return err
}
} else {
if err := e.setByte1Int(def.Uint64); err != nil {
return err
}
if err := e.setByte8Uint64(v); err != nil {
return err
}
}
return nil
}

View File

@@ -2,11 +2,14 @@ package msgpack
import (
"fmt"
"io"
"github.com/shamaton/msgpack/v2/def"
"github.com/shamaton/msgpack/v2/ext"
"github.com/shamaton/msgpack/v2/internal/decoding"
"github.com/shamaton/msgpack/v2/internal/encoding"
streamdecoding "github.com/shamaton/msgpack/v2/internal/stream/decoding"
streamencoding "github.com/shamaton/msgpack/v2/internal/stream/encoding"
)
// StructAsArray is encoding option.
@@ -18,12 +21,23 @@ func Marshal(v interface{}) ([]byte, error) {
return encoding.Encode(v, StructAsArray)
}
// MarshalWrite writes MessagePack-encoded byte array of v to writer.
func MarshalWrite(w io.Writer, v interface{}) error {
return streamencoding.Encode(w, v, StructAsArray)
}
// Unmarshal analyzes the MessagePack-encoded data and stores
// the result into the pointer of v.
func Unmarshal(data []byte, v interface{}) error {
return decoding.Decode(data, v, StructAsArray)
}
// UnmarshalRead reads the MessagePack-encoded data from reader and stores
// the result into the pointer of v.
func UnmarshalRead(r io.Reader, v interface{}) error {
return streamdecoding.Decode(r, v, StructAsArray)
}
// AddExtCoder adds encoders for extension types.
func AddExtCoder(e ext.Encoder, d ext.Decoder) error {
if e.Code() != d.Code() {
@@ -34,6 +48,16 @@ func AddExtCoder(e ext.Encoder, d ext.Decoder) error {
return nil
}
// AddExtStreamCoder adds stream encoders for extension types.
func AddExtStreamCoder(e ext.StreamEncoder, d ext.StreamDecoder) error {
if e.Code() != d.Code() {
return fmt.Errorf("code different %d:%d", e.Code(), d.Code())
}
streamencoding.AddExtEncoder(e)
streamdecoding.AddExtDecoder(d)
return nil
}
// RemoveExtCoder removes encoders for extension types.
func RemoveExtCoder(e ext.Encoder, d ext.Decoder) error {
if e.Code() != d.Code() {
@@ -44,6 +68,16 @@ func RemoveExtCoder(e ext.Encoder, d ext.Decoder) error {
return nil
}
// RemoveExtStreamCoder removes stream encoders for extension types.
func RemoveExtStreamCoder(e ext.StreamEncoder, d ext.StreamDecoder) error {
if e.Code() != d.Code() {
return fmt.Errorf("code different %d:%d", e.Code(), d.Code())
}
streamencoding.RemoveExtEncoder(e)
streamdecoding.RemoveExtDecoder(d)
return nil
}
// SetComplexTypeCode sets def.complexTypeCode
func SetComplexTypeCode(code int8) {
def.SetComplexTypeCode(code)

View File

@@ -18,6 +18,8 @@ type timeDecoder struct {
ext.DecoderCommon
}
var _ ext.Decoder = (*timeDecoder)(nil)
func (td *timeDecoder) Code() int8 {
return def.TimeStamp
}

View File

@@ -0,0 +1,57 @@
package time
import (
"encoding/binary"
"fmt"
"github.com/shamaton/msgpack/v2/def"
"github.com/shamaton/msgpack/v2/ext"
"reflect"
"time"
)
var StreamDecoder = new(timeStreamDecoder)
type timeStreamDecoder struct {
ext.DecoderStreamCommon
}
var _ ext.StreamDecoder = (*timeStreamDecoder)(nil)
func (td *timeStreamDecoder) Code() int8 {
return def.TimeStamp
}
func (td *timeStreamDecoder) IsType(code byte, innerType int8, dataLength int) bool {
switch code {
case def.Fixext4, def.Fixext8:
return innerType == td.Code()
case def.Ext8:
return innerType == td.Code() && dataLength == 12
}
return false
}
func (td *timeStreamDecoder) ToValue(code byte, data []byte, k reflect.Kind) (interface{}, error) {
switch code {
case def.Fixext4:
return time.Unix(int64(binary.BigEndian.Uint32(data)), 0), nil
case def.Fixext8:
data64 := binary.BigEndian.Uint64(data)
nano := int64(data64 >> 34)
if nano > 999999999 {
return zero, fmt.Errorf("in timestamp 64 formats, nanoseconds must not be larger than 999999999 : %d", nano)
}
return time.Unix(int64(data64&0x00000003ffffffff), nano), nil
case def.Ext8:
nano := binary.BigEndian.Uint32(data[:4])
if nano > 999999999 {
return zero, fmt.Errorf("in timestamp 96 formats, nanoseconds must not be larger than 999999999 : %d", nano)
}
sec := binary.BigEndian.Uint64(data[4:12])
return time.Unix(int64(sec), int64(nano)), nil
}
return zero, fmt.Errorf("should not reach this line!! code %x decoding %v", code, k)
}

View File

@@ -0,0 +1,76 @@
package time
import (
"github.com/shamaton/msgpack/v2/internal/common"
"io"
"reflect"
"time"
"github.com/shamaton/msgpack/v2/def"
"github.com/shamaton/msgpack/v2/ext"
)
var StreamEncoder = new(timeStreamEncoder)
type timeStreamEncoder struct {
ext.StreamEncoderCommon
}
var _ ext.StreamEncoder = (*timeStreamEncoder)(nil)
func (timeStreamEncoder) Code() int8 {
return def.TimeStamp
}
func (timeStreamEncoder) Type() reflect.Type {
return typeOf
}
func (e timeStreamEncoder) Write(w io.Writer, value reflect.Value, buf *common.Buffer) error {
t := value.Interface().(time.Time)
secs := uint64(t.Unix())
if secs>>34 == 0 {
data := uint64(t.Nanosecond())<<34 | secs
if data&0xffffffff00000000 == 0 {
if err := e.WriteByte1Int(w, def.Fixext4, buf); err != nil {
return err
}
if err := e.WriteByte1Int(w, def.TimeStamp, buf); err != nil {
return err
}
if err := e.WriteByte4Uint64(w, data, buf); err != nil {
return err
}
return nil
}
if err := e.WriteByte1Int(w, def.Fixext8, buf); err != nil {
return err
}
if err := e.WriteByte1Int(w, def.TimeStamp, buf); err != nil {
return err
}
if err := e.WriteByte8Uint64(w, data, buf); err != nil {
return err
}
return nil
}
if err := e.WriteByte1Int(w, def.Ext8, buf); err != nil {
return err
}
if err := e.WriteByte1Int(w, 12, buf); err != nil {
return err
}
if err := e.WriteByte1Int(w, def.TimeStamp, buf); err != nil {
return err
}
if err := e.WriteByte4Int(w, t.Nanosecond(), buf); err != nil {
return err
}
if err := e.WriteByte8Uint64(w, secs, buf); err != nil {
return err
}
return nil
}

6
vendor/modules.txt vendored
View File

@@ -1702,14 +1702,16 @@ github.com/sergi/go-diff/diffmatchpatch
# github.com/sethvargo/go-password v0.2.0
## explicit; go 1.14
github.com/sethvargo/go-password/password
# github.com/shamaton/msgpack/v2 v2.1.1
## explicit; go 1.15
# github.com/shamaton/msgpack/v2 v2.2.0
## explicit; go 1.20
github.com/shamaton/msgpack/v2
github.com/shamaton/msgpack/v2/def
github.com/shamaton/msgpack/v2/ext
github.com/shamaton/msgpack/v2/internal/common
github.com/shamaton/msgpack/v2/internal/decoding
github.com/shamaton/msgpack/v2/internal/encoding
github.com/shamaton/msgpack/v2/internal/stream/decoding
github.com/shamaton/msgpack/v2/internal/stream/encoding
github.com/shamaton/msgpack/v2/time
# github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749
## explicit