Initial QSfera import
This commit is contained in:
+16
@@ -0,0 +1,16 @@
|
||||
package encoding
|
||||
|
||||
import "github.com/shamaton/msgpack/v2/def"
|
||||
|
||||
//func (e *encoder) calcBool() int {
|
||||
// return 0
|
||||
//}
|
||||
|
||||
func (e *encoder) writeBool(v bool, offset int) int {
|
||||
if v {
|
||||
offset = e.setByte1Int(def.True, offset)
|
||||
} else {
|
||||
offset = e.setByte1Int(def.False, offset)
|
||||
}
|
||||
return offset
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
package encoding
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"reflect"
|
||||
|
||||
"github.com/shamaton/msgpack/v2/def"
|
||||
)
|
||||
|
||||
var typeByte = reflect.TypeOf(byte(0))
|
||||
|
||||
func (e *encoder) isByteSlice(rv reflect.Value) bool {
|
||||
return rv.Type().Elem() == typeByte
|
||||
}
|
||||
|
||||
func (e *encoder) calcByteSlice(l int) (int, error) {
|
||||
if l <= math.MaxUint8 {
|
||||
return def.Byte1 + def.Byte1 + l, nil
|
||||
} else if l <= math.MaxUint16 {
|
||||
return def.Byte1 + def.Byte2 + l, nil
|
||||
} else if uint(l) <= math.MaxUint32 {
|
||||
return def.Byte1 + def.Byte4 + l, nil
|
||||
}
|
||||
// not supported error
|
||||
return 0, fmt.Errorf("%w slice length : %d", def.ErrUnsupportedType, l)
|
||||
}
|
||||
|
||||
func (e *encoder) writeByteSliceLength(l int, offset int) int {
|
||||
if l <= math.MaxUint8 {
|
||||
offset = e.setByte1Int(def.Bin8, offset)
|
||||
offset = e.setByte1Int(l, offset)
|
||||
} else if l <= math.MaxUint16 {
|
||||
offset = e.setByte1Int(def.Bin16, offset)
|
||||
offset = e.setByte2Int(l, offset)
|
||||
} else if uint(l) <= math.MaxUint32 {
|
||||
offset = e.setByte1Int(def.Bin32, offset)
|
||||
offset = e.setByte4Int(l, offset)
|
||||
}
|
||||
return offset
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
package encoding
|
||||
|
||||
import (
|
||||
"math"
|
||||
|
||||
"github.com/shamaton/msgpack/v2/def"
|
||||
)
|
||||
|
||||
func (e *encoder) calcComplex64() int {
|
||||
return def.Byte1 + def.Byte1 + def.Byte8
|
||||
}
|
||||
|
||||
func (e *encoder) calcComplex128() int {
|
||||
return def.Byte1 + def.Byte1 + def.Byte16
|
||||
}
|
||||
|
||||
func (e *encoder) writeComplex64(v complex64, offset int) int {
|
||||
offset = e.setByte1Int(def.Fixext8, offset)
|
||||
offset = e.setByte1Int(int(def.ComplexTypeCode()), offset)
|
||||
offset = e.setByte4Uint64(uint64(math.Float32bits(real(v))), offset)
|
||||
offset = e.setByte4Uint64(uint64(math.Float32bits(imag(v))), offset)
|
||||
return offset
|
||||
}
|
||||
|
||||
func (e *encoder) writeComplex128(v complex128, offset int) int {
|
||||
offset = e.setByte1Int(def.Fixext16, offset)
|
||||
offset = e.setByte1Int(int(def.ComplexTypeCode()), offset)
|
||||
offset = e.setByte8Uint64(math.Float64bits(real(v)), offset)
|
||||
offset = e.setByte8Uint64(math.Float64bits(imag(v)), offset)
|
||||
return offset
|
||||
}
|
||||
+382
@@ -0,0 +1,382 @@
|
||||
package encoding
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"reflect"
|
||||
|
||||
"github.com/shamaton/msgpack/v2/def"
|
||||
"github.com/shamaton/msgpack/v2/internal/common"
|
||||
)
|
||||
|
||||
type encoder struct {
|
||||
d []byte
|
||||
asArray bool
|
||||
common.Common
|
||||
mk map[uintptr][]reflect.Value
|
||||
mv map[uintptr][]reflect.Value
|
||||
}
|
||||
|
||||
// Encode returns the MessagePack-encoded byte array of v.
|
||||
func Encode(v interface{}, asArray bool) (b []byte, err error) {
|
||||
e := encoder{asArray: asArray}
|
||||
/*
|
||||
defer func() {
|
||||
e := recover()
|
||||
if e != nil {
|
||||
b = nil
|
||||
err = fmt.Errorf("unexpected error!! \n%s", stackTrace())
|
||||
}
|
||||
}()
|
||||
*/
|
||||
|
||||
rv := reflect.ValueOf(v)
|
||||
if rv.Kind() == reflect.Ptr {
|
||||
rv = rv.Elem()
|
||||
if rv.Kind() == reflect.Ptr {
|
||||
rv = rv.Elem()
|
||||
}
|
||||
}
|
||||
size, err := e.calcSize(rv)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
e.d = make([]byte, size)
|
||||
last := e.create(rv, 0)
|
||||
if size != last {
|
||||
return nil, fmt.Errorf("%w size=%d, lastIdx=%d", def.ErrNotMatchLastIndex, size, last)
|
||||
}
|
||||
return e.d, err
|
||||
}
|
||||
|
||||
//func stackTrace() string {
|
||||
// msg := ""
|
||||
// for depth := 0; ; depth++ {
|
||||
// _, file, line, ok := runtime.Caller(depth)
|
||||
// if !ok {
|
||||
// break
|
||||
// }
|
||||
// msg += fmt.Sprintln(depth, ": ", file, ":", line)
|
||||
// }
|
||||
// return msg
|
||||
//}
|
||||
|
||||
func (e *encoder) calcSize(rv reflect.Value) (int, error) {
|
||||
switch rv.Kind() {
|
||||
case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
|
||||
v := rv.Uint()
|
||||
return e.calcUint(v), nil
|
||||
|
||||
case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
|
||||
v := rv.Int()
|
||||
return e.calcInt(int64(v)), nil
|
||||
|
||||
case reflect.Float32:
|
||||
return e.calcFloat32(0), nil
|
||||
|
||||
case reflect.Float64:
|
||||
return e.calcFloat64(0), nil
|
||||
|
||||
case reflect.String:
|
||||
return e.calcString(rv.String()), nil
|
||||
|
||||
case reflect.Bool:
|
||||
return def.Byte1, nil
|
||||
|
||||
case reflect.Complex64:
|
||||
return e.calcComplex64(), nil
|
||||
|
||||
case reflect.Complex128:
|
||||
return e.calcComplex128(), nil
|
||||
|
||||
case reflect.Slice:
|
||||
if rv.IsNil() {
|
||||
return def.Byte1, nil
|
||||
}
|
||||
// bin format
|
||||
if e.isByteSlice(rv) {
|
||||
size, err := e.calcByteSlice(rv.Len())
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return size, nil
|
||||
}
|
||||
|
||||
if size, find := e.calcFixedSlice(rv); find {
|
||||
return size, nil
|
||||
}
|
||||
|
||||
// func
|
||||
elem := rv.Type().Elem()
|
||||
var f structCalcFunc
|
||||
if elem.Kind() == reflect.Struct {
|
||||
f = e.getStructCalc(elem)
|
||||
} else {
|
||||
f = e.calcSize
|
||||
}
|
||||
|
||||
l := rv.Len()
|
||||
size, err := e.calcLength(l)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// objects size
|
||||
for i := 0; i < l; i++ {
|
||||
s, err := f(rv.Index(i))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
size += s
|
||||
}
|
||||
return size, nil
|
||||
|
||||
case reflect.Array:
|
||||
// bin format
|
||||
if e.isByteSlice(rv) {
|
||||
size, err := e.calcByteSlice(rv.Len())
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return size, nil
|
||||
}
|
||||
|
||||
// func
|
||||
elem := rv.Type().Elem()
|
||||
var f structCalcFunc
|
||||
if elem.Kind() == reflect.Struct {
|
||||
f = e.getStructCalc(elem)
|
||||
} else {
|
||||
f = e.calcSize
|
||||
}
|
||||
|
||||
l := rv.Len()
|
||||
size, err := e.calcLength(l)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// objects size
|
||||
for i := 0; i < l; i++ {
|
||||
s, err := f(rv.Index(i))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
size += s
|
||||
}
|
||||
return size, nil
|
||||
|
||||
case reflect.Map:
|
||||
if rv.IsNil() {
|
||||
return def.Byte1, nil
|
||||
}
|
||||
|
||||
if size, find := e.calcFixedMap(rv); find {
|
||||
return size, nil
|
||||
}
|
||||
|
||||
if e.mk == nil {
|
||||
e.mk = map[uintptr][]reflect.Value{}
|
||||
e.mv = map[uintptr][]reflect.Value{}
|
||||
}
|
||||
|
||||
keys := rv.MapKeys()
|
||||
size, err := e.calcLength(len(keys))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// key-value
|
||||
mv := make([]reflect.Value, len(keys))
|
||||
i := 0
|
||||
for _, k := range keys {
|
||||
keySize, err := e.calcSize(k)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
value := rv.MapIndex(k)
|
||||
valueSize, err := e.calcSize(value)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
size += keySize + valueSize
|
||||
mv[i] = value
|
||||
i++
|
||||
}
|
||||
e.mk[rv.Pointer()], e.mv[rv.Pointer()] = keys, mv
|
||||
return size, nil
|
||||
|
||||
case reflect.Struct:
|
||||
size, err := e.calcStruct(rv)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return size, nil
|
||||
|
||||
case reflect.Ptr:
|
||||
if rv.IsNil() {
|
||||
return def.Byte1, nil
|
||||
}
|
||||
size, err := e.calcSize(rv.Elem())
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return size, nil
|
||||
|
||||
case reflect.Interface:
|
||||
size, err := e.calcSize(rv.Elem())
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return size, nil
|
||||
|
||||
case reflect.Invalid:
|
||||
// do nothing (return nil)
|
||||
return def.Byte1, nil
|
||||
|
||||
default:
|
||||
return 0, fmt.Errorf("%v is %w type", rv.Kind(), def.ErrUnsupportedType)
|
||||
}
|
||||
}
|
||||
|
||||
func (e *encoder) calcLength(l int) (int, error) {
|
||||
if l <= 0x0f {
|
||||
return def.Byte1, nil
|
||||
} else if l <= math.MaxUint16 {
|
||||
return def.Byte1 + def.Byte2, nil
|
||||
} else if uint(l) <= math.MaxUint32 {
|
||||
return def.Byte1 + def.Byte4, nil
|
||||
}
|
||||
// not supported error
|
||||
return 0, fmt.Errorf("array length %d is %w", l, def.ErrUnsupportedLength)
|
||||
}
|
||||
|
||||
func (e *encoder) create(rv reflect.Value, offset int) int {
|
||||
|
||||
switch rv.Kind() {
|
||||
case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
|
||||
v := rv.Uint()
|
||||
offset = e.writeUint(v, offset)
|
||||
|
||||
case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
|
||||
v := rv.Int()
|
||||
offset = e.writeInt(v, offset)
|
||||
|
||||
case reflect.Float32:
|
||||
offset = e.writeFloat32(rv.Float(), offset)
|
||||
|
||||
case reflect.Float64:
|
||||
offset = e.writeFloat64(rv.Float(), offset)
|
||||
|
||||
case reflect.Bool:
|
||||
offset = e.writeBool(rv.Bool(), offset)
|
||||
|
||||
case reflect.String:
|
||||
offset = e.writeString(rv.String(), offset)
|
||||
|
||||
case reflect.Complex64:
|
||||
offset = e.writeComplex64(complex64(rv.Complex()), offset)
|
||||
|
||||
case reflect.Complex128:
|
||||
offset = e.writeComplex128(rv.Complex(), offset)
|
||||
|
||||
case reflect.Slice:
|
||||
if rv.IsNil() {
|
||||
return e.writeNil(offset)
|
||||
}
|
||||
|
||||
// bin format
|
||||
if e.isByteSlice(rv) {
|
||||
offset = e.writeByteSliceLength(rv.Len(), offset)
|
||||
offset = e.setBytes(rv.Bytes(), offset)
|
||||
return offset
|
||||
}
|
||||
|
||||
if offset, find := e.writeFixedSlice(rv, offset); find {
|
||||
return offset
|
||||
}
|
||||
|
||||
// func
|
||||
elem := rv.Type().Elem()
|
||||
var f structWriteFunc
|
||||
if elem.Kind() == reflect.Struct {
|
||||
f = e.getStructWriter(elem)
|
||||
} else {
|
||||
f = e.create
|
||||
}
|
||||
|
||||
// objects
|
||||
l := rv.Len()
|
||||
offset = e.writeSliceLength(l, offset)
|
||||
for i := 0; i < l; i++ {
|
||||
offset = f(rv.Index(i), offset)
|
||||
}
|
||||
|
||||
case reflect.Array:
|
||||
l := rv.Len()
|
||||
// bin format
|
||||
if e.isByteSlice(rv) {
|
||||
offset = e.writeByteSliceLength(l, offset)
|
||||
// objects
|
||||
for i := 0; i < l; i++ {
|
||||
offset = e.setByte1Uint64(rv.Index(i).Uint(), offset)
|
||||
}
|
||||
return offset
|
||||
}
|
||||
|
||||
// format
|
||||
offset = e.writeSliceLength(l, offset)
|
||||
|
||||
// func
|
||||
elem := rv.Type().Elem()
|
||||
var f structWriteFunc
|
||||
if elem.Kind() == reflect.Struct {
|
||||
f = e.getStructWriter(elem)
|
||||
} else {
|
||||
f = e.create
|
||||
}
|
||||
|
||||
// objects
|
||||
for i := 0; i < l; i++ {
|
||||
offset = f(rv.Index(i), offset)
|
||||
}
|
||||
|
||||
case reflect.Map:
|
||||
if rv.IsNil() {
|
||||
return e.writeNil(offset)
|
||||
}
|
||||
|
||||
l := rv.Len()
|
||||
offset = e.writeMapLength(l, offset)
|
||||
|
||||
if offset, find := e.writeFixedMap(rv, offset); find {
|
||||
return offset
|
||||
}
|
||||
|
||||
// key-value
|
||||
p := rv.Pointer()
|
||||
for i := range e.mk[p] {
|
||||
offset = e.create(e.mk[p][i], offset)
|
||||
offset = e.create(e.mv[p][i], offset)
|
||||
}
|
||||
|
||||
case reflect.Struct:
|
||||
offset = e.writeStruct(rv, offset)
|
||||
|
||||
case reflect.Ptr:
|
||||
if rv.IsNil() {
|
||||
return e.writeNil(offset)
|
||||
}
|
||||
|
||||
offset = e.create(rv.Elem(), offset)
|
||||
|
||||
case reflect.Interface:
|
||||
offset = e.create(rv.Elem(), offset)
|
||||
|
||||
case reflect.Invalid:
|
||||
return e.writeNil(offset)
|
||||
|
||||
}
|
||||
return offset
|
||||
}
|
||||
+97
@@ -0,0 +1,97 @@
|
||||
package encoding
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
|
||||
"github.com/shamaton/msgpack/v2/ext"
|
||||
"github.com/shamaton/msgpack/v2/time"
|
||||
)
|
||||
|
||||
var extCoderMap = map[reflect.Type]ext.Encoder{time.Encoder.Type(): time.Encoder}
|
||||
var extCoders = []ext.Encoder{time.Encoder}
|
||||
|
||||
// AddExtEncoder adds encoders for extension types.
|
||||
func AddExtEncoder(f ext.Encoder) {
|
||||
// ignore time
|
||||
if f.Type() == time.Encoder.Type() {
|
||||
return
|
||||
}
|
||||
|
||||
_, ok := extCoderMap[f.Type()]
|
||||
if !ok {
|
||||
extCoderMap[f.Type()] = f
|
||||
updateExtCoders()
|
||||
}
|
||||
}
|
||||
|
||||
// RemoveExtEncoder removes encoders for extension types.
|
||||
func RemoveExtEncoder(f ext.Encoder) {
|
||||
// ignore time
|
||||
if f.Type() == time.Encoder.Type() {
|
||||
return
|
||||
}
|
||||
|
||||
_, ok := extCoderMap[f.Type()]
|
||||
if ok {
|
||||
delete(extCoderMap, f.Type())
|
||||
updateExtCoders()
|
||||
}
|
||||
}
|
||||
|
||||
func updateExtCoders() {
|
||||
extCoders = make([]ext.Encoder, len(extCoderMap))
|
||||
i := 0
|
||||
for k := range extCoderMap {
|
||||
extCoders[i] = extCoderMap[k]
|
||||
i++
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
func (e *encoder) isDateTime(value reflect.Value) (bool, time.Time) {
|
||||
i := value.Interface()
|
||||
switch t := i.(type) {
|
||||
case time.Time:
|
||||
return true, t
|
||||
}
|
||||
return false, now
|
||||
}
|
||||
|
||||
func (e *encoder) calcTime(t time.Time) int {
|
||||
secs := uint64(t.Unix())
|
||||
if secs>>34 == 0 {
|
||||
data := uint64(t.Nanosecond())<<34 | secs
|
||||
if data&0xffffffff00000000 == 0 {
|
||||
return def.Byte1 + def.Byte4
|
||||
}
|
||||
return def.Byte1 + def.Byte8
|
||||
}
|
||||
|
||||
return def.Byte1 + def.Byte1 + def.Byte4 + def.Byte8
|
||||
}
|
||||
|
||||
func (e *encoder) writeTime(t time.Time, offset int) int {
|
||||
secs := uint64(t.Unix())
|
||||
if secs>>34 == 0 {
|
||||
data := uint64(t.Nanosecond())<<34 | secs
|
||||
if data&0xffffffff00000000 == 0 {
|
||||
offset = e.setByte1Int(def.Fixext4, offset)
|
||||
offset = e.setByte1Int(def.TimeStamp, offset)
|
||||
offset = e.setByte4Uint64(data, offset)
|
||||
return offset
|
||||
}
|
||||
|
||||
offset = e.setByte1Int(def.Fixext8, offset)
|
||||
offset = e.setByte1Int(def.TimeStamp, offset)
|
||||
offset = e.setByte8Uint64(data, offset)
|
||||
return offset
|
||||
}
|
||||
|
||||
offset = e.setByte1Int(def.Ext8, offset)
|
||||
offset = e.setByte1Int(12, offset)
|
||||
offset = e.setByte1Int(def.TimeStamp, offset)
|
||||
offset = e.setByte4Int(t.Nanosecond(), offset)
|
||||
offset = e.setByte8Uint64(secs, offset)
|
||||
return offset
|
||||
}
|
||||
*/
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
package encoding
|
||||
|
||||
import (
|
||||
"math"
|
||||
|
||||
"github.com/shamaton/msgpack/v2/def"
|
||||
)
|
||||
|
||||
func (e *encoder) calcFloat32(_ float64) int {
|
||||
return def.Byte1 + def.Byte4
|
||||
}
|
||||
|
||||
func (e *encoder) calcFloat64(_ float64) int {
|
||||
return def.Byte1 + def.Byte8
|
||||
}
|
||||
|
||||
func (e *encoder) writeFloat32(v float64, offset int) int {
|
||||
offset = e.setByte1Int(def.Float32, offset)
|
||||
offset = e.setByte4Uint64(uint64(math.Float32bits(float32(v))), offset)
|
||||
return offset
|
||||
}
|
||||
|
||||
func (e *encoder) writeFloat64(v float64, offset int) int {
|
||||
offset = e.setByte1Int(def.Float64, offset)
|
||||
offset = e.setByte8Uint64(math.Float64bits(v), offset)
|
||||
return offset
|
||||
}
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
package encoding
|
||||
|
||||
import (
|
||||
"math"
|
||||
|
||||
"github.com/shamaton/msgpack/v2/def"
|
||||
)
|
||||
|
||||
func (e *encoder) isNegativeFixInt64(v int64) bool {
|
||||
return def.NegativeFixintMin <= v && v <= def.NegativeFixintMax
|
||||
}
|
||||
|
||||
func (e *encoder) calcInt(v int64) int {
|
||||
if v >= 0 {
|
||||
return e.calcUint(uint64(v))
|
||||
} else if e.isNegativeFixInt64(v) {
|
||||
// format code only
|
||||
return def.Byte1
|
||||
} else if v >= math.MinInt8 {
|
||||
return def.Byte1 + def.Byte1
|
||||
} else if v >= math.MinInt16 {
|
||||
return def.Byte1 + def.Byte2
|
||||
} else if v >= math.MinInt32 {
|
||||
return def.Byte1 + def.Byte4
|
||||
}
|
||||
return def.Byte1 + def.Byte8
|
||||
}
|
||||
|
||||
func (e *encoder) writeInt(v int64, offset int) int {
|
||||
if v >= 0 {
|
||||
offset = e.writeUint(uint64(v), offset)
|
||||
} else if e.isNegativeFixInt64(v) {
|
||||
offset = e.setByte1Int64(v, offset)
|
||||
} else if v >= math.MinInt8 {
|
||||
offset = e.setByte1Int(def.Int8, offset)
|
||||
offset = e.setByte1Int64(v, offset)
|
||||
} else if v >= math.MinInt16 {
|
||||
offset = e.setByte1Int(def.Int16, offset)
|
||||
offset = e.setByte2Int64(v, offset)
|
||||
} else if v >= math.MinInt32 {
|
||||
offset = e.setByte1Int(def.Int32, offset)
|
||||
offset = e.setByte4Int64(v, offset)
|
||||
} else {
|
||||
offset = e.setByte1Int(def.Int64, offset)
|
||||
offset = e.setByte8Int64(v, offset)
|
||||
}
|
||||
return offset
|
||||
}
|
||||
+559
@@ -0,0 +1,559 @@
|
||||
package encoding
|
||||
|
||||
import (
|
||||
"math"
|
||||
"reflect"
|
||||
|
||||
"github.com/shamaton/msgpack/v2/def"
|
||||
)
|
||||
|
||||
func (e *encoder) calcFixedMap(rv reflect.Value) (int, bool) {
|
||||
// calcLength formally returns (int, error), but for map lengths in Go
|
||||
// the error case is unreachable. The error value is always nil and is
|
||||
// intentionally ignored with `_`.
|
||||
switch m := rv.Interface().(type) {
|
||||
case map[string]int:
|
||||
size, _ := e.calcLength(len(m))
|
||||
for k, v := range m {
|
||||
size += e.calcString(k)
|
||||
size += e.calcInt(int64(v))
|
||||
}
|
||||
return size, true
|
||||
|
||||
case map[string]uint:
|
||||
size, _ := e.calcLength(len(m))
|
||||
for k, v := range m {
|
||||
size += e.calcString(k)
|
||||
size += e.calcUint(uint64(v))
|
||||
}
|
||||
return size, true
|
||||
|
||||
case map[string]string:
|
||||
size, _ := e.calcLength(len(m))
|
||||
for k, v := range m {
|
||||
size += e.calcString(k)
|
||||
size += e.calcString(v)
|
||||
}
|
||||
return size, true
|
||||
|
||||
case map[string]float32:
|
||||
size, _ := e.calcLength(len(m))
|
||||
for k := range m {
|
||||
size += e.calcString(k)
|
||||
size += e.calcFloat32(0)
|
||||
}
|
||||
return size, true
|
||||
|
||||
case map[string]float64:
|
||||
size, _ := e.calcLength(len(m))
|
||||
for k := range m {
|
||||
size += e.calcString(k)
|
||||
size += e.calcFloat64(0)
|
||||
}
|
||||
return size, true
|
||||
|
||||
case map[string]bool:
|
||||
size, _ := e.calcLength(len(m))
|
||||
for k := range m {
|
||||
size += e.calcString(k)
|
||||
size += def.Byte1 /*+ e.calcBool()*/
|
||||
}
|
||||
return size, true
|
||||
|
||||
case map[string]int8:
|
||||
size, _ := e.calcLength(len(m))
|
||||
for k, v := range m {
|
||||
size += e.calcString(k)
|
||||
size += e.calcInt(int64(v))
|
||||
}
|
||||
return size, true
|
||||
case map[string]int16:
|
||||
size, _ := e.calcLength(len(m))
|
||||
for k, v := range m {
|
||||
size += e.calcString(k)
|
||||
size += e.calcInt(int64(v))
|
||||
}
|
||||
return size, true
|
||||
case map[string]int32:
|
||||
size, _ := e.calcLength(len(m))
|
||||
for k, v := range m {
|
||||
size += e.calcString(k)
|
||||
size += e.calcInt(int64(v))
|
||||
}
|
||||
return size, true
|
||||
case map[string]int64:
|
||||
size, _ := e.calcLength(len(m))
|
||||
for k, v := range m {
|
||||
size += e.calcString(k)
|
||||
size += e.calcInt(v)
|
||||
}
|
||||
return size, true
|
||||
case map[string]uint8:
|
||||
size, _ := e.calcLength(len(m))
|
||||
for k, v := range m {
|
||||
size += e.calcString(k)
|
||||
size += e.calcUint(uint64(v))
|
||||
}
|
||||
return size, true
|
||||
case map[string]uint16:
|
||||
size, _ := e.calcLength(len(m))
|
||||
for k, v := range m {
|
||||
size += e.calcString(k)
|
||||
size += e.calcUint(uint64(v))
|
||||
}
|
||||
return size, true
|
||||
case map[string]uint32:
|
||||
size, _ := e.calcLength(len(m))
|
||||
for k, v := range m {
|
||||
size += e.calcString(k)
|
||||
size += e.calcUint(uint64(v))
|
||||
}
|
||||
return size, true
|
||||
case map[string]uint64:
|
||||
size, _ := e.calcLength(len(m))
|
||||
for k, v := range m {
|
||||
size += e.calcString(k)
|
||||
size += e.calcUint(v)
|
||||
}
|
||||
return size, true
|
||||
|
||||
case map[int]string:
|
||||
size, _ := e.calcLength(len(m))
|
||||
for k, v := range m {
|
||||
size += e.calcInt(int64(k))
|
||||
size += e.calcString(v)
|
||||
}
|
||||
return size, true
|
||||
case map[int]bool:
|
||||
size, _ := e.calcLength(len(m))
|
||||
for k := range m {
|
||||
size += e.calcInt(int64(k))
|
||||
size += def.Byte1 /* + e.calcBool()*/
|
||||
}
|
||||
return size, true
|
||||
|
||||
case map[uint]string:
|
||||
size, _ := e.calcLength(len(m))
|
||||
for k, v := range m {
|
||||
size += e.calcUint(uint64(k))
|
||||
size += e.calcString(v)
|
||||
}
|
||||
return size, true
|
||||
case map[uint]bool:
|
||||
size, _ := e.calcLength(len(m))
|
||||
for k := range m {
|
||||
size += e.calcUint(uint64(k))
|
||||
size += def.Byte1 /* + e.calcBool()*/
|
||||
}
|
||||
return size, true
|
||||
|
||||
case map[float32]string:
|
||||
size, _ := e.calcLength(len(m))
|
||||
for k, v := range m {
|
||||
size += e.calcFloat32(float64(k))
|
||||
size += e.calcString(v)
|
||||
}
|
||||
return size, true
|
||||
case map[float32]bool:
|
||||
size, _ := e.calcLength(len(m))
|
||||
for k := range m {
|
||||
size += e.calcFloat32(float64(k))
|
||||
size += def.Byte1 /* + e.calcBool()*/
|
||||
}
|
||||
return size, true
|
||||
|
||||
case map[float64]string:
|
||||
size, _ := e.calcLength(len(m))
|
||||
for k, v := range m {
|
||||
size += e.calcFloat64(k)
|
||||
size += e.calcString(v)
|
||||
}
|
||||
return size, true
|
||||
case map[float64]bool:
|
||||
size, _ := e.calcLength(len(m))
|
||||
for k := range m {
|
||||
size += e.calcFloat64(k)
|
||||
size += def.Byte1 /* + e.calcBool()*/
|
||||
}
|
||||
return size, true
|
||||
|
||||
case map[int8]string:
|
||||
size, _ := e.calcLength(len(m))
|
||||
for k, v := range m {
|
||||
size += e.calcInt(int64(k))
|
||||
size += e.calcString(v)
|
||||
}
|
||||
return size, true
|
||||
case map[int8]bool:
|
||||
size, _ := e.calcLength(len(m))
|
||||
for k := range m {
|
||||
size += e.calcInt(int64(k))
|
||||
size += def.Byte1 /* + e.calcBool()*/
|
||||
}
|
||||
return size, true
|
||||
case map[int16]string:
|
||||
size, _ := e.calcLength(len(m))
|
||||
for k, v := range m {
|
||||
size += e.calcInt(int64(k))
|
||||
size += e.calcString(v)
|
||||
}
|
||||
return size, true
|
||||
case map[int16]bool:
|
||||
size, _ := e.calcLength(len(m))
|
||||
for k := range m {
|
||||
size += e.calcInt(int64(k))
|
||||
size += def.Byte1 /* + e.calcBool()*/
|
||||
}
|
||||
return size, true
|
||||
case map[int32]string:
|
||||
size, _ := e.calcLength(len(m))
|
||||
for k, v := range m {
|
||||
size += e.calcInt(int64(k))
|
||||
size += e.calcString(v)
|
||||
}
|
||||
return size, true
|
||||
case map[int32]bool:
|
||||
size, _ := e.calcLength(len(m))
|
||||
for k := range m {
|
||||
size += e.calcInt(int64(k))
|
||||
size += def.Byte1 /* + e.calcBool()*/
|
||||
}
|
||||
return size, true
|
||||
case map[int64]string:
|
||||
size, _ := e.calcLength(len(m))
|
||||
for k, v := range m {
|
||||
size += e.calcInt(k)
|
||||
size += e.calcString(v)
|
||||
}
|
||||
return size, true
|
||||
case map[int64]bool:
|
||||
size, _ := e.calcLength(len(m))
|
||||
for k := range m {
|
||||
size += e.calcInt(k)
|
||||
size += def.Byte1 /* + e.calcBool()*/
|
||||
}
|
||||
return size, true
|
||||
|
||||
case map[uint8]string:
|
||||
size, _ := e.calcLength(len(m))
|
||||
for k, v := range m {
|
||||
size += e.calcUint(uint64(k))
|
||||
size += e.calcString(v)
|
||||
}
|
||||
return size, true
|
||||
case map[uint8]bool:
|
||||
size, _ := e.calcLength(len(m))
|
||||
for k := range m {
|
||||
size += e.calcUint(uint64(k))
|
||||
size += def.Byte1 /* + e.calcBool()*/
|
||||
}
|
||||
return size, true
|
||||
case map[uint16]string:
|
||||
size, _ := e.calcLength(len(m))
|
||||
for k, v := range m {
|
||||
size += e.calcUint(uint64(k))
|
||||
size += e.calcString(v)
|
||||
}
|
||||
return size, true
|
||||
case map[uint16]bool:
|
||||
size, _ := e.calcLength(len(m))
|
||||
for k := range m {
|
||||
size += e.calcUint(uint64(k))
|
||||
size += def.Byte1 /* + e.calcBool()*/
|
||||
}
|
||||
return size, true
|
||||
case map[uint32]string:
|
||||
size, _ := e.calcLength(len(m))
|
||||
for k, v := range m {
|
||||
size += e.calcUint(uint64(k))
|
||||
size += e.calcString(v)
|
||||
}
|
||||
return size, true
|
||||
case map[uint32]bool:
|
||||
size, _ := e.calcLength(len(m))
|
||||
for k := range m {
|
||||
size += e.calcUint(uint64(k))
|
||||
size += def.Byte1 /* + e.calcBool()*/
|
||||
}
|
||||
return size, true
|
||||
case map[uint64]string:
|
||||
size, _ := e.calcLength(len(m))
|
||||
for k, v := range m {
|
||||
size += e.calcUint(k)
|
||||
size += e.calcString(v)
|
||||
}
|
||||
return size, true
|
||||
case map[uint64]bool:
|
||||
size, _ := e.calcLength(len(m))
|
||||
for k := range m {
|
||||
size += e.calcUint(k)
|
||||
size += def.Byte1 /* + e.calcBool()*/
|
||||
}
|
||||
return size, true
|
||||
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
|
||||
func (e *encoder) writeMapLength(l int, offset int) int {
|
||||
|
||||
// format
|
||||
if l <= 0x0f {
|
||||
offset = e.setByte1Int(def.FixMap+l, offset)
|
||||
} else if l <= math.MaxUint16 {
|
||||
offset = e.setByte1Int(def.Map16, offset)
|
||||
offset = e.setByte2Int(l, offset)
|
||||
} else if uint(l) <= math.MaxUint32 {
|
||||
offset = e.setByte1Int(def.Map32, offset)
|
||||
offset = e.setByte4Int(l, offset)
|
||||
}
|
||||
return offset
|
||||
}
|
||||
|
||||
func (e *encoder) writeFixedMap(rv reflect.Value, offset int) (int, bool) {
|
||||
switch m := rv.Interface().(type) {
|
||||
case map[string]int:
|
||||
for k, v := range m {
|
||||
offset = e.writeString(k, offset)
|
||||
offset = e.writeInt(int64(v), offset)
|
||||
}
|
||||
return offset, true
|
||||
|
||||
case map[string]uint:
|
||||
for k, v := range m {
|
||||
offset = e.writeString(k, offset)
|
||||
offset = e.writeUint(uint64(v), offset)
|
||||
}
|
||||
return offset, true
|
||||
|
||||
case map[string]float32:
|
||||
for k, v := range m {
|
||||
offset = e.writeString(k, offset)
|
||||
offset = e.writeFloat32(float64(v), offset)
|
||||
}
|
||||
return offset, true
|
||||
|
||||
case map[string]float64:
|
||||
for k, v := range m {
|
||||
offset = e.writeString(k, offset)
|
||||
offset = e.writeFloat64(v, offset)
|
||||
}
|
||||
return offset, true
|
||||
|
||||
case map[string]bool:
|
||||
for k, v := range m {
|
||||
offset = e.writeString(k, offset)
|
||||
offset = e.writeBool(v, offset)
|
||||
}
|
||||
return offset, true
|
||||
|
||||
case map[string]string:
|
||||
for k, v := range m {
|
||||
offset = e.writeString(k, offset)
|
||||
offset = e.writeString(v, offset)
|
||||
}
|
||||
return offset, true
|
||||
|
||||
case map[string]int8:
|
||||
for k, v := range m {
|
||||
offset = e.writeString(k, offset)
|
||||
offset = e.writeInt(int64(v), offset)
|
||||
}
|
||||
return offset, true
|
||||
case map[string]int16:
|
||||
for k, v := range m {
|
||||
offset = e.writeString(k, offset)
|
||||
offset = e.writeInt(int64(v), offset)
|
||||
}
|
||||
return offset, true
|
||||
case map[string]int32:
|
||||
for k, v := range m {
|
||||
offset = e.writeString(k, offset)
|
||||
offset = e.writeInt(int64(v), offset)
|
||||
}
|
||||
return offset, true
|
||||
case map[string]int64:
|
||||
for k, v := range m {
|
||||
offset = e.writeString(k, offset)
|
||||
offset = e.writeInt(int64(v), offset)
|
||||
}
|
||||
return offset, true
|
||||
|
||||
case map[string]uint8:
|
||||
for k, v := range m {
|
||||
offset = e.writeString(k, offset)
|
||||
offset = e.writeUint(uint64(v), offset)
|
||||
}
|
||||
return offset, true
|
||||
case map[string]uint16:
|
||||
for k, v := range m {
|
||||
offset = e.writeString(k, offset)
|
||||
offset = e.writeUint(uint64(v), offset)
|
||||
}
|
||||
return offset, true
|
||||
case map[string]uint32:
|
||||
for k, v := range m {
|
||||
offset = e.writeString(k, offset)
|
||||
offset = e.writeUint(uint64(v), offset)
|
||||
}
|
||||
return offset, true
|
||||
case map[string]uint64:
|
||||
for k, v := range m {
|
||||
offset = e.writeString(k, offset)
|
||||
offset = e.writeUint(uint64(v), offset)
|
||||
}
|
||||
return offset, true
|
||||
|
||||
case map[int]string:
|
||||
for k, v := range m {
|
||||
offset = e.writeInt(int64(k), offset)
|
||||
offset = e.writeString(v, offset)
|
||||
}
|
||||
return offset, true
|
||||
case map[int]bool:
|
||||
for k, v := range m {
|
||||
offset = e.writeInt(int64(k), offset)
|
||||
offset = e.writeBool(v, offset)
|
||||
}
|
||||
return offset, true
|
||||
|
||||
case map[uint]string:
|
||||
for k, v := range m {
|
||||
offset = e.writeUint(uint64(k), offset)
|
||||
offset = e.writeString(v, offset)
|
||||
}
|
||||
return offset, true
|
||||
case map[uint]bool:
|
||||
for k, v := range m {
|
||||
offset = e.writeUint(uint64(k), offset)
|
||||
offset = e.writeBool(v, offset)
|
||||
}
|
||||
return offset, true
|
||||
|
||||
case map[float32]string:
|
||||
for k, v := range m {
|
||||
offset = e.writeFloat32(float64(k), offset)
|
||||
offset = e.writeString(v, offset)
|
||||
}
|
||||
return offset, true
|
||||
case map[float32]bool:
|
||||
for k, v := range m {
|
||||
offset = e.writeFloat32(float64(k), offset)
|
||||
offset = e.writeBool(v, offset)
|
||||
}
|
||||
return offset, true
|
||||
|
||||
case map[float64]string:
|
||||
for k, v := range m {
|
||||
offset = e.writeFloat64(k, offset)
|
||||
offset = e.writeString(v, offset)
|
||||
}
|
||||
return offset, true
|
||||
case map[float64]bool:
|
||||
for k, v := range m {
|
||||
offset = e.writeFloat64(k, offset)
|
||||
offset = e.writeBool(v, offset)
|
||||
}
|
||||
return offset, true
|
||||
|
||||
case map[int8]string:
|
||||
for k, v := range m {
|
||||
offset = e.writeInt(int64(k), offset)
|
||||
offset = e.writeString(v, offset)
|
||||
}
|
||||
return offset, true
|
||||
case map[int8]bool:
|
||||
for k, v := range m {
|
||||
offset = e.writeInt(int64(k), offset)
|
||||
offset = e.writeBool(v, offset)
|
||||
}
|
||||
return offset, true
|
||||
case map[int16]string:
|
||||
for k, v := range m {
|
||||
offset = e.writeInt(int64(k), offset)
|
||||
offset = e.writeString(v, offset)
|
||||
}
|
||||
return offset, true
|
||||
case map[int16]bool:
|
||||
for k, v := range m {
|
||||
offset = e.writeInt(int64(k), offset)
|
||||
offset = e.writeBool(v, offset)
|
||||
}
|
||||
return offset, true
|
||||
case map[int32]string:
|
||||
for k, v := range m {
|
||||
offset = e.writeInt(int64(k), offset)
|
||||
offset = e.writeString(v, offset)
|
||||
}
|
||||
return offset, true
|
||||
case map[int32]bool:
|
||||
for k, v := range m {
|
||||
offset = e.writeInt(int64(k), offset)
|
||||
offset = e.writeBool(v, offset)
|
||||
}
|
||||
return offset, true
|
||||
case map[int64]string:
|
||||
for k, v := range m {
|
||||
offset = e.writeInt(k, offset)
|
||||
offset = e.writeString(v, offset)
|
||||
}
|
||||
return offset, true
|
||||
case map[int64]bool:
|
||||
for k, v := range m {
|
||||
offset = e.writeInt(k, offset)
|
||||
offset = e.writeBool(v, offset)
|
||||
}
|
||||
return offset, true
|
||||
|
||||
case map[uint8]string:
|
||||
for k, v := range m {
|
||||
offset = e.writeUint(uint64(k), offset)
|
||||
offset = e.writeString(v, offset)
|
||||
}
|
||||
return offset, true
|
||||
case map[uint8]bool:
|
||||
for k, v := range m {
|
||||
offset = e.writeUint(uint64(k), offset)
|
||||
offset = e.writeBool(v, offset)
|
||||
}
|
||||
return offset, true
|
||||
case map[uint16]string:
|
||||
for k, v := range m {
|
||||
offset = e.writeUint(uint64(k), offset)
|
||||
offset = e.writeString(v, offset)
|
||||
}
|
||||
return offset, true
|
||||
case map[uint16]bool:
|
||||
for k, v := range m {
|
||||
offset = e.writeUint(uint64(k), offset)
|
||||
offset = e.writeBool(v, offset)
|
||||
}
|
||||
return offset, true
|
||||
case map[uint32]string:
|
||||
for k, v := range m {
|
||||
offset = e.writeUint(uint64(k), offset)
|
||||
offset = e.writeString(v, offset)
|
||||
}
|
||||
return offset, true
|
||||
case map[uint32]bool:
|
||||
for k, v := range m {
|
||||
offset = e.writeUint(uint64(k), offset)
|
||||
offset = e.writeBool(v, offset)
|
||||
}
|
||||
return offset, true
|
||||
case map[uint64]string:
|
||||
for k, v := range m {
|
||||
offset = e.writeUint(k, offset)
|
||||
offset = e.writeString(v, offset)
|
||||
}
|
||||
return offset, true
|
||||
case map[uint64]bool:
|
||||
for k, v := range m {
|
||||
offset = e.writeUint(k, offset)
|
||||
offset = e.writeBool(v, offset)
|
||||
}
|
||||
return offset, true
|
||||
|
||||
}
|
||||
return offset, false
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
package encoding
|
||||
|
||||
import "github.com/shamaton/msgpack/v2/def"
|
||||
|
||||
func (e *encoder) writeNil(offset int) int {
|
||||
offset = e.setByte1Int(def.Nil, offset)
|
||||
return offset
|
||||
}
|
||||
+89
@@ -0,0 +1,89 @@
|
||||
package encoding
|
||||
|
||||
func (e *encoder) setByte1Int64(value int64, offset int) int {
|
||||
e.d[offset] = byte(value)
|
||||
return offset + 1
|
||||
}
|
||||
|
||||
func (e *encoder) setByte2Int64(value int64, offset int) int {
|
||||
e.d[offset+0] = byte(value >> 8)
|
||||
e.d[offset+1] = byte(value)
|
||||
return offset + 2
|
||||
}
|
||||
|
||||
func (e *encoder) setByte4Int64(value int64, offset int) int {
|
||||
e.d[offset+0] = byte(value >> 24)
|
||||
e.d[offset+1] = byte(value >> 16)
|
||||
e.d[offset+2] = byte(value >> 8)
|
||||
e.d[offset+3] = byte(value)
|
||||
return offset + 4
|
||||
}
|
||||
|
||||
func (e *encoder) setByte8Int64(value int64, offset int) int {
|
||||
e.d[offset] = byte(value >> 56)
|
||||
e.d[offset+1] = byte(value >> 48)
|
||||
e.d[offset+2] = byte(value >> 40)
|
||||
e.d[offset+3] = byte(value >> 32)
|
||||
e.d[offset+4] = byte(value >> 24)
|
||||
e.d[offset+5] = byte(value >> 16)
|
||||
e.d[offset+6] = byte(value >> 8)
|
||||
e.d[offset+7] = byte(value)
|
||||
return offset + 8
|
||||
}
|
||||
|
||||
func (e *encoder) setByte1Uint64(value uint64, offset int) int {
|
||||
e.d[offset] = byte(value)
|
||||
return offset + 1
|
||||
}
|
||||
|
||||
func (e *encoder) setByte2Uint64(value uint64, offset int) int {
|
||||
e.d[offset] = byte(value >> 8)
|
||||
e.d[offset+1] = byte(value)
|
||||
return offset + 2
|
||||
}
|
||||
|
||||
func (e *encoder) setByte4Uint64(value uint64, offset int) int {
|
||||
e.d[offset] = byte(value >> 24)
|
||||
e.d[offset+1] = byte(value >> 16)
|
||||
e.d[offset+2] = byte(value >> 8)
|
||||
e.d[offset+3] = byte(value)
|
||||
return offset + 4
|
||||
}
|
||||
|
||||
func (e *encoder) setByte8Uint64(value uint64, offset int) int {
|
||||
e.d[offset] = byte(value >> 56)
|
||||
e.d[offset+1] = byte(value >> 48)
|
||||
e.d[offset+2] = byte(value >> 40)
|
||||
e.d[offset+3] = byte(value >> 32)
|
||||
e.d[offset+4] = byte(value >> 24)
|
||||
e.d[offset+5] = byte(value >> 16)
|
||||
e.d[offset+6] = byte(value >> 8)
|
||||
e.d[offset+7] = byte(value)
|
||||
return offset + 8
|
||||
}
|
||||
|
||||
func (e *encoder) setByte1Int(code, offset int) int {
|
||||
e.d[offset] = byte(code)
|
||||
return offset + 1
|
||||
}
|
||||
|
||||
func (e *encoder) setByte2Int(value int, offset int) int {
|
||||
e.d[offset] = byte(value >> 8)
|
||||
e.d[offset+1] = byte(value)
|
||||
return offset + 2
|
||||
}
|
||||
|
||||
func (e *encoder) setByte4Int(value int, offset int) int {
|
||||
e.d[offset] = byte(value >> 24)
|
||||
e.d[offset+1] = byte(value >> 16)
|
||||
e.d[offset+2] = byte(value >> 8)
|
||||
e.d[offset+3] = byte(value)
|
||||
return offset + 4
|
||||
}
|
||||
|
||||
func (e *encoder) setBytes(bs []byte, offset int) int {
|
||||
for i := range bs {
|
||||
e.d[offset+i] = bs[i]
|
||||
}
|
||||
return offset + len(bs)
|
||||
}
|
||||
+232
@@ -0,0 +1,232 @@
|
||||
package encoding
|
||||
|
||||
import (
|
||||
"math"
|
||||
"reflect"
|
||||
|
||||
"github.com/shamaton/msgpack/v2/def"
|
||||
)
|
||||
|
||||
func (e *encoder) calcFixedSlice(rv reflect.Value) (int, bool) {
|
||||
// calcLength formally returns (int, error), but for map lengths in Go
|
||||
// the error case is unreachable. The error value is always nil and is
|
||||
// intentionally ignored with `_`.
|
||||
switch sli := rv.Interface().(type) {
|
||||
case []int:
|
||||
size, _ := e.calcLength(len(sli))
|
||||
for _, v := range sli {
|
||||
size += e.calcInt(int64(v))
|
||||
}
|
||||
return size, true
|
||||
|
||||
case []uint:
|
||||
size, _ := e.calcLength(len(sli))
|
||||
for _, v := range sli {
|
||||
size += e.calcUint(uint64(v))
|
||||
}
|
||||
return size, true
|
||||
|
||||
case []string:
|
||||
size, _ := e.calcLength(len(sli))
|
||||
for _, v := range sli {
|
||||
size += e.calcString(v)
|
||||
}
|
||||
return size, true
|
||||
|
||||
case []float32:
|
||||
size, _ := e.calcLength(len(sli))
|
||||
for _, v := range sli {
|
||||
size += e.calcFloat32(float64(v))
|
||||
}
|
||||
return size, true
|
||||
|
||||
case []float64:
|
||||
size, _ := e.calcLength(len(sli))
|
||||
for _, v := range sli {
|
||||
size += e.calcFloat64(v)
|
||||
}
|
||||
return size, true
|
||||
|
||||
case []bool:
|
||||
size, _ := e.calcLength(len(sli))
|
||||
size += def.Byte1 * len(sli)
|
||||
return size, true
|
||||
|
||||
case []int8:
|
||||
size, _ := e.calcLength(len(sli))
|
||||
for _, v := range sli {
|
||||
size += e.calcInt(int64(v))
|
||||
}
|
||||
return size, true
|
||||
|
||||
case []int16:
|
||||
size, _ := e.calcLength(len(sli))
|
||||
for _, v := range sli {
|
||||
size += e.calcInt(int64(v))
|
||||
}
|
||||
return size, true
|
||||
|
||||
case []int32:
|
||||
size, _ := e.calcLength(len(sli))
|
||||
for _, v := range sli {
|
||||
size += e.calcInt(int64(v))
|
||||
}
|
||||
return size, true
|
||||
|
||||
case []int64:
|
||||
size, _ := e.calcLength(len(sli))
|
||||
for _, v := range sli {
|
||||
size += e.calcInt(v)
|
||||
}
|
||||
return size, true
|
||||
|
||||
case []uint8:
|
||||
size, _ := e.calcLength(len(sli))
|
||||
for _, v := range sli {
|
||||
size += e.calcUint(uint64(v))
|
||||
}
|
||||
return size, true
|
||||
|
||||
case []uint16:
|
||||
size, _ := e.calcLength(len(sli))
|
||||
for _, v := range sli {
|
||||
size += e.calcUint(uint64(v))
|
||||
}
|
||||
return size, true
|
||||
|
||||
case []uint32:
|
||||
size, _ := e.calcLength(len(sli))
|
||||
for _, v := range sli {
|
||||
size += e.calcUint(uint64(v))
|
||||
}
|
||||
return size, true
|
||||
|
||||
case []uint64:
|
||||
size, _ := e.calcLength(len(sli))
|
||||
for _, v := range sli {
|
||||
size += e.calcUint(v)
|
||||
}
|
||||
return size, true
|
||||
}
|
||||
|
||||
return 0, false
|
||||
}
|
||||
|
||||
func (e *encoder) writeSliceLength(l int, offset int) int {
|
||||
// format size
|
||||
if l <= 0x0f {
|
||||
offset = e.setByte1Int(def.FixArray+l, offset)
|
||||
} else if l <= math.MaxUint16 {
|
||||
offset = e.setByte1Int(def.Array16, offset)
|
||||
offset = e.setByte2Int(l, offset)
|
||||
} else if uint(l) <= math.MaxUint32 {
|
||||
offset = e.setByte1Int(def.Array32, offset)
|
||||
offset = e.setByte4Int(l, offset)
|
||||
}
|
||||
return offset
|
||||
}
|
||||
|
||||
func (e *encoder) writeFixedSlice(rv reflect.Value, offset int) (int, bool) {
|
||||
|
||||
switch sli := rv.Interface().(type) {
|
||||
case []int:
|
||||
offset = e.writeSliceLength(len(sli), offset)
|
||||
for _, v := range sli {
|
||||
offset = e.writeInt(int64(v), offset)
|
||||
}
|
||||
return offset, true
|
||||
|
||||
case []uint:
|
||||
offset = e.writeSliceLength(len(sli), offset)
|
||||
for _, v := range sli {
|
||||
offset = e.writeUint(uint64(v), offset)
|
||||
}
|
||||
return offset, true
|
||||
|
||||
case []string:
|
||||
offset = e.writeSliceLength(len(sli), offset)
|
||||
for _, v := range sli {
|
||||
offset = e.writeString(v, offset)
|
||||
}
|
||||
return offset, true
|
||||
|
||||
case []float32:
|
||||
offset = e.writeSliceLength(len(sli), offset)
|
||||
for _, v := range sli {
|
||||
offset = e.writeFloat32(float64(v), offset)
|
||||
}
|
||||
return offset, true
|
||||
|
||||
case []float64:
|
||||
offset = e.writeSliceLength(len(sli), offset)
|
||||
for _, v := range sli {
|
||||
offset = e.writeFloat64(float64(v), offset)
|
||||
}
|
||||
return offset, true
|
||||
|
||||
case []bool:
|
||||
offset = e.writeSliceLength(len(sli), offset)
|
||||
for _, v := range sli {
|
||||
offset = e.writeBool(v, offset)
|
||||
}
|
||||
return offset, true
|
||||
|
||||
case []int8:
|
||||
offset = e.writeSliceLength(len(sli), offset)
|
||||
for _, v := range sli {
|
||||
offset = e.writeInt(int64(v), offset)
|
||||
}
|
||||
return offset, true
|
||||
|
||||
case []int16:
|
||||
offset = e.writeSliceLength(len(sli), offset)
|
||||
for _, v := range sli {
|
||||
offset = e.writeInt(int64(v), offset)
|
||||
}
|
||||
return offset, true
|
||||
|
||||
case []int32:
|
||||
offset = e.writeSliceLength(len(sli), offset)
|
||||
for _, v := range sli {
|
||||
offset = e.writeInt(int64(v), offset)
|
||||
}
|
||||
return offset, true
|
||||
|
||||
case []int64:
|
||||
offset = e.writeSliceLength(len(sli), offset)
|
||||
for _, v := range sli {
|
||||
offset = e.writeInt(v, offset)
|
||||
}
|
||||
return offset, true
|
||||
|
||||
case []uint8:
|
||||
offset = e.writeSliceLength(len(sli), offset)
|
||||
for _, v := range sli {
|
||||
offset = e.writeUint(uint64(v), offset)
|
||||
}
|
||||
return offset, true
|
||||
|
||||
case []uint16:
|
||||
offset = e.writeSliceLength(len(sli), offset)
|
||||
for _, v := range sli {
|
||||
offset = e.writeUint(uint64(v), offset)
|
||||
}
|
||||
return offset, true
|
||||
|
||||
case []uint32:
|
||||
offset = e.writeSliceLength(len(sli), offset)
|
||||
for _, v := range sli {
|
||||
offset = e.writeUint(uint64(v), offset)
|
||||
}
|
||||
return offset, true
|
||||
|
||||
case []uint64:
|
||||
offset = e.writeSliceLength(len(sli), offset)
|
||||
for _, v := range sli {
|
||||
offset = e.writeUint(v, offset)
|
||||
}
|
||||
return offset, true
|
||||
}
|
||||
|
||||
return offset, false
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
package encoding
|
||||
|
||||
import (
|
||||
"math"
|
||||
"unsafe"
|
||||
|
||||
"github.com/shamaton/msgpack/v2/def"
|
||||
)
|
||||
|
||||
func (e *encoder) calcString(v string) int {
|
||||
// NOTE : unsafe
|
||||
strBytes := *(*[]byte)(unsafe.Pointer(&v))
|
||||
l := len(strBytes)
|
||||
if l < 32 {
|
||||
return def.Byte1 + l
|
||||
} else if l <= math.MaxUint8 {
|
||||
return def.Byte1 + def.Byte1 + l
|
||||
} else if l <= math.MaxUint16 {
|
||||
return def.Byte1 + def.Byte2 + l
|
||||
}
|
||||
return def.Byte1 + def.Byte4 + l
|
||||
// NOTE : length over uint32
|
||||
}
|
||||
|
||||
func (e *encoder) writeString(str string, offset int) int {
|
||||
// NOTE : unsafe
|
||||
strBytes := *(*[]byte)(unsafe.Pointer(&str))
|
||||
l := len(strBytes)
|
||||
if l < 32 {
|
||||
offset = e.setByte1Int(def.FixStr+l, offset)
|
||||
} else if l <= math.MaxUint8 {
|
||||
offset = e.setByte1Int(def.Str8, offset)
|
||||
offset = e.setByte1Int(l, offset)
|
||||
} else if l <= math.MaxUint16 {
|
||||
offset = e.setByte1Int(def.Str16, offset)
|
||||
offset = e.setByte2Int(l, offset)
|
||||
} else {
|
||||
offset = e.setByte1Int(def.Str32, offset)
|
||||
offset = e.setByte4Int(l, offset)
|
||||
}
|
||||
offset += copy(e.d[offset:], str)
|
||||
return offset
|
||||
}
|
||||
+275
@@ -0,0 +1,275 @@
|
||||
package encoding
|
||||
|
||||
import (
|
||||
"math"
|
||||
"reflect"
|
||||
"sync"
|
||||
|
||||
"github.com/shamaton/msgpack/v2/def"
|
||||
"github.com/shamaton/msgpack/v2/internal/common"
|
||||
)
|
||||
|
||||
type structCache struct {
|
||||
indexes []int
|
||||
names []string
|
||||
omits []bool
|
||||
noOmit bool
|
||||
common.Common
|
||||
}
|
||||
|
||||
var cachemap = sync.Map{}
|
||||
|
||||
type structCalcFunc func(rv reflect.Value) (int, error)
|
||||
type structWriteFunc func(rv reflect.Value, offset int) int
|
||||
|
||||
func (e *encoder) getStructCalc(typ reflect.Type) structCalcFunc {
|
||||
|
||||
for j := range extCoders {
|
||||
if extCoders[j].Type() == typ {
|
||||
return extCoders[j].CalcByteSize
|
||||
}
|
||||
}
|
||||
if e.asArray {
|
||||
return e.calcStructArray
|
||||
}
|
||||
return e.calcStructMap
|
||||
|
||||
}
|
||||
|
||||
func (e *encoder) calcStruct(rv reflect.Value) (int, error) {
|
||||
|
||||
//if isTime, tm := e.isDateTime(rv); isTime {
|
||||
// size := e.calcTime(tm)
|
||||
// return size, nil
|
||||
//}
|
||||
|
||||
for i := range extCoders {
|
||||
if extCoders[i].Type() == rv.Type() {
|
||||
return extCoders[i].CalcByteSize(rv)
|
||||
}
|
||||
}
|
||||
|
||||
if e.asArray {
|
||||
return e.calcStructArray(rv)
|
||||
}
|
||||
return e.calcStructMap(rv)
|
||||
}
|
||||
|
||||
func (e *encoder) calcStructArray(rv reflect.Value) (int, error) {
|
||||
ret := 0
|
||||
t := rv.Type()
|
||||
cache, find := cachemap.Load(t)
|
||||
var c *structCache
|
||||
if !find {
|
||||
num := rv.NumField()
|
||||
c = &structCache{
|
||||
indexes: make([]int, 0, num),
|
||||
names: make([]string, 0, num),
|
||||
omits: make([]bool, 0, num),
|
||||
}
|
||||
omitCount := 0
|
||||
for i := 0; i < num; i++ {
|
||||
field := t.Field(i)
|
||||
if ok, omit, name := e.CheckField(field); ok {
|
||||
size, err := e.calcSize(rv.Field(i))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
ret += size
|
||||
c.indexes = append(c.indexes, i)
|
||||
c.names = append(c.names, name)
|
||||
c.omits = append(c.omits, omit)
|
||||
if omit {
|
||||
omitCount++
|
||||
}
|
||||
}
|
||||
}
|
||||
c.noOmit = omitCount == 0
|
||||
cachemap.Store(t, c)
|
||||
} else {
|
||||
c = cache.(*structCache)
|
||||
for i := 0; i < len(c.indexes); i++ {
|
||||
size, err := e.calcSize(rv.Field(c.indexes[i]))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
ret += size
|
||||
}
|
||||
}
|
||||
|
||||
// format size
|
||||
size, err := e.calcLength(len(c.indexes))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
ret += size
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (e *encoder) calcStructMap(rv reflect.Value) (int, error) {
|
||||
ret := 0
|
||||
t := rv.Type()
|
||||
cache, find := cachemap.Load(t)
|
||||
var c *structCache
|
||||
var l int
|
||||
if !find {
|
||||
num := rv.NumField()
|
||||
c = &structCache{
|
||||
indexes: make([]int, 0, num),
|
||||
names: make([]string, 0, num),
|
||||
omits: make([]bool, 0, num),
|
||||
}
|
||||
omitCount := 0
|
||||
for i := 0; i < num; i++ {
|
||||
if ok, omit, name := e.CheckField(rv.Type().Field(i)); ok {
|
||||
size, err := e.calcSizeWithOmitEmpty(rv.Field(i), name, omit)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
ret += size
|
||||
c.indexes = append(c.indexes, i)
|
||||
c.names = append(c.names, name)
|
||||
c.omits = append(c.omits, omit)
|
||||
if omit {
|
||||
omitCount++
|
||||
}
|
||||
if size > 0 {
|
||||
l++
|
||||
}
|
||||
}
|
||||
}
|
||||
c.noOmit = omitCount == 0
|
||||
cachemap.Store(t, c)
|
||||
} else {
|
||||
c = cache.(*structCache)
|
||||
for i := 0; i < len(c.indexes); i++ {
|
||||
size, err := e.calcSizeWithOmitEmpty(rv.Field(c.indexes[i]), c.names[i], c.omits[i])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
ret += size
|
||||
if size > 0 {
|
||||
l++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// format size
|
||||
size, err := e.calcLength(len(c.indexes))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
ret += size
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (e *encoder) calcSizeWithOmitEmpty(rv reflect.Value, name string, omit bool) (int, error) {
|
||||
keySize := 0
|
||||
valueSize := 0
|
||||
if !omit || !rv.IsZero() {
|
||||
keySize = e.calcString(name)
|
||||
vSize, err := e.calcSize(rv)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
valueSize = vSize
|
||||
}
|
||||
return keySize + valueSize, nil
|
||||
}
|
||||
|
||||
func (e *encoder) getStructWriter(typ reflect.Type) structWriteFunc {
|
||||
|
||||
for i := range extCoders {
|
||||
if extCoders[i].Type() == typ {
|
||||
return func(rv reflect.Value, offset int) int {
|
||||
return extCoders[i].WriteToBytes(rv, offset, &e.d)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if e.asArray {
|
||||
return e.writeStructArray
|
||||
}
|
||||
return e.writeStructMap
|
||||
}
|
||||
|
||||
func (e *encoder) writeStruct(rv reflect.Value, offset int) int {
|
||||
/*
|
||||
if isTime, tm := e.isDateTime(rv); isTime {
|
||||
return e.writeTime(tm, offset)
|
||||
}
|
||||
*/
|
||||
|
||||
for i := range extCoders {
|
||||
if extCoders[i].Type() == rv.Type() {
|
||||
return extCoders[i].WriteToBytes(rv, offset, &e.d)
|
||||
}
|
||||
}
|
||||
|
||||
if e.asArray {
|
||||
return e.writeStructArray(rv, offset)
|
||||
}
|
||||
return e.writeStructMap(rv, offset)
|
||||
}
|
||||
|
||||
func (e *encoder) writeStructArray(rv reflect.Value, offset int) int {
|
||||
|
||||
cache, _ := cachemap.Load(rv.Type())
|
||||
c := cache.(*structCache)
|
||||
|
||||
// write format
|
||||
num := len(c.indexes)
|
||||
if num <= 0x0f {
|
||||
offset = e.setByte1Int(def.FixArray+num, offset)
|
||||
} else if num <= math.MaxUint16 {
|
||||
offset = e.setByte1Int(def.Array16, offset)
|
||||
offset = e.setByte2Int(num, offset)
|
||||
} else if uint(num) <= math.MaxUint32 {
|
||||
offset = e.setByte1Int(def.Array32, offset)
|
||||
offset = e.setByte4Int(num, offset)
|
||||
}
|
||||
|
||||
for i := 0; i < num; i++ {
|
||||
offset = e.create(rv.Field(c.indexes[i]), offset)
|
||||
}
|
||||
return offset
|
||||
}
|
||||
|
||||
func (e *encoder) writeStructMap(rv reflect.Value, offset int) int {
|
||||
|
||||
cache, _ := cachemap.Load(rv.Type())
|
||||
c := cache.(*structCache)
|
||||
|
||||
// format size
|
||||
num := len(c.indexes)
|
||||
l := 0
|
||||
if c.noOmit {
|
||||
l = num
|
||||
} else {
|
||||
for i := 0; i < num; i++ {
|
||||
irv := rv.Field(c.indexes[i])
|
||||
if !c.omits[i] || !irv.IsZero() {
|
||||
l++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if l <= 0x0f {
|
||||
offset = e.setByte1Int(def.FixMap+l, offset)
|
||||
} else if l <= math.MaxUint16 {
|
||||
offset = e.setByte1Int(def.Map16, offset)
|
||||
offset = e.setByte2Int(l, offset)
|
||||
} else if uint(l) <= math.MaxUint32 {
|
||||
offset = e.setByte1Int(def.Map32, offset)
|
||||
offset = e.setByte4Int(l, offset)
|
||||
}
|
||||
|
||||
for i := 0; i < num; i++ {
|
||||
irv := rv.Field(c.indexes[i])
|
||||
if !c.omits[i] || !irv.IsZero() {
|
||||
offset = e.writeString(c.names[i], offset)
|
||||
offset = e.create(irv, offset)
|
||||
}
|
||||
}
|
||||
return offset
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
package encoding
|
||||
|
||||
import (
|
||||
"math"
|
||||
|
||||
"github.com/shamaton/msgpack/v2/def"
|
||||
)
|
||||
|
||||
func (e *encoder) calcUint(v uint64) int {
|
||||
if v <= math.MaxInt8 {
|
||||
// format code only
|
||||
return def.Byte1
|
||||
} else if v <= math.MaxUint8 {
|
||||
return def.Byte1 + def.Byte1
|
||||
} else if v <= math.MaxUint16 {
|
||||
return def.Byte1 + def.Byte2
|
||||
} else if v <= math.MaxUint32 {
|
||||
return def.Byte1 + def.Byte4
|
||||
}
|
||||
return def.Byte1 + def.Byte8
|
||||
}
|
||||
|
||||
func (e *encoder) writeUint(v uint64, offset int) int {
|
||||
if v <= math.MaxInt8 {
|
||||
offset = e.setByte1Uint64(v, offset)
|
||||
} else if v <= math.MaxUint8 {
|
||||
offset = e.setByte1Int(def.Uint8, offset)
|
||||
offset = e.setByte1Uint64(v, offset)
|
||||
} else if v <= math.MaxUint16 {
|
||||
offset = e.setByte1Int(def.Uint16, offset)
|
||||
offset = e.setByte2Uint64(v, offset)
|
||||
} else if v <= math.MaxUint32 {
|
||||
offset = e.setByte1Int(def.Uint32, offset)
|
||||
offset = e.setByte4Uint64(v, offset)
|
||||
} else {
|
||||
offset = e.setByte1Int(def.Uint64, offset)
|
||||
offset = e.setByte8Uint64(v, offset)
|
||||
}
|
||||
return offset
|
||||
}
|
||||
Reference in New Issue
Block a user