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