bump reva

Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de>
This commit is contained in:
Jörn Friedrich Dreyer
2025-09-12 12:18:47 +02:00
parent 9f096d4107
commit f8440edc9a
66 changed files with 3771 additions and 1136 deletions
+3 -3
View File
@@ -16,11 +16,11 @@ func (e *encoder) isByteSlice(rv reflect.Value) bool {
func (e *encoder) calcByteSlice(l int) (int, error) {
if l <= math.MaxUint8 {
return def.Byte1 + l, nil
return def.Byte1 + def.Byte1 + l, nil
} else if l <= math.MaxUint16 {
return def.Byte2 + l, nil
return def.Byte1 + def.Byte2 + l, nil
} else if uint(l) <= math.MaxUint32 {
return def.Byte4 + l, nil
return def.Byte1 + def.Byte4 + l, nil
}
// not supported error
return 0, fmt.Errorf("%w slice length : %d", def.ErrUnsupportedType, l)
+2 -2
View File
@@ -7,11 +7,11 @@ import (
)
func (e *encoder) calcComplex64() int {
return def.Byte1 + def.Byte8
return def.Byte1 + def.Byte1 + def.Byte8
}
func (e *encoder) calcComplex128() int {
return def.Byte1 + def.Byte16
return def.Byte1 + def.Byte1 + def.Byte16
}
func (e *encoder) writeComplex64(v complex64, offset int) int {
+62 -79
View File
@@ -63,65 +63,48 @@ func Encode(v interface{}, asArray bool) (b []byte, err error) {
//}
func (e *encoder) calcSize(rv reflect.Value) (int, error) {
ret := def.Byte1
switch rv.Kind() {
case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
v := rv.Uint()
ret += e.calcUint(v)
return e.calcUint(v), nil
case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
v := rv.Int()
ret += e.calcInt(int64(v))
return e.calcInt(int64(v)), nil
case reflect.Float32:
ret += e.calcFloat32(0)
return e.calcFloat32(0), nil
case reflect.Float64:
ret += e.calcFloat64(0)
return e.calcFloat64(0), nil
case reflect.String:
ret += e.calcString(rv.String())
return e.calcString(rv.String()), nil
case reflect.Bool:
// do nothing
return def.Byte1, nil
case reflect.Complex64:
ret += e.calcComplex64()
return e.calcComplex64(), nil
case reflect.Complex128:
ret += e.calcComplex128()
return e.calcComplex128(), nil
case reflect.Slice:
if rv.IsNil() {
return ret, nil
return def.Byte1, nil
}
l := rv.Len()
// bin format
if e.isByteSlice(rv) {
r, err := e.calcByteSlice(l)
size, err := e.calcByteSlice(rv.Len())
if err != nil {
return 0, err
}
ret += r
return ret, nil
}
// format size
if l <= 0x0f {
// format code only
} else if l <= math.MaxUint16 {
ret += def.Byte2
} else if uint(l) <= math.MaxUint32 {
ret += def.Byte4
} else {
// not supported error
return 0, fmt.Errorf("%w array length : %d", def.ErrUnsupportedType, l)
return size, nil
}
if size, find := e.calcFixedSlice(rv); find {
ret += size
return ret, nil
return size, nil
}
// func
@@ -129,42 +112,34 @@ func (e *encoder) calcSize(rv reflect.Value) (int, error) {
var f structCalcFunc
if elem.Kind() == reflect.Struct {
f = e.getStructCalc(elem)
ret += def.Byte1 * l
} 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++ {
size, err := f(rv.Index(i))
s, err := f(rv.Index(i))
if err != nil {
return 0, err
}
ret += size
size += s
}
return size, nil
case reflect.Array:
l := rv.Len()
// bin format
if e.isByteSlice(rv) {
r, err := e.calcByteSlice(l)
size, err := e.calcByteSlice(rv.Len())
if err != nil {
return 0, err
}
ret += r
return ret, nil
}
// format size
if l <= 0x0f {
// format code only
} else if l <= math.MaxUint16 {
ret += def.Byte2
} else if uint(l) <= math.MaxUint32 {
ret += def.Byte4
} else {
// not supported error
return 0, fmt.Errorf("array length %d is %w", l, def.ErrUnsupportedLength)
return size, nil
}
// func
@@ -172,41 +147,33 @@ func (e *encoder) calcSize(rv reflect.Value) (int, error) {
var f structCalcFunc
if elem.Kind() == reflect.Struct {
f = e.getStructCalc(elem)
ret += def.Byte1 * l
} 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++ {
size, err := f(rv.Index(i))
s, err := f(rv.Index(i))
if err != nil {
return 0, err
}
ret += size
size += s
}
return size, nil
case reflect.Map:
if rv.IsNil() {
return ret, nil
}
l := rv.Len()
// format
if l <= 0x0f {
// do nothing
} else if l <= math.MaxUint16 {
ret += def.Byte2
} else if uint(l) <= math.MaxUint32 {
ret += def.Byte4
} else {
// not supported error
return 0, fmt.Errorf("map length %d is %w", l, def.ErrUnsupportedLength)
return def.Byte1, nil
}
if size, find := e.calcFixedMap(rv); find {
ret += size
return ret, nil
return size, nil
}
if e.mk == nil {
@@ -214,8 +181,13 @@ func (e *encoder) calcSize(rv reflect.Value) (int, error) {
e.mv = map[uintptr][]reflect.Value{}
}
// key-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 {
@@ -228,44 +200,56 @@ func (e *encoder) calcSize(rv reflect.Value) (int, error) {
if err != nil {
return 0, err
}
ret += keySize + valueSize
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
}
ret += size
return size, nil
case reflect.Ptr:
if rv.IsNil() {
return ret, nil
return def.Byte1, nil
}
size, err := e.calcSize(rv.Elem())
if err != nil {
return 0, err
}
ret = size
return size, nil
case reflect.Interface:
size, err := e.calcSize(rv.Elem())
if err != nil {
return 0, err
}
ret = size
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)
}
}
return ret, nil
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 {
@@ -301,17 +285,14 @@ func (e *encoder) create(rv reflect.Value, offset int) int {
if rv.IsNil() {
return e.writeNil(offset)
}
l := rv.Len()
// bin format
if e.isByteSlice(rv) {
offset = e.writeByteSliceLength(l, offset)
offset = e.writeByteSliceLength(rv.Len(), offset)
offset = e.setBytes(rv.Bytes(), offset)
return offset
}
// format
offset = e.writeSliceLength(l, offset)
if offset, find := e.writeFixedSlice(rv, offset); find {
return offset
}
@@ -326,6 +307,8 @@ func (e *encoder) create(rv reflect.Value, offset int) int {
}
// objects
l := rv.Len()
offset = e.writeSliceLength(l, offset)
for i := 0; i < l; i++ {
offset = f(rv.Index(i), offset)
}
+4 -4
View File
@@ -6,12 +6,12 @@ import (
"github.com/shamaton/msgpack/v2/def"
)
func (e *encoder) calcFloat32(v float64) int {
return def.Byte4
func (e *encoder) calcFloat32(_ float64) int {
return def.Byte1 + def.Byte4
}
func (e *encoder) calcFloat64(v float64) int {
return def.Byte8
func (e *encoder) calcFloat64(_ float64) int {
return def.Byte1 + def.Byte8
}
func (e *encoder) writeFloat32(v float64, offset int) int {
+5 -5
View File
@@ -15,15 +15,15 @@ func (e *encoder) calcInt(v int64) int {
return e.calcUint(uint64(v))
} else if e.isNegativeFixInt64(v) {
// format code only
return 0
} else if v >= math.MinInt8 {
return def.Byte1
} else if v >= math.MinInt8 {
return def.Byte1 + def.Byte1
} else if v >= math.MinInt16 {
return def.Byte2
return def.Byte1 + def.Byte2
} else if v >= math.MinInt32 {
return def.Byte4
return def.Byte1 + def.Byte4
}
return def.Byte8
return def.Byte1 + def.Byte8
}
func (e *encoder) writeInt(v int64, offset int) int {
+105 -66
View File
@@ -8,252 +8,291 @@ import (
)
func (e *encoder) calcFixedMap(rv reflect.Value) (int, bool) {
size := 0
// 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 += def.Byte1 + e.calcString(k)
size += def.Byte1 + e.calcInt(int64(v))
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 += def.Byte1 + e.calcString(k)
size += def.Byte1 + e.calcUint(uint64(v))
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 += def.Byte1 + e.calcString(k)
size += def.Byte1 + e.calcString(v)
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 += def.Byte1 + e.calcString(k)
size += def.Byte1 + e.calcFloat32(0)
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 += def.Byte1 + e.calcString(k)
size += def.Byte1 + e.calcFloat64(0)
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 += def.Byte1 + e.calcString(k)
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 += def.Byte1 + e.calcString(k)
size += def.Byte1 + e.calcInt(int64(v))
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 += def.Byte1 + e.calcString(k)
size += def.Byte1 + e.calcInt(int64(v))
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 += def.Byte1 + e.calcString(k)
size += def.Byte1 + e.calcInt(int64(v))
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 += def.Byte1 + e.calcString(k)
size += def.Byte1 + e.calcInt(v)
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 += def.Byte1 + e.calcString(k)
size += def.Byte1 + e.calcUint(uint64(v))
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 += def.Byte1 + e.calcString(k)
size += def.Byte1 + e.calcUint(uint64(v))
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 += def.Byte1 + e.calcString(k)
size += def.Byte1 + e.calcUint(uint64(v))
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 += def.Byte1 + e.calcString(k)
size += def.Byte1 + e.calcUint(v)
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 += def.Byte1 + e.calcInt(int64(k))
size += def.Byte1 + e.calcString(v)
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 += def.Byte1 + e.calcInt(int64(k))
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 += def.Byte1 + e.calcUint(uint64(k))
size += def.Byte1 + e.calcString(v)
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 += def.Byte1 + e.calcUint(uint64(k))
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 += def.Byte1 + e.calcFloat32(float64(k))
size += def.Byte1 + e.calcString(v)
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 += def.Byte1 + e.calcFloat32(float64(k))
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 += def.Byte1 + e.calcFloat64(k)
size += def.Byte1 + e.calcString(v)
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 += def.Byte1 + e.calcFloat64(k)
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 += def.Byte1 + e.calcInt(int64(k))
size += def.Byte1 + e.calcString(v)
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 += def.Byte1 + e.calcInt(int64(k))
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 += def.Byte1 + e.calcInt(int64(k))
size += def.Byte1 + e.calcString(v)
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 += def.Byte1 + e.calcInt(int64(k))
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 += def.Byte1 + e.calcInt(int64(k))
size += def.Byte1 + e.calcString(v)
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 += def.Byte1 + e.calcInt(int64(k))
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 += def.Byte1 + e.calcInt(k)
size += def.Byte1 + e.calcString(v)
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 += def.Byte1 + e.calcInt(k)
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 += def.Byte1 + e.calcUint(uint64(k))
size += def.Byte1 + e.calcString(v)
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 += def.Byte1 + e.calcUint(uint64(k))
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 += def.Byte1 + e.calcUint(uint64(k))
size += def.Byte1 + e.calcString(v)
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 += def.Byte1 + e.calcUint(uint64(k))
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 += def.Byte1 + e.calcUint(uint64(k))
size += def.Byte1 + e.calcString(v)
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 += def.Byte1 + e.calcUint(uint64(k))
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 += def.Byte1 + e.calcUint(k)
size += def.Byte1 + e.calcString(v)
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 += def.Byte1 + e.calcUint(k)
size += e.calcUint(k)
size += def.Byte1 /* + e.calcBool()*/
}
return size, true
}
return size, false
return 0, false
}
func (e *encoder) writeMapLength(l int, offset int) int {
+45 -16
View File
@@ -8,93 +8,108 @@ import (
)
func (e *encoder) calcFixedSlice(rv reflect.Value) (int, bool) {
size := 0
// 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 += def.Byte1 + e.calcInt(int64(v))
size += e.calcInt(int64(v))
}
return size, true
case []uint:
size, _ := e.calcLength(len(sli))
for _, v := range sli {
size += def.Byte1 + e.calcUint(uint64(v))
size += e.calcUint(uint64(v))
}
return size, true
case []string:
size, _ := e.calcLength(len(sli))
for _, v := range sli {
size += def.Byte1 + e.calcString(v)
size += e.calcString(v)
}
return size, true
case []float32:
size, _ := e.calcLength(len(sli))
for _, v := range sli {
size += def.Byte1 + e.calcFloat32(float64(v))
size += e.calcFloat32(float64(v))
}
return size, true
case []float64:
size, _ := e.calcLength(len(sli))
for _, v := range sli {
size += def.Byte1 + e.calcFloat64(v)
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 += def.Byte1 + e.calcInt(int64(v))
size += e.calcInt(int64(v))
}
return size, true
case []int16:
size, _ := e.calcLength(len(sli))
for _, v := range sli {
size += def.Byte1 + e.calcInt(int64(v))
size += e.calcInt(int64(v))
}
return size, true
case []int32:
size, _ := e.calcLength(len(sli))
for _, v := range sli {
size += def.Byte1 + e.calcInt(int64(v))
size += e.calcInt(int64(v))
}
return size, true
case []int64:
size, _ := e.calcLength(len(sli))
for _, v := range sli {
size += def.Byte1 + e.calcInt(v)
size += e.calcInt(v)
}
return size, true
case []uint8:
size, _ := e.calcLength(len(sli))
for _, v := range sli {
size += def.Byte1 + e.calcUint(uint64(v))
size += e.calcUint(uint64(v))
}
return size, true
case []uint16:
size, _ := e.calcLength(len(sli))
for _, v := range sli {
size += def.Byte1 + e.calcUint(uint64(v))
size += e.calcUint(uint64(v))
}
return size, true
case []uint32:
size, _ := e.calcLength(len(sli))
for _, v := range sli {
size += def.Byte1 + e.calcUint(uint64(v))
size += e.calcUint(uint64(v))
}
return size, true
case []uint64:
size, _ := e.calcLength(len(sli))
for _, v := range sli {
size += def.Byte1 + e.calcUint(v)
size += e.calcUint(v)
}
return size, true
}
return size, false
return 0, false
}
func (e *encoder) writeSliceLength(l int, offset int) int {
@@ -115,84 +130,98 @@ 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)
}
+4 -4
View File
@@ -12,13 +12,13 @@ func (e *encoder) calcString(v string) int {
strBytes := *(*[]byte)(unsafe.Pointer(&v))
l := len(strBytes)
if l < 32 {
return l
} else if l <= math.MaxUint8 {
return def.Byte1 + l
} else if l <= math.MaxUint8 {
return def.Byte1 + def.Byte1 + l
} else if l <= math.MaxUint16 {
return def.Byte2 + l
return def.Byte1 + def.Byte2 + l
}
return def.Byte4 + l
return def.Byte1 + def.Byte4 + l
// NOTE : length over uint32
}
+86 -41
View File
@@ -1,7 +1,6 @@
package encoding
import (
"fmt"
"math"
"reflect"
"sync"
@@ -13,6 +12,8 @@ import (
type structCache struct {
indexes []int
names []string
omits []bool
noOmit bool
common.Common
}
@@ -60,10 +61,16 @@ func (e *encoder) calcStructArray(rv reflect.Value) (int, error) {
cache, find := cachemap.Load(t)
var c *structCache
if !find {
c = &structCache{}
for i := 0; i < rv.NumField(); i++ {
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, name := e.CheckField(field); ok {
if ok, omit, name := e.CheckField(field); ok {
size, err := e.calcSize(rv.Field(i))
if err != nil {
return 0, err
@@ -71,8 +78,13 @@ func (e *encoder) calcStructArray(rv reflect.Value) (int, error) {
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)
@@ -86,17 +98,11 @@ func (e *encoder) calcStructArray(rv reflect.Value) (int, error) {
}
// format size
l := len(c.indexes)
if l <= 0x0f {
// format code only
} else if l <= math.MaxUint16 {
ret += def.Byte2
} else if uint(l) <= math.MaxUint32 {
ret += def.Byte4
} else {
// not supported error
return 0, fmt.Errorf("array length %d is %w", l, def.ErrUnsupportedLength)
size, err := e.calcLength(len(c.indexes))
if err != nil {
return 0, err
}
ret += size
return ret, nil
}
@@ -105,48 +111,72 @@ func (e *encoder) calcStructMap(rv reflect.Value) (int, error) {
t := rv.Type()
cache, find := cachemap.Load(t)
var c *structCache
var l int
if !find {
c = &structCache{}
for i := 0; i < rv.NumField(); i++ {
if ok, name := e.CheckField(rv.Type().Field(i)); ok {
keySize := def.Byte1 + e.calcString(name)
valueSize, err := e.calcSize(rv.Field(i))
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 += keySize + valueSize
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++ {
keySize := def.Byte1 + e.calcString(c.names[i])
valueSize, err := e.calcSize(rv.Field(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 += keySize + valueSize
ret += size
if size > 0 {
l++
}
}
}
// format size
l := len(c.indexes)
if l <= 0x0f {
// format code only
} else if l <= math.MaxUint16 {
ret += def.Byte2
} else if uint(l) <= math.MaxUint32 {
ret += def.Byte4
} else {
// not supported error
return 0, fmt.Errorf("map length %d is %w", l, def.ErrUnsupportedLength)
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 {
@@ -212,19 +242,34 @@ func (e *encoder) writeStructMap(rv reflect.Value, offset int) int {
// format size
num := len(c.indexes)
if num <= 0x0f {
offset = e.setByte1Int(def.FixMap+num, offset)
} else if num <= math.MaxUint16 {
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(num, offset)
} else if uint(num) <= math.MaxUint32 {
offset = e.setByte2Int(l, offset)
} else if uint(l) <= math.MaxUint32 {
offset = e.setByte1Int(def.Map32, offset)
offset = e.setByte4Int(num, offset)
offset = e.setByte4Int(l, offset)
}
for i := 0; i < num; i++ {
offset = e.writeString(c.names[i], offset)
offset = e.create(rv.Field(c.indexes[i]), offset)
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
}
+5 -5
View File
@@ -9,15 +9,15 @@ import (
func (e *encoder) calcUint(v uint64) int {
if v <= math.MaxInt8 {
// format code only
return 0
} else if v <= math.MaxUint8 {
return def.Byte1
} else if v <= math.MaxUint8 {
return def.Byte1 + def.Byte1
} else if v <= math.MaxUint16 {
return def.Byte2
return def.Byte1 + def.Byte2
} else if v <= math.MaxUint32 {
return def.Byte4
return def.Byte1 + def.Byte4
}
return def.Byte8
return def.Byte1 + def.Byte8
}
func (e *encoder) writeUint(v uint64, offset int) int {