Added more types. Implemented unsafe marshalling for faster

serialization
This commit is contained in:
Matthias Fulz 2019-10-05 01:42:09 +02:00
parent 17f127cdb6
commit b398aec2ed
7 changed files with 797 additions and 304 deletions

View File

@ -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
} }

View File

@ -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)
} }

22
endianess.go Normal file
View File

@ -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()
}

View File

@ -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

View File

@ -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

49
unsafe_encoder.go Normal file
View File

@ -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)
}

410
unsafe_marshal.go Normal file
View File

@ -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
}