Added more types. Implemented unsafe marshalling for faster
serialization
This commit is contained in:
parent
17f127cdb6
commit
b398aec2ed
|
@ -35,13 +35,13 @@ func (dec *Decoder) DecodeValue(value reflect.Value) (err error) {
|
||||||
dec.mutex.Lock()
|
dec.mutex.Lock()
|
||||||
defer dec.mutex.Unlock()
|
defer dec.mutex.Unlock()
|
||||||
|
|
||||||
lb := make([]byte, 8)
|
lb := make([]byte, 4)
|
||||||
err = binary.Read(dec.r, binary.BigEndian, lb)
|
err = binary.Read(dec.r, binary.BigEndian, lb)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
l, n, err := UnmarshalInt64(lb)
|
l, n, err := UnmarshalInt32(lb)
|
||||||
if err != nil || n != 8 {
|
if err != nil || n != 4 {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
11
encoder.go
11
encoder.go
|
@ -32,15 +32,18 @@ func (enc *Encoder) EncodeValue(value reflect.Value) (err error) {
|
||||||
return errors.New("ssob: Cannot encode nil of type " + value.Type().String())
|
return errors.New("ssob: Cannot encode nil of type " + value.Type().String())
|
||||||
}
|
}
|
||||||
|
|
||||||
b, err := marshal(value.Interface())
|
bb, err := marshal(value.Interface())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
bb := MarshalInt64(int64(len(b)))
|
bl := MarshalInt32(int32(len(bb)))
|
||||||
bb = append(bb, b...)
|
|
||||||
|
w := make([]byte, 4+len(bb))
|
||||||
|
copy(w, bl)
|
||||||
|
copy(w[4:], bb)
|
||||||
|
|
||||||
enc.mutex.Lock()
|
enc.mutex.Lock()
|
||||||
defer enc.mutex.Unlock()
|
defer enc.mutex.Unlock()
|
||||||
|
|
||||||
return binary.Write(enc.w, binary.BigEndian, bb)
|
return binary.Write(enc.w, binary.BigEndian, w)
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
package ssob
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
func isLittleEndian() bool {
|
||||||
|
var i int = 0x0100
|
||||||
|
ptr := unsafe.Pointer(&i)
|
||||||
|
if 0x00 == *(*byte)(ptr) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
var sPtr uintptr
|
||||||
|
var littleEndian bool
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
sPtr = unsafe.Sizeof(byte(0))
|
||||||
|
littleEndian = isLittleEndian()
|
||||||
|
}
|
258
marshal.go
258
marshal.go
|
@ -3,15 +3,16 @@ package ssob
|
||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
"reflect"
|
"reflect"
|
||||||
)
|
)
|
||||||
|
|
||||||
func MarshalString(in string) (ret []byte) {
|
func MarshalString(in string) (ret []byte) {
|
||||||
l := int64(len(in))
|
l := int32(len(in))
|
||||||
b := MarshalInt64(l)
|
b := MarshalInt32(l)
|
||||||
b = append(b, []byte(in)...)
|
ret = make([]byte, int(l)+len(b))
|
||||||
return b
|
copy(ret, b)
|
||||||
|
copy(ret[4:], []byte(in))
|
||||||
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
func MarshalInt8(in int8) (ret []byte) {
|
func MarshalInt8(in int8) (ret []byte) {
|
||||||
|
@ -84,17 +85,72 @@ var encoderCache map[string]MarshalFunc
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
encoderCache = make(map[string]MarshalFunc)
|
encoderCache = make(map[string]MarshalFunc)
|
||||||
encRegister(int8(0))
|
RegisterEncoder("int8", func(e interface{}) (ret []byte, err error) {
|
||||||
encRegister(uint8(0))
|
if i, ok := e.(int8); ok {
|
||||||
encRegister(int16(0))
|
return MarshalInt8(i), nil
|
||||||
encRegister(uint16(0))
|
}
|
||||||
encRegister(int32(0))
|
return nil, errors.New("ssob: Incompatible type - expected int8")
|
||||||
encRegister(uint32(0))
|
})
|
||||||
encRegister(float32(0))
|
RegisterEncoder("uint8", func(e interface{}) (ret []byte, err error) {
|
||||||
encRegister(int64(0))
|
if i, ok := e.(uint8); ok {
|
||||||
encRegister(uint64(0))
|
return MarshalUint8(i), nil
|
||||||
encRegister(float64(0))
|
}
|
||||||
encRegister(string(""))
|
return nil, errors.New("ssob: Incompatible type - expected uint8")
|
||||||
|
})
|
||||||
|
RegisterEncoder("int16", func(e interface{}) (ret []byte, err error) {
|
||||||
|
if i, ok := e.(int16); ok {
|
||||||
|
return MarshalInt16(i), nil
|
||||||
|
}
|
||||||
|
return nil, errors.New("ssob: Incompatible type - expected int16")
|
||||||
|
})
|
||||||
|
RegisterEncoder("uint16", func(e interface{}) (ret []byte, err error) {
|
||||||
|
if i, ok := e.(uint16); ok {
|
||||||
|
return MarshalUint16(i), nil
|
||||||
|
}
|
||||||
|
return nil, errors.New("ssob: Incompatible type - expected uint16")
|
||||||
|
})
|
||||||
|
RegisterEncoder("int32", func(e interface{}) (ret []byte, err error) {
|
||||||
|
if i, ok := e.(int32); ok {
|
||||||
|
return MarshalInt32(i), nil
|
||||||
|
}
|
||||||
|
return nil, errors.New("ssob: Incompatible type - expected int32")
|
||||||
|
})
|
||||||
|
RegisterEncoder("uint32", func(e interface{}) (ret []byte, err error) {
|
||||||
|
if i, ok := e.(uint32); ok {
|
||||||
|
return MarshalUint32(i), nil
|
||||||
|
}
|
||||||
|
return nil, errors.New("ssob: Incompatible type - expected uint32")
|
||||||
|
})
|
||||||
|
RegisterEncoder("float32", func(e interface{}) (ret []byte, err error) {
|
||||||
|
if i, ok := e.(float32); ok {
|
||||||
|
return MarshalFloat32(i), nil
|
||||||
|
}
|
||||||
|
return nil, errors.New("ssob: Incompatible type - expected float32")
|
||||||
|
})
|
||||||
|
RegisterEncoder("int64", func(e interface{}) (ret []byte, err error) {
|
||||||
|
if i, ok := e.(int64); ok {
|
||||||
|
return MarshalInt64(i), nil
|
||||||
|
}
|
||||||
|
return nil, errors.New("ssob: Incompatible type - expected int64")
|
||||||
|
})
|
||||||
|
RegisterEncoder("uint64", func(e interface{}) (ret []byte, err error) {
|
||||||
|
if i, ok := e.(uint64); ok {
|
||||||
|
return MarshalUint64(i), nil
|
||||||
|
}
|
||||||
|
return nil, errors.New("ssob: Incompatible type - expected uint64")
|
||||||
|
})
|
||||||
|
RegisterEncoder("float64", func(e interface{}) (ret []byte, err error) {
|
||||||
|
if i, ok := e.(float64); ok {
|
||||||
|
return MarshalFloat64(i), nil
|
||||||
|
}
|
||||||
|
return nil, errors.New("ssob: Incompatible type - expected float64")
|
||||||
|
})
|
||||||
|
RegisterEncoder("string", func(e interface{}) (ret []byte, err error) {
|
||||||
|
if i, ok := e.(string); ok {
|
||||||
|
return MarshalString(i), nil
|
||||||
|
}
|
||||||
|
return nil, errors.New("ssob: Incompatible type - expected string")
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func encRegister(e interface{}) (err error) {
|
func encRegister(e interface{}) (err error) {
|
||||||
|
@ -107,123 +163,68 @@ func encRegister(e interface{}) (err error) {
|
||||||
f := func(e interface{}) (ret []byte, err error) {
|
f := func(e interface{}) (ret []byte, err error) {
|
||||||
v := reflect.ValueOf(e)
|
v := reflect.ValueOf(e)
|
||||||
l := v.Len()
|
l := v.Len()
|
||||||
ret, err = marshal(int64(l))
|
slen := MarshalInt32(int32(l))
|
||||||
|
blen := 4
|
||||||
|
bs := make([][]byte, l)
|
||||||
|
for i := 0; i < l; i++ {
|
||||||
|
bs[i], err = marshal(v.Index(i).Interface())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
for i := 0; i < l; i++ {
|
blen += len(bs[i])
|
||||||
b, err := marshal(v.Index(i).Interface())
|
}
|
||||||
|
|
||||||
|
ret = make([]byte, blen)
|
||||||
|
i := copy(ret, slen)
|
||||||
|
for c := 0; c < l; c++ {
|
||||||
|
i += copy(ret[i:], bs[c])
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
encoderCache[string(t.Kind())] = f
|
||||||
|
case reflect.Map:
|
||||||
|
f := func(e interface{}) (ret []byte, err error) {
|
||||||
|
v := reflect.ValueOf(e)
|
||||||
|
l := v.Len()
|
||||||
|
ret = MarshalInt32(int32(l))
|
||||||
|
for _, ek := range v.MapKeys() {
|
||||||
|
ee := v.MapIndex(ek)
|
||||||
|
b, err := marshal(ek.Interface())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ret = append(ret, b...)
|
||||||
|
|
||||||
|
b, err = marshal(ee.Interface())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
ret = append(ret, b...)
|
ret = append(ret, b...)
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret, nil
|
return ret, nil
|
||||||
}
|
}
|
||||||
encoderCache[string(t.Kind())] = f
|
encoderCache[string(t.Kind())] = f
|
||||||
case reflect.Struct:
|
case reflect.Struct:
|
||||||
f := func(e interface{}) (ret []byte, err error) {
|
f := func(e interface{}) (ret []byte, err error) {
|
||||||
n := v.NumField()
|
n := v.NumField()
|
||||||
ret = []byte{}
|
bs := make([][]byte, n)
|
||||||
|
blen := 0
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
b, err := marshal(v.Field(i).Interface())
|
bs[i], err = marshal(v.Field(i).Interface())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
ret = append(ret, b...)
|
blen += len(bs[i])
|
||||||
|
}
|
||||||
|
ret = make([]byte, blen)
|
||||||
|
i := 0
|
||||||
|
for c := 0; c < n; c++ {
|
||||||
|
i += copy(ret[i:], bs[c])
|
||||||
}
|
}
|
||||||
return ret, nil
|
return ret, nil
|
||||||
}
|
}
|
||||||
encoderCache[t.Name()] = f
|
encoderCache[t.Name()] = f
|
||||||
case reflect.Int8:
|
|
||||||
f := func(e interface{}) (ret []byte, err error) {
|
|
||||||
if i, ok := e.(int8); ok {
|
|
||||||
return MarshalInt8(i), nil
|
|
||||||
}
|
|
||||||
return nil, errors.New("ssob: Incompatible type " + string(v.Kind()) + " - expected int8")
|
|
||||||
}
|
|
||||||
encoderCache[string(v.Kind())] = f
|
|
||||||
case reflect.Uint8:
|
|
||||||
f := func(e interface{}) (ret []byte, err error) {
|
|
||||||
if i, ok := e.(uint8); ok {
|
|
||||||
return MarshalUint8(i), nil
|
|
||||||
}
|
|
||||||
return nil, errors.New("ssob: Incompatible type " + string(v.Kind()) + " - expected uint8")
|
|
||||||
}
|
|
||||||
encoderCache[string(v.Kind())] = f
|
|
||||||
case reflect.Int16:
|
|
||||||
f := func(e interface{}) (ret []byte, err error) {
|
|
||||||
if i, ok := e.(int16); ok {
|
|
||||||
return MarshalInt16(i), nil
|
|
||||||
}
|
|
||||||
return nil, errors.New("ssob: Incompatible type " + string(v.Kind()) + " - expected int16")
|
|
||||||
}
|
|
||||||
encoderCache[string(v.Kind())] = f
|
|
||||||
case reflect.Uint16:
|
|
||||||
f := func(e interface{}) (ret []byte, err error) {
|
|
||||||
if i, ok := e.(uint16); ok {
|
|
||||||
return MarshalUint16(i), nil
|
|
||||||
}
|
|
||||||
return nil, errors.New("ssob: Incompatible type " + string(v.Kind()) + " - expected uint16")
|
|
||||||
}
|
|
||||||
encoderCache[string(v.Kind())] = f
|
|
||||||
case reflect.Int32:
|
|
||||||
f := func(e interface{}) (ret []byte, err error) {
|
|
||||||
if i, ok := e.(int32); ok {
|
|
||||||
return MarshalInt32(i), nil
|
|
||||||
}
|
|
||||||
return nil, errors.New("ssob: Incompatible type " + string(v.Kind()) + " - expected int32")
|
|
||||||
}
|
|
||||||
encoderCache[string(v.Kind())] = f
|
|
||||||
case reflect.Uint32:
|
|
||||||
f := func(e interface{}) (ret []byte, err error) {
|
|
||||||
if i, ok := e.(uint32); ok {
|
|
||||||
return MarshalUint32(i), nil
|
|
||||||
}
|
|
||||||
return nil, errors.New("ssob: Incompatible type " + string(v.Kind()) + " - expected uint32")
|
|
||||||
}
|
|
||||||
encoderCache[string(v.Kind())] = f
|
|
||||||
case reflect.Float32:
|
|
||||||
f := func(e interface{}) (ret []byte, err error) {
|
|
||||||
if i, ok := e.(float32); ok {
|
|
||||||
return MarshalFloat32(i), nil
|
|
||||||
}
|
|
||||||
return nil, errors.New("ssob: Incompatible type " + string(v.Kind()) + " - expected float32")
|
|
||||||
}
|
|
||||||
encoderCache[string(v.Kind())] = f
|
|
||||||
case reflect.Int64:
|
|
||||||
f := func(e interface{}) (ret []byte, err error) {
|
|
||||||
if i, ok := e.(int64); ok {
|
|
||||||
return MarshalInt64(i), nil
|
|
||||||
}
|
|
||||||
return nil, errors.New("ssob: Incompatible type " + string(v.Kind()) + " - expected int64")
|
|
||||||
}
|
|
||||||
encoderCache[string(v.Kind())] = f
|
|
||||||
case reflect.Uint64:
|
|
||||||
f := func(e interface{}) (ret []byte, err error) {
|
|
||||||
if i, ok := e.(uint64); ok {
|
|
||||||
return MarshalUint64(i), nil
|
|
||||||
}
|
|
||||||
return nil, errors.New("ssob: Incompatible type " + string(v.Kind()) + " - expected uint64")
|
|
||||||
}
|
|
||||||
encoderCache[string(v.Kind())] = f
|
|
||||||
case reflect.Float64:
|
|
||||||
f := func(e interface{}) (ret []byte, err error) {
|
|
||||||
if i, ok := e.(float64); ok {
|
|
||||||
return MarshalFloat64(i), nil
|
|
||||||
}
|
|
||||||
return nil, errors.New("ssob: Incompatible type " + string(v.Kind()) + " - expected float64")
|
|
||||||
}
|
|
||||||
encoderCache[string(v.Kind())] = f
|
|
||||||
case reflect.String:
|
|
||||||
f := func(e interface{}) (ret []byte, err error) {
|
|
||||||
if i, ok := e.(string); ok {
|
|
||||||
return MarshalString(i), nil
|
|
||||||
}
|
|
||||||
return nil, errors.New("ssob: Incompatible type " + string(v.Kind()) + " - expected string")
|
|
||||||
}
|
|
||||||
encoderCache[string(v.Kind())] = f
|
|
||||||
default:
|
default:
|
||||||
return errors.New("ssob: Unknown type " + string(v.Kind()))
|
return errors.New("ssob: Unknown type " + string(v.Kind()))
|
||||||
}
|
}
|
||||||
|
@ -231,7 +232,41 @@ func encRegister(e interface{}) (err error) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func marshalBaseType(e interface{}) (ret []byte, err error) {
|
||||||
|
switch t := e.(type) {
|
||||||
|
case int8:
|
||||||
|
return encoderCache["int8"](t)
|
||||||
|
case uint8:
|
||||||
|
return encoderCache["uint8"](t)
|
||||||
|
case int16:
|
||||||
|
return encoderCache["int16"](t)
|
||||||
|
case uint16:
|
||||||
|
return encoderCache["uint16"](t)
|
||||||
|
case int32:
|
||||||
|
return encoderCache["int32"](t)
|
||||||
|
case uint32:
|
||||||
|
return encoderCache["uint32"](t)
|
||||||
|
case int64:
|
||||||
|
return encoderCache["int64"](t)
|
||||||
|
case uint64:
|
||||||
|
return encoderCache["uint64"](t)
|
||||||
|
case float32:
|
||||||
|
return encoderCache["float32"](t)
|
||||||
|
case float64:
|
||||||
|
return encoderCache["float64"](t)
|
||||||
|
case string:
|
||||||
|
return encoderCache["string"](t)
|
||||||
|
default:
|
||||||
|
return nil, errors.New("ssob: No base type")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func marshal(e interface{}) (ret []byte, err error) {
|
func marshal(e interface{}) (ret []byte, err error) {
|
||||||
|
ret, err = marshalBaseType(e)
|
||||||
|
if err == nil {
|
||||||
|
return ret, err
|
||||||
|
}
|
||||||
|
|
||||||
var key string
|
var key string
|
||||||
t := reflect.TypeOf(e)
|
t := reflect.TypeOf(e)
|
||||||
v := reflect.ValueOf(e)
|
v := reflect.ValueOf(e)
|
||||||
|
@ -251,7 +286,6 @@ func marshal(e interface{}) (ret []byte, err error) {
|
||||||
if f, ok := encoderCache[key]; ok {
|
if f, ok := encoderCache[key]; ok {
|
||||||
return f(e)
|
return f(e)
|
||||||
} else {
|
} else {
|
||||||
fmt.Println("Not found")
|
|
||||||
err = encRegister(e)
|
err = encRegister(e)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
341
unmarshal.go
341
unmarshal.go
|
@ -3,20 +3,19 @@ package ssob
|
||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
"reflect"
|
"reflect"
|
||||||
)
|
)
|
||||||
|
|
||||||
func UnmarshalString(in []byte) (ret string, n int, err error) {
|
func UnmarshalString(in []byte) (ret string, n int, err error) {
|
||||||
if len(in) < 8 {
|
if len(in) < 4 {
|
||||||
return "", 0, errors.New("ssob: Invalid input to decode string")
|
return "", 0, errors.New("ssob: Invalid input to decode string")
|
||||||
}
|
}
|
||||||
l := int64(binary.BigEndian.Uint64(in))
|
l := int32(binary.BigEndian.Uint32(in))
|
||||||
|
|
||||||
if len(in[8:]) < int(l) {
|
if len(in[4:]) < int(l) {
|
||||||
return "", 0, errors.New("ssob: Invalid length of string")
|
return "", 0, errors.New("ssob: Invalid length of string")
|
||||||
}
|
}
|
||||||
return string(in[8 : l+8]), int(l) + 8, nil
|
return string(in[4 : l+4]), int(l) + 4, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func UnmarshalInt8(in []byte) (ret int8, n int, err error) {
|
func UnmarshalInt8(in []byte) (ret int8, n int, err error) {
|
||||||
|
@ -105,17 +104,83 @@ var decoderCache map[string]unmarshalFunc
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
decoderCache = make(map[string]unmarshalFunc)
|
decoderCache = make(map[string]unmarshalFunc)
|
||||||
decRegister(int8(0))
|
RegisterDecoder("int8", func(e interface{}, in []byte) (n int, err error) {
|
||||||
decRegister(uint8(0))
|
if i, ok := e.(*int8); ok {
|
||||||
decRegister(int16(0))
|
*i, n, err = UnmarshalInt8(in)
|
||||||
decRegister(uint16(0))
|
return n, nil
|
||||||
decRegister(int32(0))
|
}
|
||||||
decRegister(uint32(0))
|
return 0, errors.New("ssob: Incompatible type - expected int8")
|
||||||
decRegister(float32(0))
|
})
|
||||||
decRegister(int64(0))
|
RegisterDecoder("uint8", func(e interface{}, in []byte) (n int, err error) {
|
||||||
decRegister(uint64(0))
|
if i, ok := e.(*uint8); ok {
|
||||||
decRegister(float64(0))
|
*i, n, err = UnmarshalUint8(in)
|
||||||
decRegister(string(""))
|
return n, nil
|
||||||
|
}
|
||||||
|
return 0, errors.New("ssob: Incompatible type - expected uint8")
|
||||||
|
})
|
||||||
|
RegisterDecoder("int16", func(e interface{}, in []byte) (n int, err error) {
|
||||||
|
if i, ok := e.(*int16); ok {
|
||||||
|
*i, n, err = UnmarshalInt16(in)
|
||||||
|
return n, nil
|
||||||
|
}
|
||||||
|
return 0, errors.New("ssob: Incompatible type - expected int16")
|
||||||
|
})
|
||||||
|
RegisterDecoder("uint16", func(e interface{}, in []byte) (n int, err error) {
|
||||||
|
if i, ok := e.(*uint16); ok {
|
||||||
|
*i, n, err = UnmarshalUint16(in)
|
||||||
|
return n, nil
|
||||||
|
}
|
||||||
|
return 0, errors.New("ssob: Incompatible type - expected uint16")
|
||||||
|
})
|
||||||
|
RegisterDecoder("int32", func(e interface{}, in []byte) (n int, err error) {
|
||||||
|
if i, ok := e.(*int32); ok {
|
||||||
|
*i, n, err = UnmarshalInt32(in)
|
||||||
|
return n, nil
|
||||||
|
}
|
||||||
|
return 0, errors.New("ssob: Incompatible type - expected int32")
|
||||||
|
})
|
||||||
|
RegisterDecoder("uint32", func(e interface{}, in []byte) (n int, err error) {
|
||||||
|
if i, ok := e.(*uint32); ok {
|
||||||
|
*i, n, err = UnmarshalUint32(in)
|
||||||
|
return n, nil
|
||||||
|
}
|
||||||
|
return 0, errors.New("ssob: Incompatible type - expected uint32")
|
||||||
|
})
|
||||||
|
RegisterDecoder("float32", func(e interface{}, in []byte) (n int, err error) {
|
||||||
|
if i, ok := e.(*float32); ok {
|
||||||
|
*i, n, err = UnmarshalFloat32(in)
|
||||||
|
return n, nil
|
||||||
|
}
|
||||||
|
return 0, errors.New("ssob: Incompatible type - expected float32")
|
||||||
|
})
|
||||||
|
RegisterDecoder("int64", func(e interface{}, in []byte) (n int, err error) {
|
||||||
|
if i, ok := e.(*int64); ok {
|
||||||
|
*i, n, err = UnmarshalInt64(in)
|
||||||
|
return n, nil
|
||||||
|
}
|
||||||
|
return 0, errors.New("ssob: Incompatible type - expected int64")
|
||||||
|
})
|
||||||
|
RegisterDecoder("uint64", func(e interface{}, in []byte) (n int, err error) {
|
||||||
|
if i, ok := e.(*uint64); ok {
|
||||||
|
*i, n, err = UnmarshalUint64(in)
|
||||||
|
return n, nil
|
||||||
|
}
|
||||||
|
return 0, errors.New("ssob: Incompatible type - expected uint64")
|
||||||
|
})
|
||||||
|
RegisterDecoder("float64", func(e interface{}, in []byte) (n int, err error) {
|
||||||
|
if i, ok := e.(*float64); ok {
|
||||||
|
*i, n, err = UnmarshalFloat64(in)
|
||||||
|
return n, nil
|
||||||
|
}
|
||||||
|
return 0, errors.New("ssob: Incompatible type - expected float64")
|
||||||
|
})
|
||||||
|
RegisterDecoder("string", func(e interface{}, in []byte) (n int, err error) {
|
||||||
|
if i, ok := e.(*string); ok {
|
||||||
|
*i, n, err = UnmarshalString(in)
|
||||||
|
return n, nil
|
||||||
|
}
|
||||||
|
return 0, errors.New("ssob: Incompatible type - expected string")
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func decRegister(e interface{}) (err error) {
|
func decRegister(e interface{}) (err error) {
|
||||||
|
@ -125,7 +190,35 @@ func decRegister(e interface{}) (err error) {
|
||||||
case reflect.Invalid:
|
case reflect.Invalid:
|
||||||
return errors.New("ssob: Invalid type")
|
return errors.New("ssob: Invalid type")
|
||||||
case reflect.Slice:
|
case reflect.Slice:
|
||||||
return errors.New("ssob: Unsupported type")
|
f := func(e interface{}, in []byte) (n int, err error) {
|
||||||
|
t := reflect.TypeOf(e)
|
||||||
|
v := reflect.ValueOf(e)
|
||||||
|
pos := 0
|
||||||
|
|
||||||
|
if t.Kind() != reflect.Ptr || v.IsNil() {
|
||||||
|
return 0, errors.New("ssob: Cannot unmarshal to nil pointer")
|
||||||
|
}
|
||||||
|
|
||||||
|
l, r, err := UnmarshalInt32(in)
|
||||||
|
pos += r
|
||||||
|
if err != nil {
|
||||||
|
return pos, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ti := v.Elem()
|
||||||
|
ti.Set(reflect.MakeSlice(reflect.TypeOf(ti.Interface()), 0, ti.Cap()))
|
||||||
|
for i := 0; i < int(l); i++ {
|
||||||
|
e := reflect.New(reflect.TypeOf(ti.Interface()).Elem())
|
||||||
|
r, err := unmarshal(e.Interface(), in[pos:])
|
||||||
|
pos += r
|
||||||
|
if err != nil {
|
||||||
|
return pos, err
|
||||||
|
}
|
||||||
|
ti.Set(reflect.Append(ti, reflect.Indirect(e)))
|
||||||
|
}
|
||||||
|
return pos, nil
|
||||||
|
}
|
||||||
|
decoderCache[string(t.Kind())] = f
|
||||||
case reflect.Struct:
|
case reflect.Struct:
|
||||||
f := func(e interface{}, in []byte) (n int, err error) {
|
f := func(e interface{}, in []byte) (n int, err error) {
|
||||||
t := reflect.TypeOf(e)
|
t := reflect.TypeOf(e)
|
||||||
|
@ -149,171 +242,20 @@ func decRegister(e interface{}) (err error) {
|
||||||
return pos, nil
|
return pos, nil
|
||||||
}
|
}
|
||||||
decoderCache[t.Name()] = f
|
decoderCache[t.Name()] = f
|
||||||
case reflect.Int8:
|
case reflect.Map:
|
||||||
f := func(e interface{}, in []byte) (n int, err error) {
|
return errors.New("ssob: Unsupported type")
|
||||||
if i, ok := e.(*int8); ok {
|
//f := func(e interface{}, in []byte) (n int, err error) {
|
||||||
if i == nil {
|
//t := reflect.TypeOf(e)
|
||||||
return 0, errors.New("ssob: Cannot unmarshal to nil pointer")
|
//v := reflect.ValueOf(e)
|
||||||
}
|
//pos := 0
|
||||||
*i, n, err = UnmarshalInt8(in)
|
|
||||||
if err != nil {
|
//if t.Kind() != reflect.Ptr || v.IsNil() {
|
||||||
return 0, err
|
//return 0, errors.New("ssob: Cannot unmarshal to nil pointer")
|
||||||
}
|
//}
|
||||||
return n, err
|
|
||||||
}
|
//vi := reflect.Indirect(v)
|
||||||
return 0, errors.New("ssob: Incompatible type " + string(v.Kind()) + " - expected *int8")
|
|
||||||
}
|
//}
|
||||||
decoderCache[string(v.Kind())] = f
|
|
||||||
case reflect.Uint8:
|
|
||||||
f := func(e interface{}, in []byte) (n int, err error) {
|
|
||||||
if i, ok := e.(*uint8); ok {
|
|
||||||
if i == nil {
|
|
||||||
return 0, errors.New("ssob: Cannot unmarshal to nil pointer")
|
|
||||||
}
|
|
||||||
*i, n, err = UnmarshalUint8(in)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
return n, err
|
|
||||||
}
|
|
||||||
return 0, errors.New("ssob: Incompatible type " + string(v.Kind()) + " - expected *uint8")
|
|
||||||
}
|
|
||||||
decoderCache[string(v.Kind())] = f
|
|
||||||
case reflect.Int16:
|
|
||||||
f := func(e interface{}, in []byte) (n int, err error) {
|
|
||||||
if i, ok := e.(*int16); ok {
|
|
||||||
if i == nil {
|
|
||||||
return 0, errors.New("ssob: Cannot unmarshal to nil pointer")
|
|
||||||
}
|
|
||||||
*i, n, err = UnmarshalInt16(in)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
return n, err
|
|
||||||
}
|
|
||||||
return 0, errors.New("ssob: Incompatible type " + string(v.Kind()) + " - expected *int16")
|
|
||||||
}
|
|
||||||
decoderCache[string(v.Kind())] = f
|
|
||||||
case reflect.Uint16:
|
|
||||||
f := func(e interface{}, in []byte) (n int, err error) {
|
|
||||||
if i, ok := e.(*uint16); ok {
|
|
||||||
if i == nil {
|
|
||||||
return 0, errors.New("ssob: Cannot unmarshal to nil pointer")
|
|
||||||
}
|
|
||||||
*i, n, err = UnmarshalUint16(in)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
return n, err
|
|
||||||
}
|
|
||||||
return 0, errors.New("ssob: Incompatible type " + string(v.Kind()) + " - expected *uint16")
|
|
||||||
}
|
|
||||||
decoderCache[string(v.Kind())] = f
|
|
||||||
case reflect.Int32:
|
|
||||||
f := func(e interface{}, in []byte) (n int, err error) {
|
|
||||||
if i, ok := e.(*int32); ok {
|
|
||||||
if i == nil {
|
|
||||||
return 0, errors.New("ssob: Cannot unmarshal to nil pointer")
|
|
||||||
}
|
|
||||||
*i, n, err = UnmarshalInt32(in)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
return n, err
|
|
||||||
}
|
|
||||||
return 0, errors.New("ssob: Incompatible type " + string(v.Kind()) + " - expected *int32")
|
|
||||||
}
|
|
||||||
decoderCache[string(v.Kind())] = f
|
|
||||||
case reflect.Uint32:
|
|
||||||
f := func(e interface{}, in []byte) (n int, err error) {
|
|
||||||
if i, ok := e.(*uint32); ok {
|
|
||||||
if i == nil {
|
|
||||||
return 0, errors.New("ssob: Cannot unmarshal to nil pointer")
|
|
||||||
}
|
|
||||||
*i, n, err = UnmarshalUint32(in)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
return n, err
|
|
||||||
}
|
|
||||||
return 0, errors.New("ssob: Incompatible type " + string(v.Kind()) + " - expected *uint32")
|
|
||||||
}
|
|
||||||
decoderCache[string(v.Kind())] = f
|
|
||||||
case reflect.Float32:
|
|
||||||
f := func(e interface{}, in []byte) (n int, err error) {
|
|
||||||
if i, ok := e.(*float32); ok {
|
|
||||||
if i == nil {
|
|
||||||
return 0, errors.New("ssob: Cannot unmarshal to nil pointer")
|
|
||||||
}
|
|
||||||
*i, n, err = UnmarshalFloat32(in)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
return n, err
|
|
||||||
}
|
|
||||||
return 0, errors.New("ssob: Incompatible type " + string(v.Kind()) + " - expected *float32")
|
|
||||||
}
|
|
||||||
decoderCache[string(v.Kind())] = f
|
|
||||||
case reflect.Int64:
|
|
||||||
f := func(e interface{}, in []byte) (n int, err error) {
|
|
||||||
if i, ok := e.(*int64); ok {
|
|
||||||
if i == nil {
|
|
||||||
return 0, errors.New("ssob: Cannot unmarshal to nil pointer")
|
|
||||||
}
|
|
||||||
*i, n, err = UnmarshalInt64(in)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
return n, err
|
|
||||||
}
|
|
||||||
return 0, errors.New("ssob: Incompatible type " + string(v.Kind()) + " - expected *int64")
|
|
||||||
}
|
|
||||||
decoderCache[string(v.Kind())] = f
|
|
||||||
case reflect.Uint64:
|
|
||||||
f := func(e interface{}, in []byte) (n int, err error) {
|
|
||||||
if i, ok := e.(*uint64); ok {
|
|
||||||
if i == nil {
|
|
||||||
return 0, errors.New("ssob: Cannot unmarshal to nil pointer")
|
|
||||||
}
|
|
||||||
*i, n, err = UnmarshalUint64(in)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
return n, err
|
|
||||||
}
|
|
||||||
return 0, errors.New("ssob: Incompatible type " + string(v.Kind()) + " - expected *uint64")
|
|
||||||
}
|
|
||||||
decoderCache[string(v.Kind())] = f
|
|
||||||
case reflect.Float64:
|
|
||||||
f := func(e interface{}, in []byte) (n int, err error) {
|
|
||||||
if i, ok := e.(*float64); ok {
|
|
||||||
if i == nil {
|
|
||||||
return 0, errors.New("ssob: Cannot unmarshal to nil pointer")
|
|
||||||
}
|
|
||||||
*i, n, err = UnmarshalFloat64(in)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
return n, err
|
|
||||||
}
|
|
||||||
return 0, errors.New("ssob: Incompatible type " + string(v.Kind()) + " - expected *float64")
|
|
||||||
}
|
|
||||||
decoderCache[string(v.Kind())] = f
|
|
||||||
case reflect.String:
|
|
||||||
f := func(e interface{}, in []byte) (n int, err error) {
|
|
||||||
if i, ok := e.(*string); ok {
|
|
||||||
if i == nil {
|
|
||||||
return 0, errors.New("ssob: Cannot unmarshal to nil pointer")
|
|
||||||
}
|
|
||||||
*i, n, err = UnmarshalString(in)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
return n, err
|
|
||||||
}
|
|
||||||
return 0, errors.New("ssob: Incompatible type " + string(v.Kind()) + " - expected *string")
|
|
||||||
}
|
|
||||||
decoderCache[string(v.Kind())] = f
|
|
||||||
default:
|
default:
|
||||||
return errors.New("ssob: Unknown type " + string(v.Kind()))
|
return errors.New("ssob: Unknown type " + string(v.Kind()))
|
||||||
}
|
}
|
||||||
|
@ -321,7 +263,41 @@ func decRegister(e interface{}) (err error) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func unmarshalBaseType(e interface{}, in []byte) (n int, err error) {
|
||||||
|
switch t := e.(type) {
|
||||||
|
case *int8:
|
||||||
|
return decoderCache["int8"](t, in)
|
||||||
|
case *uint8:
|
||||||
|
return decoderCache["uint8"](t, in)
|
||||||
|
case *int16:
|
||||||
|
return decoderCache["int16"](t, in)
|
||||||
|
case *uint16:
|
||||||
|
return decoderCache["uint16"](t, in)
|
||||||
|
case *int32:
|
||||||
|
return decoderCache["int32"](t, in)
|
||||||
|
case *uint32:
|
||||||
|
return decoderCache["uint32"](t, in)
|
||||||
|
case *int64:
|
||||||
|
return decoderCache["int64"](t, in)
|
||||||
|
case *uint64:
|
||||||
|
return decoderCache["uint64"](t, in)
|
||||||
|
case *float32:
|
||||||
|
return decoderCache["float32"](t, in)
|
||||||
|
case *float64:
|
||||||
|
return decoderCache["float64"](t, in)
|
||||||
|
case *string:
|
||||||
|
return decoderCache["string"](t, in)
|
||||||
|
default:
|
||||||
|
return 0, errors.New("ssob: No base type")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func unmarshal(e interface{}, in []byte) (n int, err error) {
|
func unmarshal(e interface{}, in []byte) (n int, err error) {
|
||||||
|
n, err = unmarshalBaseType(e, in)
|
||||||
|
if err == nil {
|
||||||
|
return n, err
|
||||||
|
}
|
||||||
|
|
||||||
var key string
|
var key string
|
||||||
t := reflect.TypeOf(e)
|
t := reflect.TypeOf(e)
|
||||||
v := reflect.ValueOf(e)
|
v := reflect.ValueOf(e)
|
||||||
|
@ -340,7 +316,6 @@ func unmarshal(e interface{}, in []byte) (n int, err error) {
|
||||||
if f, ok := decoderCache[key]; ok {
|
if f, ok := decoderCache[key]; ok {
|
||||||
return f(v.Interface(), in)
|
return f(v.Interface(), in)
|
||||||
} else {
|
} else {
|
||||||
fmt.Println("Not found")
|
|
||||||
err = decRegister(p.Interface())
|
err = decRegister(p.Interface())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
package ssob
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
"errors"
|
||||||
|
"io"
|
||||||
|
"reflect"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
type UnsafeEncoder struct {
|
||||||
|
mutex sync.Mutex
|
||||||
|
w io.Writer
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewUnsafeEncoder(w io.Writer) *UnsafeEncoder {
|
||||||
|
enc := new(UnsafeEncoder)
|
||||||
|
enc.w = w
|
||||||
|
return enc
|
||||||
|
}
|
||||||
|
|
||||||
|
func (enc *UnsafeEncoder) Encode(e interface{}) (err error) {
|
||||||
|
return enc.EncodeValue(reflect.ValueOf(e))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (enc *UnsafeEncoder) EncodeValue(value reflect.Value) (err error) {
|
||||||
|
if value.Kind() == reflect.Invalid {
|
||||||
|
return errors.New("ssob: Cannot encode nil value")
|
||||||
|
}
|
||||||
|
|
||||||
|
if value.Kind() == reflect.Ptr && value.IsNil() {
|
||||||
|
return errors.New("ssob: Cannot encode nil of type " + value.Type().String())
|
||||||
|
}
|
||||||
|
|
||||||
|
bb, err := unsafeMarshal(value.Interface())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
bl := UnsafeMarshalInt32(int32(len(bb)))
|
||||||
|
|
||||||
|
w := make([]byte, 4+len(bb))
|
||||||
|
copy(w, bl)
|
||||||
|
copy(w[4:], bb)
|
||||||
|
|
||||||
|
enc.mutex.Lock()
|
||||||
|
defer enc.mutex.Unlock()
|
||||||
|
|
||||||
|
return binary.Write(enc.w, binary.BigEndian, w)
|
||||||
|
}
|
|
@ -0,0 +1,410 @@
|
||||||
|
package ssob
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"reflect"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
func UnsafeMarshalString(in string) (ret []byte) {
|
||||||
|
l := int32(len(in))
|
||||||
|
b := UnsafeMarshalInt32(l)
|
||||||
|
ret = make([]byte, int(l)+len(b))
|
||||||
|
copy(ret, b)
|
||||||
|
copy(ret[4:], []byte(in))
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func UnsafeMarshalInt8(in int8) (ret []byte) {
|
||||||
|
return []byte{byte(in)}
|
||||||
|
}
|
||||||
|
|
||||||
|
func UnsafeMarshalUint8(in uint8) (ret []byte) {
|
||||||
|
return []byte{byte(in)}
|
||||||
|
}
|
||||||
|
|
||||||
|
func UnsafeMarshalInt16(in int16) (ret []byte) {
|
||||||
|
out := make([]byte, 2)
|
||||||
|
|
||||||
|
start := unsafe.Pointer(&in)
|
||||||
|
if littleEndian {
|
||||||
|
out[0] = *(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(1)))
|
||||||
|
out[1] = *(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(0)))
|
||||||
|
} else {
|
||||||
|
out[0] = *(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(0)))
|
||||||
|
out[1] = *(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(1)))
|
||||||
|
}
|
||||||
|
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
func UnsafeMarshalUint16(in uint16) (ret []byte) {
|
||||||
|
out := make([]byte, 2)
|
||||||
|
|
||||||
|
start := unsafe.Pointer(&in)
|
||||||
|
if littleEndian {
|
||||||
|
out[0] = *(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(1)))
|
||||||
|
out[1] = *(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(0)))
|
||||||
|
} else {
|
||||||
|
out[0] = *(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(0)))
|
||||||
|
out[1] = *(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(1)))
|
||||||
|
}
|
||||||
|
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
func UnsafeMarshalInt32(in int32) (ret []byte) {
|
||||||
|
out := make([]byte, 4)
|
||||||
|
|
||||||
|
start := unsafe.Pointer(&in)
|
||||||
|
if littleEndian {
|
||||||
|
out[0] = *(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(3)))
|
||||||
|
out[1] = *(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(2)))
|
||||||
|
out[2] = *(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(1)))
|
||||||
|
out[3] = *(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(0)))
|
||||||
|
} else {
|
||||||
|
out[0] = *(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(0)))
|
||||||
|
out[1] = *(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(1)))
|
||||||
|
out[2] = *(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(2)))
|
||||||
|
out[3] = *(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(3)))
|
||||||
|
}
|
||||||
|
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
func UnsafeMarshalUint32(in uint32) (ret []byte) {
|
||||||
|
out := make([]byte, 4)
|
||||||
|
|
||||||
|
start := unsafe.Pointer(&in)
|
||||||
|
if littleEndian {
|
||||||
|
out[0] = *(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(3)))
|
||||||
|
out[1] = *(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(2)))
|
||||||
|
out[2] = *(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(1)))
|
||||||
|
out[3] = *(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(0)))
|
||||||
|
} else {
|
||||||
|
out[0] = *(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(0)))
|
||||||
|
out[1] = *(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(1)))
|
||||||
|
out[2] = *(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(2)))
|
||||||
|
out[3] = *(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(3)))
|
||||||
|
}
|
||||||
|
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
func UnsafeMarshalFloat32(in float32) (ret []byte) {
|
||||||
|
out := make([]byte, 4)
|
||||||
|
|
||||||
|
start := unsafe.Pointer(&in)
|
||||||
|
if littleEndian {
|
||||||
|
out[0] = *(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(3)))
|
||||||
|
out[1] = *(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(2)))
|
||||||
|
out[2] = *(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(1)))
|
||||||
|
out[3] = *(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(0)))
|
||||||
|
} else {
|
||||||
|
out[0] = *(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(0)))
|
||||||
|
out[1] = *(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(1)))
|
||||||
|
out[2] = *(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(2)))
|
||||||
|
out[3] = *(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(3)))
|
||||||
|
}
|
||||||
|
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
func UnsafeMarshalInt64(in int64) (ret []byte) {
|
||||||
|
out := make([]byte, 8)
|
||||||
|
|
||||||
|
start := unsafe.Pointer(&in)
|
||||||
|
if littleEndian {
|
||||||
|
out[0] = *(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(7)))
|
||||||
|
out[1] = *(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(6)))
|
||||||
|
out[2] = *(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(5)))
|
||||||
|
out[3] = *(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(4)))
|
||||||
|
out[4] = *(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(3)))
|
||||||
|
out[5] = *(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(2)))
|
||||||
|
out[6] = *(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(1)))
|
||||||
|
out[7] = *(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(0)))
|
||||||
|
} else {
|
||||||
|
out[0] = *(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(0)))
|
||||||
|
out[1] = *(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(1)))
|
||||||
|
out[2] = *(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(2)))
|
||||||
|
out[3] = *(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(3)))
|
||||||
|
out[4] = *(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(4)))
|
||||||
|
out[5] = *(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(5)))
|
||||||
|
out[6] = *(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(6)))
|
||||||
|
out[7] = *(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(7)))
|
||||||
|
}
|
||||||
|
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
func UnsafeMarshalUint64(in uint64) (ret []byte) {
|
||||||
|
out := make([]byte, 8)
|
||||||
|
|
||||||
|
start := unsafe.Pointer(&in)
|
||||||
|
if littleEndian {
|
||||||
|
out[0] = *(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(7)))
|
||||||
|
out[1] = *(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(6)))
|
||||||
|
out[2] = *(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(5)))
|
||||||
|
out[3] = *(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(4)))
|
||||||
|
out[4] = *(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(3)))
|
||||||
|
out[5] = *(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(2)))
|
||||||
|
out[6] = *(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(1)))
|
||||||
|
out[7] = *(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(0)))
|
||||||
|
} else {
|
||||||
|
out[0] = *(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(0)))
|
||||||
|
out[1] = *(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(1)))
|
||||||
|
out[2] = *(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(2)))
|
||||||
|
out[3] = *(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(3)))
|
||||||
|
out[4] = *(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(4)))
|
||||||
|
out[5] = *(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(5)))
|
||||||
|
out[6] = *(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(6)))
|
||||||
|
out[7] = *(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(7)))
|
||||||
|
}
|
||||||
|
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
func UnsafeMarshalFloat64(in float64) (ret []byte) {
|
||||||
|
out := make([]byte, 8)
|
||||||
|
|
||||||
|
start := unsafe.Pointer(&in)
|
||||||
|
if littleEndian {
|
||||||
|
out[0] = *(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(7)))
|
||||||
|
out[1] = *(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(6)))
|
||||||
|
out[2] = *(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(5)))
|
||||||
|
out[3] = *(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(4)))
|
||||||
|
out[4] = *(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(3)))
|
||||||
|
out[5] = *(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(2)))
|
||||||
|
out[6] = *(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(1)))
|
||||||
|
out[7] = *(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(0)))
|
||||||
|
} else {
|
||||||
|
out[0] = *(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(0)))
|
||||||
|
out[1] = *(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(1)))
|
||||||
|
out[2] = *(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(2)))
|
||||||
|
out[3] = *(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(3)))
|
||||||
|
out[4] = *(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(4)))
|
||||||
|
out[5] = *(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(5)))
|
||||||
|
out[6] = *(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(6)))
|
||||||
|
out[7] = *(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(7)))
|
||||||
|
}
|
||||||
|
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
var unsafeEncoderCache map[string]MarshalFunc
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
unsafeEncoderCache = make(map[string]MarshalFunc)
|
||||||
|
RegisterUnsafeEncoder("int8", func(e interface{}) (ret []byte, err error) {
|
||||||
|
if i, ok := e.(int8); ok {
|
||||||
|
return UnsafeMarshalInt8(i), nil
|
||||||
|
}
|
||||||
|
return nil, errors.New("ssob: Incompatible type - expected int8")
|
||||||
|
})
|
||||||
|
RegisterUnsafeEncoder("uint8", func(e interface{}) (ret []byte, err error) {
|
||||||
|
if i, ok := e.(uint8); ok {
|
||||||
|
return UnsafeMarshalUint8(i), nil
|
||||||
|
}
|
||||||
|
return nil, errors.New("ssob: Incompatible type - expected uint8")
|
||||||
|
})
|
||||||
|
RegisterUnsafeEncoder("int16", func(e interface{}) (ret []byte, err error) {
|
||||||
|
if i, ok := e.(int16); ok {
|
||||||
|
return UnsafeMarshalInt16(i), nil
|
||||||
|
}
|
||||||
|
return nil, errors.New("ssob: Incompatible type - expected int16")
|
||||||
|
})
|
||||||
|
RegisterUnsafeEncoder("uint16", func(e interface{}) (ret []byte, err error) {
|
||||||
|
if i, ok := e.(uint16); ok {
|
||||||
|
return UnsafeMarshalUint16(i), nil
|
||||||
|
}
|
||||||
|
return nil, errors.New("ssob: Incompatible type - expected uint16")
|
||||||
|
})
|
||||||
|
RegisterUnsafeEncoder("int32", func(e interface{}) (ret []byte, err error) {
|
||||||
|
if i, ok := e.(int32); ok {
|
||||||
|
return UnsafeMarshalInt32(i), nil
|
||||||
|
}
|
||||||
|
return nil, errors.New("ssob: Incompatible type - expected int32")
|
||||||
|
})
|
||||||
|
RegisterUnsafeEncoder("uint32", func(e interface{}) (ret []byte, err error) {
|
||||||
|
if i, ok := e.(uint32); ok {
|
||||||
|
return UnsafeMarshalUint32(i), nil
|
||||||
|
}
|
||||||
|
return nil, errors.New("ssob: Incompatible type - expected uint32")
|
||||||
|
})
|
||||||
|
RegisterUnsafeEncoder("float32", func(e interface{}) (ret []byte, err error) {
|
||||||
|
if i, ok := e.(float32); ok {
|
||||||
|
return UnsafeMarshalFloat32(i), nil
|
||||||
|
}
|
||||||
|
return nil, errors.New("ssob: Incompatible type - expected float32")
|
||||||
|
})
|
||||||
|
RegisterUnsafeEncoder("int64", func(e interface{}) (ret []byte, err error) {
|
||||||
|
if i, ok := e.(int64); ok {
|
||||||
|
return UnsafeMarshalInt64(i), nil
|
||||||
|
}
|
||||||
|
return nil, errors.New("ssob: Incompatible type - expected int64")
|
||||||
|
})
|
||||||
|
RegisterUnsafeEncoder("uint64", func(e interface{}) (ret []byte, err error) {
|
||||||
|
if i, ok := e.(uint64); ok {
|
||||||
|
return UnsafeMarshalUint64(i), nil
|
||||||
|
}
|
||||||
|
return nil, errors.New("ssob: Incompatible type - expected uint64")
|
||||||
|
})
|
||||||
|
RegisterUnsafeEncoder("float64", func(e interface{}) (ret []byte, err error) {
|
||||||
|
if i, ok := e.(float64); ok {
|
||||||
|
return UnsafeMarshalFloat64(i), nil
|
||||||
|
}
|
||||||
|
return nil, errors.New("ssob: Incompatible type - expected float64")
|
||||||
|
})
|
||||||
|
RegisterUnsafeEncoder("string", func(e interface{}) (ret []byte, err error) {
|
||||||
|
if i, ok := e.(string); ok {
|
||||||
|
return UnsafeMarshalString(i), nil
|
||||||
|
}
|
||||||
|
return nil, errors.New("ssob: Incompatible type - expected string")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func encRegisterUnsafe(e interface{}) (err error) {
|
||||||
|
v := reflect.ValueOf(e)
|
||||||
|
t := reflect.TypeOf(e)
|
||||||
|
switch t.Kind() {
|
||||||
|
case reflect.Invalid:
|
||||||
|
return errors.New("ssob: Invalid type")
|
||||||
|
case reflect.Slice:
|
||||||
|
f := func(e interface{}) (ret []byte, err error) {
|
||||||
|
v := reflect.ValueOf(e)
|
||||||
|
l := v.Len()
|
||||||
|
slen := UnsafeMarshalInt32(int32(l))
|
||||||
|
blen := 4
|
||||||
|
bs := make([][]byte, l)
|
||||||
|
for i := 0; i < l; i++ {
|
||||||
|
bs[i], err = unsafeMarshal(v.Index(i).Interface())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
blen += len(bs[i])
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = make([]byte, blen)
|
||||||
|
i := copy(ret, slen)
|
||||||
|
for c := 0; c < l; c++ {
|
||||||
|
i += copy(ret[i:], bs[c])
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
unsafeEncoderCache[string(t.Kind())] = f
|
||||||
|
case reflect.Map:
|
||||||
|
f := func(e interface{}) (ret []byte, err error) {
|
||||||
|
v := reflect.ValueOf(e)
|
||||||
|
l := v.Len()
|
||||||
|
ret = UnsafeMarshalInt32(int32(l))
|
||||||
|
for _, ek := range v.MapKeys() {
|
||||||
|
ee := v.MapIndex(ek)
|
||||||
|
b, err := unsafeMarshal(ek.Interface())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ret = append(ret, b...)
|
||||||
|
|
||||||
|
b, err = unsafeMarshal(ee.Interface())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ret = append(ret, b...)
|
||||||
|
}
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
unsafeEncoderCache[string(t.Kind())] = f
|
||||||
|
case reflect.Struct:
|
||||||
|
f := func(e interface{}) (ret []byte, err error) {
|
||||||
|
n := v.NumField()
|
||||||
|
bs := make([][]byte, n)
|
||||||
|
blen := 0
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
bs[i], err = unsafeMarshal(v.Field(i).Interface())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
blen += len(bs[i])
|
||||||
|
}
|
||||||
|
ret = make([]byte, blen)
|
||||||
|
i := 0
|
||||||
|
for c := 0; c < n; c++ {
|
||||||
|
i += copy(ret[i:], bs[c])
|
||||||
|
}
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
unsafeEncoderCache[t.Name()] = f
|
||||||
|
default:
|
||||||
|
return errors.New("ssob: Unknown type " + string(v.Kind()))
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func unsafeMarshalBaseType(e interface{}) (ret []byte, err error) {
|
||||||
|
switch t := e.(type) {
|
||||||
|
case int8:
|
||||||
|
return unsafeEncoderCache["int8"](t)
|
||||||
|
case uint8:
|
||||||
|
return unsafeEncoderCache["uint8"](t)
|
||||||
|
case int16:
|
||||||
|
return unsafeEncoderCache["int16"](t)
|
||||||
|
case uint16:
|
||||||
|
return unsafeEncoderCache["uint16"](t)
|
||||||
|
case int32:
|
||||||
|
return unsafeEncoderCache["int32"](t)
|
||||||
|
case uint32:
|
||||||
|
return unsafeEncoderCache["uint32"](t)
|
||||||
|
case int64:
|
||||||
|
return unsafeEncoderCache["int64"](t)
|
||||||
|
case uint64:
|
||||||
|
return unsafeEncoderCache["uint64"](t)
|
||||||
|
case float32:
|
||||||
|
return unsafeEncoderCache["float32"](t)
|
||||||
|
case float64:
|
||||||
|
return unsafeEncoderCache["float64"](t)
|
||||||
|
case string:
|
||||||
|
return unsafeEncoderCache["string"](t)
|
||||||
|
default:
|
||||||
|
return nil, errors.New("ssob: No base type")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func unsafeMarshal(e interface{}) (ret []byte, err error) {
|
||||||
|
ret, err = unsafeMarshalBaseType(e)
|
||||||
|
if err == nil {
|
||||||
|
return ret, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var key string
|
||||||
|
t := reflect.TypeOf(e)
|
||||||
|
v := reflect.ValueOf(e)
|
||||||
|
if t.Kind() == reflect.Ptr {
|
||||||
|
if v.IsNil() {
|
||||||
|
return nil, errors.New("ssob: Cannot marshal nil pointer")
|
||||||
|
}
|
||||||
|
p := reflect.Indirect(v)
|
||||||
|
return unsafeMarshal(p.Interface())
|
||||||
|
}
|
||||||
|
if t.Kind() == reflect.Struct {
|
||||||
|
key = reflect.TypeOf(e).Name()
|
||||||
|
} else {
|
||||||
|
key = string(t.Kind())
|
||||||
|
}
|
||||||
|
|
||||||
|
if f, ok := unsafeEncoderCache[key]; ok {
|
||||||
|
return f(e)
|
||||||
|
} else {
|
||||||
|
err = encRegisterUnsafe(e)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return unsafeMarshal(e)
|
||||||
|
}
|
||||||
|
|
||||||
|
func RegisterUnsafeEncoder(name string, f MarshalFunc) {
|
||||||
|
unsafeEncoderCache[name] = f
|
||||||
|
}
|
Loading…
Reference in New Issue