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()
|
||||
defer dec.mutex.Unlock()
|
||||
|
||||
lb := make([]byte, 8)
|
||||
lb := make([]byte, 4)
|
||||
err = binary.Read(dec.r, binary.BigEndian, lb)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
l, n, err := UnmarshalInt64(lb)
|
||||
if err != nil || n != 8 {
|
||||
l, n, err := UnmarshalInt32(lb)
|
||||
if err != nil || n != 4 {
|
||||
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())
|
||||
}
|
||||
|
||||
b, err := marshal(value.Interface())
|
||||
bb, err := marshal(value.Interface())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
bb := MarshalInt64(int64(len(b)))
|
||||
bb = append(bb, b...)
|
||||
bl := MarshalInt32(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, 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 (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
func MarshalString(in string) (ret []byte) {
|
||||
l := int64(len(in))
|
||||
b := MarshalInt64(l)
|
||||
b = append(b, []byte(in)...)
|
||||
return b
|
||||
l := int32(len(in))
|
||||
b := MarshalInt32(l)
|
||||
ret = make([]byte, int(l)+len(b))
|
||||
copy(ret, b)
|
||||
copy(ret[4:], []byte(in))
|
||||
return ret
|
||||
}
|
||||
|
||||
func MarshalInt8(in int8) (ret []byte) {
|
||||
|
@ -84,17 +85,72 @@ var encoderCache map[string]MarshalFunc
|
|||
|
||||
func init() {
|
||||
encoderCache = make(map[string]MarshalFunc)
|
||||
encRegister(int8(0))
|
||||
encRegister(uint8(0))
|
||||
encRegister(int16(0))
|
||||
encRegister(uint16(0))
|
||||
encRegister(int32(0))
|
||||
encRegister(uint32(0))
|
||||
encRegister(float32(0))
|
||||
encRegister(int64(0))
|
||||
encRegister(uint64(0))
|
||||
encRegister(float64(0))
|
||||
encRegister(string(""))
|
||||
RegisterEncoder("int8", func(e interface{}) (ret []byte, err error) {
|
||||
if i, ok := e.(int8); ok {
|
||||
return MarshalInt8(i), nil
|
||||
}
|
||||
return nil, errors.New("ssob: Incompatible type - expected int8")
|
||||
})
|
||||
RegisterEncoder("uint8", func(e interface{}) (ret []byte, err error) {
|
||||
if i, ok := e.(uint8); ok {
|
||||
return MarshalUint8(i), nil
|
||||
}
|
||||
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) {
|
||||
|
@ -107,123 +163,68 @@ func encRegister(e interface{}) (err error) {
|
|||
f := func(e interface{}) (ret []byte, err error) {
|
||||
v := reflect.ValueOf(e)
|
||||
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 {
|
||||
return nil, err
|
||||
}
|
||||
for i := 0; i < l; i++ {
|
||||
b, err := marshal(v.Index(i).Interface())
|
||||
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
|
||||
}
|
||||
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 {
|
||||
return nil, err
|
||||
}
|
||||
ret = append(ret, b...)
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
encoderCache[string(t.Kind())] = f
|
||||
case reflect.Struct:
|
||||
f := func(e interface{}) (ret []byte, err error) {
|
||||
n := v.NumField()
|
||||
ret = []byte{}
|
||||
bs := make([][]byte, n)
|
||||
blen := 0
|
||||
for i := 0; i < n; i++ {
|
||||
b, err := marshal(v.Field(i).Interface())
|
||||
bs[i], err = marshal(v.Field(i).Interface())
|
||||
if err != nil {
|
||||
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
|
||||
}
|
||||
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:
|
||||
return errors.New("ssob: Unknown type " + string(v.Kind()))
|
||||
}
|
||||
|
@ -231,7 +232,41 @@ func encRegister(e interface{}) (err error) {
|
|||
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) {
|
||||
ret, err = marshalBaseType(e)
|
||||
if err == nil {
|
||||
return ret, err
|
||||
}
|
||||
|
||||
var key string
|
||||
t := reflect.TypeOf(e)
|
||||
v := reflect.ValueOf(e)
|
||||
|
@ -251,7 +286,6 @@ func marshal(e interface{}) (ret []byte, err error) {
|
|||
if f, ok := encoderCache[key]; ok {
|
||||
return f(e)
|
||||
} else {
|
||||
fmt.Println("Not found")
|
||||
err = encRegister(e)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
341
unmarshal.go
341
unmarshal.go
|
@ -3,20 +3,19 @@ package ssob
|
|||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
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")
|
||||
}
|
||||
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 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) {
|
||||
|
@ -105,17 +104,83 @@ var decoderCache map[string]unmarshalFunc
|
|||
|
||||
func init() {
|
||||
decoderCache = make(map[string]unmarshalFunc)
|
||||
decRegister(int8(0))
|
||||
decRegister(uint8(0))
|
||||
decRegister(int16(0))
|
||||
decRegister(uint16(0))
|
||||
decRegister(int32(0))
|
||||
decRegister(uint32(0))
|
||||
decRegister(float32(0))
|
||||
decRegister(int64(0))
|
||||
decRegister(uint64(0))
|
||||
decRegister(float64(0))
|
||||
decRegister(string(""))
|
||||
RegisterDecoder("int8", func(e interface{}, in []byte) (n int, err error) {
|
||||
if i, ok := e.(*int8); ok {
|
||||
*i, n, err = UnmarshalInt8(in)
|
||||
return n, nil
|
||||
}
|
||||
return 0, errors.New("ssob: Incompatible type - expected int8")
|
||||
})
|
||||
RegisterDecoder("uint8", func(e interface{}, in []byte) (n int, err error) {
|
||||
if i, ok := e.(*uint8); ok {
|
||||
*i, n, err = UnmarshalUint8(in)
|
||||
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) {
|
||||
|
@ -125,7 +190,35 @@ func decRegister(e interface{}) (err error) {
|
|||
case reflect.Invalid:
|
||||
return errors.New("ssob: Invalid type")
|
||||
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:
|
||||
f := func(e interface{}, in []byte) (n int, err error) {
|
||||
t := reflect.TypeOf(e)
|
||||
|
@ -149,171 +242,20 @@ func decRegister(e interface{}) (err error) {
|
|||
return pos, nil
|
||||
}
|
||||
decoderCache[t.Name()] = f
|
||||
case reflect.Int8:
|
||||
f := func(e interface{}, in []byte) (n int, err error) {
|
||||
if i, ok := e.(*int8); ok {
|
||||
if i == nil {
|
||||
return 0, errors.New("ssob: Cannot unmarshal to nil pointer")
|
||||
}
|
||||
*i, n, err = UnmarshalInt8(in)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return n, err
|
||||
}
|
||||
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
|
||||
case reflect.Map:
|
||||
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")
|
||||
//}
|
||||
|
||||
//vi := reflect.Indirect(v)
|
||||
|
||||
//}
|
||||
default:
|
||||
return errors.New("ssob: Unknown type " + string(v.Kind()))
|
||||
}
|
||||
|
@ -321,7 +263,41 @@ func decRegister(e interface{}) (err error) {
|
|||
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) {
|
||||
n, err = unmarshalBaseType(e, in)
|
||||
if err == nil {
|
||||
return n, err
|
||||
}
|
||||
|
||||
var key string
|
||||
t := reflect.TypeOf(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 {
|
||||
return f(v.Interface(), in)
|
||||
} else {
|
||||
fmt.Println("Not found")
|
||||
err = decRegister(p.Interface())
|
||||
if err != nil {
|
||||
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