mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2026-05-08 04:20:59 -05:00
+1
-1
@@ -1,6 +1,6 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2024 Masayuki Shamoto
|
||||
Copyright (c) 2025 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
|
||||
|
||||
+3
-6
@@ -6,15 +6,12 @@
|
||||
[](https://codecov.io/gh/shamaton/msgpack)
|
||||
[](https://app.fossa.com/projects/git%2Bgithub.com%2Fshamaton%2Fmsgpack?ref=badge_shield)
|
||||
|
||||
## 📣 Notice
|
||||
If your application serializes only primitive types, array, map and struct, code generation is also recommended.
|
||||
You can get the fastest performance with [msgpackgen](https://github.com/shamaton/msgpackgen).
|
||||
|
||||
## Features
|
||||
* Supported types : primitive / array / slice / struct / map / interface{} and time.Time
|
||||
* Renaming fields via `msgpack:"field_name"`
|
||||
* Omitting fields via `msgpack:"-"`
|
||||
* Supports extend encoder / decoder
|
||||
* Omitting empty fields via `msgpack:"field_name,omitempty"`
|
||||
* Supports extend encoder / decoder [(example)](./msgpack_example_test.go)
|
||||
* Can also Encoding / Decoding struct as array
|
||||
|
||||
## Installation
|
||||
@@ -66,7 +63,7 @@ func handle(w http.ResponseWriter, r *http.Request) {
|
||||
## Benchmark
|
||||
This result made from [shamaton/msgpack_bench](https://github.com/shamaton/msgpack_bench)
|
||||
|
||||

|
||||

|
||||
|
||||
## License
|
||||
|
||||
|
||||
+21
@@ -6,35 +6,56 @@ import (
|
||||
"github.com/shamaton/msgpack/v2/def"
|
||||
)
|
||||
|
||||
// Decoder defines an interface for decoding values from bytes.
|
||||
// It provides methods to get the decoder type, check if the data matches the type,
|
||||
// and convert the data into a Go value.
|
||||
type Decoder interface {
|
||||
// Code returns the unique code representing the decoder type.
|
||||
Code() int8
|
||||
|
||||
// IsType checks if the data at the given offset matches the expected type.
|
||||
// Returns true if the type matches, false otherwise.
|
||||
IsType(offset int, d *[]byte) bool
|
||||
|
||||
// AsValue decodes the data at the given offset into a Go value of the specified kind.
|
||||
// Returns the decoded value, the new offset, and an error if decoding fails.
|
||||
AsValue(offset int, k reflect.Kind, d *[]byte) (interface{}, int, error)
|
||||
}
|
||||
|
||||
// DecoderCommon provides common utility methods for decoding data from bytes.
|
||||
type DecoderCommon struct {
|
||||
}
|
||||
|
||||
// ReadSize1 reads a single byte from the given index in the byte slice.
|
||||
// Returns the byte and the new index after reading.
|
||||
func (cd *DecoderCommon) ReadSize1(index int, d *[]byte) (byte, int) {
|
||||
rb := def.Byte1
|
||||
return (*d)[index], index + rb
|
||||
}
|
||||
|
||||
// ReadSize2 reads two bytes from the given index in the byte slice.
|
||||
// Returns the bytes as a slice and the new index after reading.
|
||||
func (cd *DecoderCommon) ReadSize2(index int, d *[]byte) ([]byte, int) {
|
||||
rb := def.Byte2
|
||||
return (*d)[index : index+rb], index + rb
|
||||
}
|
||||
|
||||
// ReadSize4 reads four bytes from the given index in the byte slice.
|
||||
// Returns the bytes as a slice and the new index after reading.
|
||||
func (cd *DecoderCommon) ReadSize4(index int, d *[]byte) ([]byte, int) {
|
||||
rb := def.Byte4
|
||||
return (*d)[index : index+rb], index + rb
|
||||
}
|
||||
|
||||
// ReadSize8 reads eight bytes from the given index in the byte slice.
|
||||
// Returns the bytes as a slice and the new index after reading.
|
||||
func (cd *DecoderCommon) ReadSize8(index int, d *[]byte) ([]byte, int) {
|
||||
rb := def.Byte8
|
||||
return (*d)[index : index+rb], index + rb
|
||||
}
|
||||
|
||||
// ReadSizeN reads a specified number of bytes (n) from the given index in the byte slice.
|
||||
// Returns the bytes as a slice and the new index after reading.
|
||||
func (cd *DecoderCommon) ReadSizeN(index, n int, d *[]byte) ([]byte, int) {
|
||||
return (*d)[index : index+n], index + n
|
||||
}
|
||||
|
||||
+11
@@ -4,8 +4,19 @@ import (
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// StreamDecoder defines an interface for decoding streams of data.
|
||||
// It provides methods to retrieve the decoder's code, check type compatibility,
|
||||
// and convert raw data into a Go value of a specified kind.
|
||||
type StreamDecoder interface {
|
||||
// Code returns the unique identifier for the decoder.
|
||||
Code() int8
|
||||
|
||||
// IsType checks if the provided code, inner type, and data length match the expected type.
|
||||
// Returns true if the type matches, otherwise false.
|
||||
IsType(code byte, innerType int8, dataLength int) bool
|
||||
|
||||
// ToValue converts the raw data into a Go value of the specified kind.
|
||||
// Takes the code, raw data, and the target kind as input.
|
||||
// Returns the decoded value or an error if the conversion fails.
|
||||
ToValue(code byte, data []byte, k reflect.Kind) (any, error)
|
||||
}
|
||||
|
||||
+41
@@ -4,27 +4,48 @@ import (
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// Encoder defines an interface for encoding values into bytes.
|
||||
// It provides methods to get the encoding type, calculate the byte size of a value,
|
||||
// and write the encoded value into a byte slice.
|
||||
type Encoder interface {
|
||||
// Code returns the unique code representing the encoder type.
|
||||
Code() int8
|
||||
|
||||
// Type returns the reflect.Type of the value that the encoder handles.
|
||||
Type() reflect.Type
|
||||
|
||||
// CalcByteSize calculates the number of bytes required to encode the given value.
|
||||
// Returns the size and an error if the calculation fails.
|
||||
CalcByteSize(value reflect.Value) (int, error)
|
||||
|
||||
// WriteToBytes encodes the given value into a byte slice starting at the specified offset.
|
||||
// Returns the new offset after writing the bytes.
|
||||
WriteToBytes(value reflect.Value, offset int, bytes *[]byte) int
|
||||
}
|
||||
|
||||
// EncoderCommon provides utility methods for encoding various types of values into bytes.
|
||||
// It includes methods to encode integers and unsigned integers of different sizes,
|
||||
// as well as methods to write raw byte slices into a target byte slice.
|
||||
type EncoderCommon struct {
|
||||
}
|
||||
|
||||
// SetByte1Int64 encodes a single byte from the given int64 value into the byte slice at the specified offset.
|
||||
// Returns the new offset after writing the byte.
|
||||
func (c *EncoderCommon) SetByte1Int64(value int64, offset int, d *[]byte) int {
|
||||
(*d)[offset] = byte(value)
|
||||
return offset + 1
|
||||
}
|
||||
|
||||
// SetByte2Int64 encodes the lower two bytes of the given int64 value into the byte slice at the specified offset.
|
||||
// Returns the new offset after writing the bytes.
|
||||
func (c *EncoderCommon) SetByte2Int64(value int64, offset int, d *[]byte) int {
|
||||
(*d)[offset+0] = byte(value >> 8)
|
||||
(*d)[offset+1] = byte(value)
|
||||
return offset + 2
|
||||
}
|
||||
|
||||
// SetByte4Int64 encodes the lower four bytes of the given int64 value into the byte slice at the specified offset.
|
||||
// Returns the new offset after writing the bytes.
|
||||
func (c *EncoderCommon) SetByte4Int64(value int64, offset int, d *[]byte) int {
|
||||
(*d)[offset+0] = byte(value >> 24)
|
||||
(*d)[offset+1] = byte(value >> 16)
|
||||
@@ -33,6 +54,8 @@ func (c *EncoderCommon) SetByte4Int64(value int64, offset int, d *[]byte) int {
|
||||
return offset + 4
|
||||
}
|
||||
|
||||
// SetByte8Int64 encodes all eight bytes of the given int64 value into the byte slice at the specified offset.
|
||||
// Returns the new offset after writing the bytes.
|
||||
func (c *EncoderCommon) SetByte8Int64(value int64, offset int, d *[]byte) int {
|
||||
(*d)[offset] = byte(value >> 56)
|
||||
(*d)[offset+1] = byte(value >> 48)
|
||||
@@ -45,17 +68,23 @@ func (c *EncoderCommon) SetByte8Int64(value int64, offset int, d *[]byte) int {
|
||||
return offset + 8
|
||||
}
|
||||
|
||||
// SetByte1Uint64 encodes a single byte from the given uint64 value into the byte slice at the specified offset.
|
||||
// Returns the new offset after writing the byte.
|
||||
func (c *EncoderCommon) SetByte1Uint64(value uint64, offset int, d *[]byte) int {
|
||||
(*d)[offset] = byte(value)
|
||||
return offset + 1
|
||||
}
|
||||
|
||||
// SetByte2Uint64 encodes the lower two bytes of the given uint64 value into the byte slice at the specified offset.
|
||||
// Returns the new offset after writing the bytes.
|
||||
func (c *EncoderCommon) SetByte2Uint64(value uint64, offset int, d *[]byte) int {
|
||||
(*d)[offset] = byte(value >> 8)
|
||||
(*d)[offset+1] = byte(value)
|
||||
return offset + 2
|
||||
}
|
||||
|
||||
// SetByte4Uint64 encodes the lower four bytes of the given uint64 value into the byte slice at the specified offset.
|
||||
// Returns the new offset after writing the bytes.
|
||||
func (c *EncoderCommon) SetByte4Uint64(value uint64, offset int, d *[]byte) int {
|
||||
(*d)[offset] = byte(value >> 24)
|
||||
(*d)[offset+1] = byte(value >> 16)
|
||||
@@ -64,6 +93,8 @@ func (c *EncoderCommon) SetByte4Uint64(value uint64, offset int, d *[]byte) int
|
||||
return offset + 4
|
||||
}
|
||||
|
||||
// SetByte8Uint64 encodes all eight bytes of the given uint64 value into the byte slice at the specified offset.
|
||||
// Returns the new offset after writing the bytes.
|
||||
func (c *EncoderCommon) SetByte8Uint64(value uint64, offset int, d *[]byte) int {
|
||||
(*d)[offset] = byte(value >> 56)
|
||||
(*d)[offset+1] = byte(value >> 48)
|
||||
@@ -76,17 +107,23 @@ func (c *EncoderCommon) SetByte8Uint64(value uint64, offset int, d *[]byte) int
|
||||
return offset + 8
|
||||
}
|
||||
|
||||
// SetByte1Int encodes a single byte from the given int value into the byte slice at the specified offset.
|
||||
// Returns the new offset after writing the byte.
|
||||
func (c *EncoderCommon) SetByte1Int(code, offset int, d *[]byte) int {
|
||||
(*d)[offset] = byte(code)
|
||||
return offset + 1
|
||||
}
|
||||
|
||||
// SetByte2Int encodes the lower two bytes of the given int value into the byte slice at the specified offset.
|
||||
// Returns the new offset after writing the bytes.
|
||||
func (c *EncoderCommon) SetByte2Int(value int, offset int, d *[]byte) int {
|
||||
(*d)[offset] = byte(value >> 8)
|
||||
(*d)[offset+1] = byte(value)
|
||||
return offset + 2
|
||||
}
|
||||
|
||||
// SetByte4Int encodes the lower four bytes of the given int value into the byte slice at the specified offset.
|
||||
// Returns the new offset after writing the bytes.
|
||||
func (c *EncoderCommon) SetByte4Int(value int, offset int, d *[]byte) int {
|
||||
(*d)[offset] = byte(value >> 24)
|
||||
(*d)[offset+1] = byte(value >> 16)
|
||||
@@ -95,6 +132,8 @@ func (c *EncoderCommon) SetByte4Int(value int, offset int, d *[]byte) int {
|
||||
return offset + 4
|
||||
}
|
||||
|
||||
// SetByte4Uint32 encodes the lower four bytes of the given uint32 value into the byte slice at the specified offset.
|
||||
// Returns the new offset after writing the bytes.
|
||||
func (c *EncoderCommon) SetByte4Uint32(value uint32, offset int, d *[]byte) int {
|
||||
(*d)[offset] = byte(value >> 24)
|
||||
(*d)[offset+1] = byte(value >> 16)
|
||||
@@ -103,6 +142,8 @@ func (c *EncoderCommon) SetByte4Uint32(value uint32, offset int, d *[]byte) int
|
||||
return offset + 4
|
||||
}
|
||||
|
||||
// SetBytes writes the given byte slice `bs` into the target byte slice at the specified offset.
|
||||
// Returns the new offset after writing the bytes.
|
||||
func (c *EncoderCommon) SetBytes(bs []byte, offset int, d *[]byte) int {
|
||||
for i := range bs {
|
||||
(*d)[offset+i] = bs[i]
|
||||
|
||||
+23
-4
@@ -7,29 +7,37 @@ import (
|
||||
"github.com/shamaton/msgpack/v2/internal/common"
|
||||
)
|
||||
|
||||
// StreamEncoder is interface that extended encoder should implement
|
||||
// StreamEncoder is an interface that extended encoders should implement.
|
||||
// It defines methods for encoding data into a stream.
|
||||
type StreamEncoder interface {
|
||||
// Code returns the unique code for the encoder.
|
||||
Code() int8
|
||||
// Type returns the reflect.Type of the value being encoded.
|
||||
Type() reflect.Type
|
||||
// Write encodes the given value and writes it to the provided StreamWriter.
|
||||
Write(w StreamWriter, value reflect.Value) error
|
||||
}
|
||||
|
||||
// StreamWriter is provided some writing functions for extended format by user
|
||||
// StreamWriter provides methods for writing data in extended formats.
|
||||
// It wraps an io.Writer and a buffer for efficient writing.
|
||||
type StreamWriter struct {
|
||||
w io.Writer
|
||||
buf *common.Buffer
|
||||
w io.Writer // The underlying writer to write data to.
|
||||
buf *common.Buffer // A buffer used for temporary storage during writing.
|
||||
}
|
||||
|
||||
// CreateStreamWriter creates and returns a new StreamWriter instance.
|
||||
func CreateStreamWriter(w io.Writer, buf *common.Buffer) StreamWriter {
|
||||
return StreamWriter{w, buf}
|
||||
}
|
||||
|
||||
// WriteByte1Int64 writes a single byte representation of an int64 value.
|
||||
func (w *StreamWriter) WriteByte1Int64(value int64) error {
|
||||
return w.buf.Write(w.w,
|
||||
byte(value),
|
||||
)
|
||||
}
|
||||
|
||||
// WriteByte2Int64 writes a two-byte representation of an int64 value.
|
||||
func (w *StreamWriter) WriteByte2Int64(value int64) error {
|
||||
return w.buf.Write(w.w,
|
||||
byte(value>>8),
|
||||
@@ -37,6 +45,7 @@ func (w *StreamWriter) WriteByte2Int64(value int64) error {
|
||||
)
|
||||
}
|
||||
|
||||
// WriteByte4Int64 writes a four-byte representation of an int64 value.
|
||||
func (w *StreamWriter) WriteByte4Int64(value int64) error {
|
||||
return w.buf.Write(w.w,
|
||||
byte(value>>24),
|
||||
@@ -46,6 +55,7 @@ func (w *StreamWriter) WriteByte4Int64(value int64) error {
|
||||
)
|
||||
}
|
||||
|
||||
// WriteByte8Int64 writes an eight-byte representation of an int64 value.
|
||||
func (w *StreamWriter) WriteByte8Int64(value int64) error {
|
||||
return w.buf.Write(w.w,
|
||||
byte(value>>56),
|
||||
@@ -59,12 +69,14 @@ func (w *StreamWriter) WriteByte8Int64(value int64) error {
|
||||
)
|
||||
}
|
||||
|
||||
// WriteByte1Uint64 writes a single byte representation of a uint64 value.
|
||||
func (w *StreamWriter) WriteByte1Uint64(value uint64) error {
|
||||
return w.buf.Write(w.w,
|
||||
byte(value),
|
||||
)
|
||||
}
|
||||
|
||||
// WriteByte2Uint64 writes a two-byte representation of a uint64 value.
|
||||
func (w *StreamWriter) WriteByte2Uint64(value uint64) error {
|
||||
return w.buf.Write(w.w,
|
||||
byte(value>>8),
|
||||
@@ -72,6 +84,7 @@ func (w *StreamWriter) WriteByte2Uint64(value uint64) error {
|
||||
)
|
||||
}
|
||||
|
||||
// WriteByte4Uint64 writes a four-byte representation of a uint64 value.
|
||||
func (w *StreamWriter) WriteByte4Uint64(value uint64) error {
|
||||
return w.buf.Write(w.w,
|
||||
byte(value>>24),
|
||||
@@ -81,6 +94,7 @@ func (w *StreamWriter) WriteByte4Uint64(value uint64) error {
|
||||
)
|
||||
}
|
||||
|
||||
// WriteByte8Uint64 writes an eight-byte representation of a uint64 value.
|
||||
func (w *StreamWriter) WriteByte8Uint64(value uint64) error {
|
||||
return w.buf.Write(w.w,
|
||||
byte(value>>56),
|
||||
@@ -94,12 +108,14 @@ func (w *StreamWriter) WriteByte8Uint64(value uint64) error {
|
||||
)
|
||||
}
|
||||
|
||||
// WriteByte1Int writes a single byte representation of an int value.
|
||||
func (w *StreamWriter) WriteByte1Int(value int) error {
|
||||
return w.buf.Write(w.w,
|
||||
byte(value),
|
||||
)
|
||||
}
|
||||
|
||||
// WriteByte2Int writes a two-byte representation of an int value.
|
||||
func (w *StreamWriter) WriteByte2Int(value int) error {
|
||||
return w.buf.Write(w.w,
|
||||
byte(value>>8),
|
||||
@@ -107,6 +123,7 @@ func (w *StreamWriter) WriteByte2Int(value int) error {
|
||||
)
|
||||
}
|
||||
|
||||
// WriteByte4Int writes a four-byte representation of an int value.
|
||||
func (w *StreamWriter) WriteByte4Int(value int) error {
|
||||
return w.buf.Write(w.w,
|
||||
byte(value>>24),
|
||||
@@ -116,6 +133,7 @@ func (w *StreamWriter) WriteByte4Int(value int) error {
|
||||
)
|
||||
}
|
||||
|
||||
// WriteByte4Uint32 writes a four-byte representation of a uint32 value.
|
||||
func (w *StreamWriter) WriteByte4Uint32(value uint32) error {
|
||||
return w.buf.Write(w.w,
|
||||
byte(value>>24),
|
||||
@@ -125,6 +143,7 @@ func (w *StreamWriter) WriteByte4Uint32(value uint32) error {
|
||||
)
|
||||
}
|
||||
|
||||
// WriteBytes writes a slice of bytes to the underlying writer.
|
||||
func (w *StreamWriter) WriteBytes(bs []byte) error {
|
||||
return w.buf.Write(w.w, bs...)
|
||||
}
|
||||
|
||||
+29
-10
@@ -1,23 +1,42 @@
|
||||
package common
|
||||
|
||||
import "reflect"
|
||||
import (
|
||||
"reflect"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Common is used encoding/decoding
|
||||
type Common struct {
|
||||
}
|
||||
|
||||
// CheckField returns flag whether should encode/decode or not and field name
|
||||
func (c *Common) CheckField(field reflect.StructField) (bool, string) {
|
||||
func (c *Common) CheckField(field reflect.StructField) (public, omit bool, name string) {
|
||||
// A to Z
|
||||
if c.isPublic(field.Name) {
|
||||
if tag := field.Tag.Get("msgpack"); tag == "-" {
|
||||
return false, ""
|
||||
} else if len(tag) > 0 {
|
||||
return true, tag
|
||||
}
|
||||
return true, field.Name
|
||||
if !c.isPublic(field.Name) {
|
||||
return false, false, ""
|
||||
}
|
||||
return false, ""
|
||||
tag := field.Tag.Get("msgpack")
|
||||
if tag == "" {
|
||||
return true, false, field.Name
|
||||
}
|
||||
|
||||
parts := strings.Split(tag, ",")
|
||||
// check ignore
|
||||
if parts[0] == "-" {
|
||||
return false, false, ""
|
||||
}
|
||||
// check omitempty
|
||||
for _, part := range parts[1:] {
|
||||
if part == "omitempty" {
|
||||
omit = true
|
||||
}
|
||||
}
|
||||
// check name
|
||||
name = field.Name
|
||||
if parts[0] != "" {
|
||||
name = parts[0]
|
||||
}
|
||||
return true, omit, name
|
||||
}
|
||||
|
||||
func (c *Common) isPublic(name string) bool {
|
||||
|
||||
+2
-2
@@ -71,7 +71,7 @@ func (d *decoder) setStructFromArray(rv reflect.Value, offset int, k reflect.Kin
|
||||
if !findCache {
|
||||
scta = &structCacheTypeArray{}
|
||||
for i := 0; i < rv.NumField(); i++ {
|
||||
if ok, _ := d.CheckField(rv.Type().Field(i)); ok {
|
||||
if ok, _, _ := d.CheckField(rv.Type().Field(i)); ok {
|
||||
scta.m = append(scta.m, i)
|
||||
}
|
||||
}
|
||||
@@ -112,7 +112,7 @@ func (d *decoder) setStructFromMap(rv reflect.Value, offset int, k reflect.Kind)
|
||||
if !cacheFind {
|
||||
sctm = &structCacheTypeMap{}
|
||||
for i := 0; i < rv.NumField(); i++ {
|
||||
if ok, name := d.CheckField(rv.Type().Field(i)); ok {
|
||||
if ok, _, name := d.CheckField(rv.Type().Field(i)); ok {
|
||||
sctm.keys = append(sctm.keys, []byte(name))
|
||||
sctm.indexes = append(sctm.indexes, i)
|
||||
}
|
||||
|
||||
+3
-3
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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 {
|
||||
|
||||
+2
-2
@@ -64,7 +64,7 @@ func (d *decoder) setStructFromArray(code byte, rv reflect.Value, k reflect.Kind
|
||||
if !findCache {
|
||||
scta = &structCacheTypeArray{}
|
||||
for i := 0; i < rv.NumField(); i++ {
|
||||
if ok, _ := d.CheckField(rv.Type().Field(i)); ok {
|
||||
if ok, _, _ := d.CheckField(rv.Type().Field(i)); ok {
|
||||
scta.m = append(scta.m, i)
|
||||
}
|
||||
}
|
||||
@@ -101,7 +101,7 @@ func (d *decoder) setStructFromMap(code byte, rv reflect.Value, k reflect.Kind)
|
||||
if !cacheFind {
|
||||
sctm = &structCacheTypeMap{}
|
||||
for i := 0; i < rv.NumField(); i++ {
|
||||
if ok, name := d.CheckField(rv.Type().Field(i)); ok {
|
||||
if ok, _, name := d.CheckField(rv.Type().Field(i)); ok {
|
||||
sctm.keys = append(sctm.keys, []byte(name))
|
||||
sctm.indexes = append(sctm.indexes, i)
|
||||
}
|
||||
|
||||
+45
-20
@@ -13,6 +13,8 @@ import (
|
||||
type structCache struct {
|
||||
indexes []int
|
||||
names []string
|
||||
omits []bool
|
||||
noOmit bool
|
||||
common.Common
|
||||
}
|
||||
|
||||
@@ -88,34 +90,49 @@ func (e *encoder) writeStructArray(rv reflect.Value) error {
|
||||
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 {
|
||||
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++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// format size
|
||||
if l <= 0x0f {
|
||||
if err := e.setByte1Int(def.FixMap + l); err != nil {
|
||||
return err
|
||||
}
|
||||
} else if num <= math.MaxUint16 {
|
||||
} else if l <= math.MaxUint16 {
|
||||
if err := e.setByte1Int(def.Map16); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := e.setByte2Int(num); err != nil {
|
||||
if err := e.setByte2Int(l); err != nil {
|
||||
return err
|
||||
}
|
||||
} else if uint(num) <= math.MaxUint32 {
|
||||
} else if uint(l) <= math.MaxUint32 {
|
||||
if err := e.setByte1Int(def.Map32); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := e.setByte4Int(num); err != nil {
|
||||
if err := e.setByte4Int(l); 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
|
||||
irv := rv.Field(c.indexes[i])
|
||||
if !c.omits[i] || !irv.IsZero() {
|
||||
if err := e.writeString(c.names[i]); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := e.create(irv); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
@@ -128,16 +145,24 @@ func (e *encoder) getStructCache(rv reflect.Value) *structCache {
|
||||
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)
|
||||
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 {
|
||||
c.indexes = append(c.indexes, i)
|
||||
c.names = append(c.names, name)
|
||||
c.omits = append(c.omits, omit)
|
||||
if omit {
|
||||
omitCount++
|
||||
}
|
||||
}
|
||||
cachemap.Store(t, c)
|
||||
}
|
||||
c.noOmit = omitCount == 0
|
||||
cachemap.Store(t, c)
|
||||
return c
|
||||
}
|
||||
|
||||
+3
-3
@@ -30,12 +30,12 @@ func (s *timeEncoder) CalcByteSize(value reflect.Value) (int, error) {
|
||||
if secs>>34 == 0 {
|
||||
data := uint64(t.Nanosecond())<<34 | secs
|
||||
if data&0xffffffff00000000 == 0 {
|
||||
return def.Byte1 + def.Byte4, nil
|
||||
return def.Byte1 + def.Byte1 + def.Byte4, nil
|
||||
}
|
||||
return def.Byte1 + def.Byte8, nil
|
||||
return def.Byte1 + def.Byte1 + def.Byte8, nil
|
||||
}
|
||||
|
||||
return def.Byte1 + def.Byte1 + def.Byte4 + def.Byte8, nil
|
||||
return def.Byte1 + def.Byte1 + def.Byte1 + def.Byte4 + def.Byte8, nil
|
||||
}
|
||||
|
||||
func (s *timeEncoder) WriteToBytes(value reflect.Value, offset int, bytes *[]byte) int {
|
||||
|
||||
Reference in New Issue
Block a user