2019-10-05 01:42:09 +02:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2019-10-05 22:12:53 +02:00
|
|
|
func UnsafeMarshalBool(in bool) (ret []byte) {
|
|
|
|
if in {
|
|
|
|
return []byte{byte(0)}
|
|
|
|
}
|
|
|
|
|
|
|
|
return []byte{byte(1)}
|
|
|
|
}
|
|
|
|
|
2019-10-05 01:42:09 +02:00
|
|
|
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)
|
2019-10-05 22:12:53 +02:00
|
|
|
RegisterUnsafeEncoder("bool", func(e interface{}) (ret []byte, err error) {
|
|
|
|
if i, ok := e.(bool); ok {
|
|
|
|
return UnsafeMarshalBool(i), nil
|
|
|
|
}
|
|
|
|
return nil, errors.New("ssob: Incompatible type - expected bool")
|
|
|
|
})
|
2019-10-05 01:42:09 +02:00
|
|
|
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")
|
2019-10-05 22:12:53 +02:00
|
|
|
case reflect.Array:
|
|
|
|
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
|
2019-10-05 01:42:09 +02:00
|
|
|
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:
|
2019-11-03 21:30:50 +01:00
|
|
|
zt := reflect.New(t)
|
|
|
|
n := zt.Elem().NumField()
|
|
|
|
mfields := []int{}
|
|
|
|
for i := 0; i < n; i++ {
|
|
|
|
if zt.Elem().Field(i).CanSet() {
|
|
|
|
mfields = append(mfields, i)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if len(mfields) == 0 {
|
|
|
|
return errors.New("ssob: No exported fields for " + string(t.Name()))
|
|
|
|
}
|
|
|
|
|
2019-10-05 01:42:09 +02:00
|
|
|
f := func(e interface{}) (ret []byte, err error) {
|
|
|
|
bs := make([][]byte, n)
|
|
|
|
blen := 0
|
2019-11-03 21:30:50 +01:00
|
|
|
for _, i := range mfields {
|
2019-10-05 01:42:09 +02:00
|
|
|
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
|
2019-10-22 15:14:26 +02:00
|
|
|
case reflect.Bool:
|
|
|
|
f := func(e interface{}) (ret []byte, err error) {
|
|
|
|
return unsafeMarshalBaseType(bool(v.Bool()))
|
|
|
|
}
|
|
|
|
unsafeEncoderCache[t.Name()] = f
|
|
|
|
case reflect.Uint8:
|
|
|
|
f := func(e interface{}) (ret []byte, err error) {
|
|
|
|
return unsafeMarshalBaseType(string(v.String()))
|
|
|
|
}
|
|
|
|
unsafeEncoderCache[t.Name()] = f
|
|
|
|
case reflect.Uint16:
|
|
|
|
f := func(e interface{}) (ret []byte, err error) {
|
|
|
|
return unsafeMarshalBaseType(string(v.String()))
|
|
|
|
}
|
|
|
|
unsafeEncoderCache[t.Name()] = f
|
|
|
|
case reflect.Uint32:
|
|
|
|
f := func(e interface{}) (ret []byte, err error) {
|
|
|
|
return unsafeMarshalBaseType(string(v.String()))
|
|
|
|
}
|
|
|
|
unsafeEncoderCache[t.Name()] = f
|
|
|
|
case reflect.Uint64:
|
|
|
|
f := func(e interface{}) (ret []byte, err error) {
|
|
|
|
return unsafeMarshalBaseType(string(v.String()))
|
|
|
|
}
|
|
|
|
unsafeEncoderCache[t.Name()] = f
|
|
|
|
case reflect.Int8:
|
|
|
|
f := func(e interface{}) (ret []byte, err error) {
|
|
|
|
return unsafeMarshalBaseType(string(v.String()))
|
|
|
|
}
|
|
|
|
unsafeEncoderCache[t.Name()] = f
|
|
|
|
case reflect.Int16:
|
|
|
|
f := func(e interface{}) (ret []byte, err error) {
|
|
|
|
return unsafeMarshalBaseType(string(v.String()))
|
|
|
|
}
|
|
|
|
unsafeEncoderCache[t.Name()] = f
|
|
|
|
case reflect.Int32:
|
|
|
|
f := func(e interface{}) (ret []byte, err error) {
|
|
|
|
return unsafeMarshalBaseType(string(v.String()))
|
|
|
|
}
|
|
|
|
unsafeEncoderCache[t.Name()] = f
|
|
|
|
case reflect.Int64:
|
|
|
|
f := func(e interface{}) (ret []byte, err error) {
|
|
|
|
return unsafeMarshalBaseType(string(v.String()))
|
|
|
|
}
|
|
|
|
unsafeEncoderCache[t.Name()] = f
|
|
|
|
case reflect.String:
|
|
|
|
f := func(e interface{}) (ret []byte, err error) {
|
|
|
|
return unsafeMarshalBaseType(string(v.String()))
|
|
|
|
}
|
|
|
|
unsafeEncoderCache[t.Name()] = f
|
2019-10-05 01:42:09 +02:00
|
|
|
default:
|
2019-10-22 15:14:26 +02:00
|
|
|
return errors.New("ssob: Unknown type " + string(t.Name()))
|
2019-10-05 01:42:09 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func unsafeMarshalBaseType(e interface{}) (ret []byte, err error) {
|
|
|
|
switch t := e.(type) {
|
2019-10-05 22:12:53 +02:00
|
|
|
case bool:
|
|
|
|
return unsafeEncoderCache["bool"](t)
|
2019-10-05 01:42:09 +02:00
|
|
|
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)
|
2019-10-22 15:14:26 +02:00
|
|
|
switch t.Kind() {
|
|
|
|
case reflect.Ptr:
|
2019-10-05 01:42:09 +02:00
|
|
|
if v.IsNil() {
|
|
|
|
return nil, errors.New("ssob: Cannot marshal nil pointer")
|
|
|
|
}
|
|
|
|
p := reflect.Indirect(v)
|
|
|
|
return unsafeMarshal(p.Interface())
|
2019-10-22 15:14:26 +02:00
|
|
|
case reflect.Bool, reflect.Int8, reflect.Int16, reflect.Int32,
|
|
|
|
reflect.Int64, reflect.Uint8, reflect.Uint16, reflect.Uint32,
|
|
|
|
reflect.Uint64, reflect.String, reflect.Struct:
|
|
|
|
key = t.Name()
|
|
|
|
default:
|
2019-10-05 01:42:09 +02:00
|
|
|
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
|
|
|
|
}
|