Cleanup
This commit is contained in:
parent
a8d0eabd84
commit
c228d3fcce
58
decoder.go
58
decoder.go
|
@ -2,13 +2,9 @@ package ssob
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"reflect"
|
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"gitea.olznet.de/OlzNet/slog"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Decoder struct {
|
type Decoder struct {
|
||||||
|
@ -22,56 +18,7 @@ func NewDecoder(r io.Reader) *Decoder {
|
||||||
return dec
|
return dec
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dec *Decoder) Decode(e interface{}) (err error) {
|
func (dec *Decoder) Decode() (ret interface{}, err error) {
|
||||||
t := reflect.TypeOf(e)
|
|
||||||
slog.LOG_DEBUGFLN("Dec: %v", t)
|
|
||||||
if t == reflect.TypeOf(errors.New("")) || t == reflect.TypeOf((*error)(nil)) {
|
|
||||||
var errstr string
|
|
||||||
if err = dec.Decode(&errstr); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if errstr != "" {
|
|
||||||
*e.(*error) = errors.New(errstr)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return dec.DecodeValue(reflect.ValueOf(e))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (dec *Decoder) DecodeValue(value reflect.Value) (err error) {
|
|
||||||
if value.Kind() == reflect.Invalid {
|
|
||||||
return fmt.Errorf("ssob: Cannot decode nil: %w", ErrValueInvalid)
|
|
||||||
}
|
|
||||||
|
|
||||||
if value.Kind() == reflect.Ptr && value.IsNil() {
|
|
||||||
return fmt.Errorf("ssob: Cannot decode nil of type %s: %w", value.Type().String(), ErrValueInvalid)
|
|
||||||
}
|
|
||||||
|
|
||||||
dec.mutex.Lock()
|
|
||||||
defer dec.mutex.Unlock()
|
|
||||||
|
|
||||||
lb := make([]byte, 4)
|
|
||||||
err = binary.Read(dec.r, binary.BigEndian, lb)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
l, n, err := UnmarshalInt32(lb)
|
|
||||||
if err != nil || n != 4 {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
bb := make([]byte, l)
|
|
||||||
err = binary.Read(dec.r, binary.BigEndian, bb)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = unmarshal(value.Interface(), bb)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (dec *Decoder) NDecode() (ret interface{}, err error) {
|
|
||||||
st := make([]byte, ST_ID_SIZE)
|
st := make([]byte, ST_ID_SIZE)
|
||||||
|
|
||||||
dec.mutex.Lock()
|
dec.mutex.Lock()
|
||||||
|
@ -84,8 +31,7 @@ func (dec *Decoder) NDecode() (ret interface{}, err error) {
|
||||||
l := binary.BigEndian.Uint32(st)
|
l := binary.BigEndian.Uint32(st)
|
||||||
b := make([]byte, l)
|
b := make([]byte, l)
|
||||||
|
|
||||||
var rl int
|
if err = binary.Read(dec.r, binary.BigEndian, b); err != nil {
|
||||||
if rl, err = dec.r.Read(b); err != nil || rl != int(l) {
|
|
||||||
return nil, fmt.Errorf("ssob: Cannot decode value: %w", err)
|
return nil, fmt.Errorf("ssob: Cannot decode value: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
83
encoder.go
83
encoder.go
|
@ -1,11 +1,8 @@
|
||||||
package ssob
|
package ssob
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/binary"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"reflect"
|
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"gitea.olznet.de/OlzNet/slog"
|
"gitea.olznet.de/OlzNet/slog"
|
||||||
|
@ -23,51 +20,6 @@ func NewEncoder(w io.Writer) *Encoder {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (enc *Encoder) Encode(e interface{}) (err error) {
|
func (enc *Encoder) Encode(e interface{}) (err error) {
|
||||||
t := reflect.TypeOf(e)
|
|
||||||
slog.LOG_DEBUGFLN("Enc: %v", t)
|
|
||||||
if t == reflect.TypeOf(errors.New("")) || t == reflect.TypeOf((*error)(nil)).Elem() {
|
|
||||||
if reflect.ValueOf(e).IsNil() {
|
|
||||||
return enc.Encode(string(""))
|
|
||||||
} else {
|
|
||||||
return enc.Encode(e.(error).Error())
|
|
||||||
}
|
|
||||||
} else if t == reflect.TypeOf((*error)(nil)) {
|
|
||||||
if reflect.Indirect(reflect.ValueOf(e)).IsNil() {
|
|
||||||
return enc.Encode(string(""))
|
|
||||||
} else {
|
|
||||||
return enc.Encode((*e.(*error)).Error())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return enc.EncodeValue(reflect.ValueOf(e))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (enc *Encoder) EncodeValue(value reflect.Value) (err error) {
|
|
||||||
if value.Kind() == reflect.Invalid {
|
|
||||||
return fmt.Errorf("ssob: Cannot encode nil: %w", ErrValueInvalid)
|
|
||||||
}
|
|
||||||
|
|
||||||
if value.Kind() == reflect.Ptr && value.IsNil() {
|
|
||||||
return fmt.Errorf("ssob: Cannot encode nil of type %s: %w", value.Type().String(), ErrValueInvalid)
|
|
||||||
}
|
|
||||||
|
|
||||||
bb, err := marshal(value.Interface())
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
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, w)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (enc *Encoder) NEncode(e interface{}) (err error) {
|
|
||||||
RegisterType(e)
|
RegisterType(e)
|
||||||
for _, t := range cacheTypes.ntypes {
|
for _, t := range cacheTypes.ntypes {
|
||||||
slog.LOG_DEBUGFLN("t: %v", t)
|
slog.LOG_DEBUGFLN("t: %v", t)
|
||||||
|
@ -87,38 +39,3 @@ func (enc *Encoder) NEncode(e interface{}) (err error) {
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (enc *Encoder) encode(e interface{}, indirectLevel int) (err error) {
|
|
||||||
t := reflect.TypeOf(e)
|
|
||||||
|
|
||||||
if t.Kind() == reflect.Invalid {
|
|
||||||
return fmt.Errorf("ssob: Cannot encode nil: %w", ErrValueInvalid)
|
|
||||||
}
|
|
||||||
|
|
||||||
v := reflect.ValueOf(e)
|
|
||||||
//slog.LOG_DEBUGFLN("ssob: encode t.name: %s", t.Name())
|
|
||||||
//slog.LOG_DEBUGFLN("ssob: encode t.kind: %s", t.Kind())
|
|
||||||
slog.LOG_DEBUGFLN("ssob: encode v.type: %s", v.Type())
|
|
||||||
switch t.Kind() {
|
|
||||||
case reflect.Ptr:
|
|
||||||
if v.IsNil() {
|
|
||||||
return fmt.Errorf("ssob: Cannot encode nil pointer: %w", ErrValueInvalid)
|
|
||||||
}
|
|
||||||
p := reflect.Indirect(v)
|
|
||||||
return enc.encode(p.Interface(), indirectLevel+1)
|
|
||||||
case reflect.Struct:
|
|
||||||
return fmt.Errorf("ssob: Type '%s' named '%s' unknown: %w", t.Kind().String(), t.Name(), ErrTypeUnknown)
|
|
||||||
case reflect.Slice:
|
|
||||||
return fmt.Errorf("ssob: Type '%s' with types '%s' unknown: %w", t.Kind().String(), t.Elem().Kind().String(), ErrTypeUnknown)
|
|
||||||
case reflect.Array:
|
|
||||||
return fmt.Errorf("ssob: Type '%s' with types '%s' unknown: %w", t.Kind().String(), t.Name(), ErrTypeUnknown)
|
|
||||||
default:
|
|
||||||
if v, ok := cacheTypes.names[t.Kind().String()]; !ok {
|
|
||||||
return fmt.Errorf("ssob: Type '%s' unknown: %w", t.Kind().String(), ErrTypeUnknown)
|
|
||||||
} else {
|
|
||||||
enc.mutex.Lock()
|
|
||||||
defer enc.mutex.Unlock()
|
|
||||||
return cacheTypes.types[v].marshal(e, enc.w)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
566
marshal.go
566
marshal.go
|
@ -3,486 +3,10 @@ package ssob
|
||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
|
||||||
"math"
|
"math"
|
||||||
"reflect"
|
"reflect"
|
||||||
)
|
)
|
||||||
|
|
||||||
func MarshalString(in string) (ret []byte) {
|
|
||||||
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 MarshalBool(in bool) (ret []byte) {
|
|
||||||
if in {
|
|
||||||
return []byte{byte(0)}
|
|
||||||
}
|
|
||||||
|
|
||||||
return []byte{byte(1)}
|
|
||||||
}
|
|
||||||
|
|
||||||
func MarshalInt8(in int8) (ret []byte) {
|
|
||||||
return []byte{byte(in)}
|
|
||||||
}
|
|
||||||
|
|
||||||
func MarshalUint8(in uint8) (ret []byte) {
|
|
||||||
return []byte{byte(in)}
|
|
||||||
}
|
|
||||||
|
|
||||||
func MarshalInt16(in int16) (ret []byte) {
|
|
||||||
out := make([]byte, 2)
|
|
||||||
|
|
||||||
binary.BigEndian.PutUint16(out, uint16(in))
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
|
|
||||||
func MarshalUint16(in uint16) (ret []byte) {
|
|
||||||
out := make([]byte, 2)
|
|
||||||
|
|
||||||
binary.BigEndian.PutUint16(out, in)
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
|
|
||||||
func MarshalInt32(in int32) (ret []byte) {
|
|
||||||
out := make([]byte, 4)
|
|
||||||
|
|
||||||
binary.BigEndian.PutUint32(out, uint32(in))
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
|
|
||||||
func MarshalUint32(in uint32) (ret []byte) {
|
|
||||||
out := make([]byte, 4)
|
|
||||||
|
|
||||||
binary.BigEndian.PutUint32(out, in)
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
|
|
||||||
func MarshalFloat32(in float32) (ret []byte) {
|
|
||||||
out := make([]byte, 4)
|
|
||||||
|
|
||||||
binary.BigEndian.PutUint32(out, math.Float32bits(in))
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
|
|
||||||
func MarshalInt64(in int64) (ret []byte) {
|
|
||||||
out := make([]byte, 8)
|
|
||||||
|
|
||||||
binary.BigEndian.PutUint64(out, uint64(in))
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
|
|
||||||
func MarshalUint64(in uint64) (ret []byte) {
|
|
||||||
out := make([]byte, 8)
|
|
||||||
|
|
||||||
binary.BigEndian.PutUint64(out, in)
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
|
|
||||||
func MarshalFloat64(in float64) (ret []byte) {
|
|
||||||
out := make([]byte, 8)
|
|
||||||
|
|
||||||
binary.BigEndian.PutUint64(out, math.Float64bits(in))
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
|
|
||||||
type MarshalFunc func(e interface{}) (ret []byte, err error)
|
|
||||||
|
|
||||||
var encoderCache map[string]MarshalFunc
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
encoderCache = make(map[string]MarshalFunc)
|
|
||||||
RegisterEncoder("bool", func(e interface{}) (ret []byte, err error) {
|
|
||||||
if i, ok := e.(bool); ok {
|
|
||||||
return MarshalBool(i), nil
|
|
||||||
}
|
|
||||||
return nil, fmt.Errorf("ssob: Incompatible type - expected bool: %w", ErrTypeMismatch)
|
|
||||||
})
|
|
||||||
RegisterEncoder("int8", func(e interface{}) (ret []byte, err error) {
|
|
||||||
if i, ok := e.(int8); ok {
|
|
||||||
return MarshalInt8(i), nil
|
|
||||||
}
|
|
||||||
return nil, fmt.Errorf("ssob: Incompatible type - expected int8: %w", ErrTypeMismatch)
|
|
||||||
})
|
|
||||||
RegisterEncoder("uint8", func(e interface{}) (ret []byte, err error) {
|
|
||||||
if i, ok := e.(uint8); ok {
|
|
||||||
return MarshalUint8(i), nil
|
|
||||||
}
|
|
||||||
return nil, fmt.Errorf("ssob: Incompatible type - expected uint8: %w", ErrTypeMismatch)
|
|
||||||
})
|
|
||||||
RegisterEncoder("int16", func(e interface{}) (ret []byte, err error) {
|
|
||||||
if i, ok := e.(int16); ok {
|
|
||||||
return MarshalInt16(i), nil
|
|
||||||
}
|
|
||||||
return nil, fmt.Errorf("ssob: Incompatible type - expected int16: %w", ErrTypeMismatch)
|
|
||||||
})
|
|
||||||
RegisterEncoder("uint16", func(e interface{}) (ret []byte, err error) {
|
|
||||||
if i, ok := e.(uint16); ok {
|
|
||||||
return MarshalUint16(i), nil
|
|
||||||
}
|
|
||||||
return nil, fmt.Errorf("ssob: Incompatible type - expected uint16: %w", ErrTypeMismatch)
|
|
||||||
})
|
|
||||||
RegisterEncoder("int32", func(e interface{}) (ret []byte, err error) {
|
|
||||||
if i, ok := e.(int32); ok {
|
|
||||||
return MarshalInt32(i), nil
|
|
||||||
}
|
|
||||||
return nil, fmt.Errorf("ssob: Incompatible type - expected int32: %w", ErrTypeMismatch)
|
|
||||||
})
|
|
||||||
RegisterEncoder("uint32", func(e interface{}) (ret []byte, err error) {
|
|
||||||
if i, ok := e.(uint32); ok {
|
|
||||||
return MarshalUint32(i), nil
|
|
||||||
}
|
|
||||||
return nil, fmt.Errorf("ssob: Incompatible type - expected uint32: %w", ErrTypeMismatch)
|
|
||||||
})
|
|
||||||
RegisterEncoder("float32", func(e interface{}) (ret []byte, err error) {
|
|
||||||
if i, ok := e.(float32); ok {
|
|
||||||
return MarshalFloat32(i), nil
|
|
||||||
}
|
|
||||||
return nil, fmt.Errorf("ssob: Incompatible type - expected float32: %w", ErrTypeMismatch)
|
|
||||||
})
|
|
||||||
RegisterEncoder("int64", func(e interface{}) (ret []byte, err error) {
|
|
||||||
if i, ok := e.(int64); ok {
|
|
||||||
return MarshalInt64(i), nil
|
|
||||||
}
|
|
||||||
return nil, fmt.Errorf("ssob: Incompatible type - expected int64: %w", ErrTypeMismatch)
|
|
||||||
})
|
|
||||||
RegisterEncoder("uint64", func(e interface{}) (ret []byte, err error) {
|
|
||||||
if i, ok := e.(uint64); ok {
|
|
||||||
return MarshalUint64(i), nil
|
|
||||||
}
|
|
||||||
return nil, fmt.Errorf("ssob: Incompatible type - expected uint64: %w", ErrTypeMismatch)
|
|
||||||
})
|
|
||||||
RegisterEncoder("float64", func(e interface{}) (ret []byte, err error) {
|
|
||||||
if i, ok := e.(float64); ok {
|
|
||||||
return MarshalFloat64(i), nil
|
|
||||||
}
|
|
||||||
return nil, fmt.Errorf("ssob: Incompatible type - expected float64: %w", ErrTypeMismatch)
|
|
||||||
})
|
|
||||||
RegisterEncoder("string", func(e interface{}) (ret []byte, err error) {
|
|
||||||
if i, ok := e.(string); ok {
|
|
||||||
return MarshalString(i), nil
|
|
||||||
}
|
|
||||||
return nil, fmt.Errorf("ssob: Incompatible type - expected string: %w", ErrTypeMismatch)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func encRegister(e interface{}) (err error) {
|
|
||||||
t := reflect.TypeOf(e)
|
|
||||||
if t == nil {
|
|
||||||
return fmt.Errorf("ssob: nil type: %w", ErrTypeInvalid)
|
|
||||||
}
|
|
||||||
|
|
||||||
switch t.Kind() {
|
|
||||||
case reflect.Invalid:
|
|
||||||
return fmt.Errorf("ssob: invalid type: %w", ErrTypeInvalid)
|
|
||||||
case reflect.Array:
|
|
||||||
f := func(e interface{}) (ret []byte, err error) {
|
|
||||||
v := reflect.ValueOf(e)
|
|
||||||
l := v.Len()
|
|
||||||
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
|
|
||||||
}
|
|
||||||
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.Slice:
|
|
||||||
f := func(e interface{}) (ret []byte, err error) {
|
|
||||||
v := reflect.ValueOf(e)
|
|
||||||
l := v.Len()
|
|
||||||
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
|
|
||||||
}
|
|
||||||
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:
|
|
||||||
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 fmt.Errorf("ssob: No exported fields for %s: %w", string(t.Name()), ErrParseFailed)
|
|
||||||
}
|
|
||||||
|
|
||||||
f := func(e interface{}) (ret []byte, err error) {
|
|
||||||
v := reflect.ValueOf(e)
|
|
||||||
bs := make([][]byte, n)
|
|
||||||
blen := 0
|
|
||||||
for _, i := range mfields {
|
|
||||||
bs[i], err = marshal(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
|
|
||||||
}
|
|
||||||
encoderCache[t.Name()] = f
|
|
||||||
case reflect.Bool:
|
|
||||||
f := func(e interface{}) (ret []byte, err error) {
|
|
||||||
v := reflect.ValueOf(e)
|
|
||||||
return marshalBaseType(bool(v.Bool()))
|
|
||||||
}
|
|
||||||
encoderCache[t.Name()] = f
|
|
||||||
case reflect.Uint8:
|
|
||||||
f := func(e interface{}) (ret []byte, err error) {
|
|
||||||
v := reflect.ValueOf(e)
|
|
||||||
return marshalBaseType(uint8(v.Uint()))
|
|
||||||
}
|
|
||||||
encoderCache[t.Name()] = f
|
|
||||||
case reflect.Uint16:
|
|
||||||
f := func(e interface{}) (ret []byte, err error) {
|
|
||||||
v := reflect.ValueOf(e)
|
|
||||||
return marshalBaseType(uint16(v.Uint()))
|
|
||||||
}
|
|
||||||
encoderCache[t.Name()] = f
|
|
||||||
case reflect.Uint32:
|
|
||||||
f := func(e interface{}) (ret []byte, err error) {
|
|
||||||
v := reflect.ValueOf(e)
|
|
||||||
return marshalBaseType(uint32(v.Uint()))
|
|
||||||
}
|
|
||||||
encoderCache[t.Name()] = f
|
|
||||||
case reflect.Uint64:
|
|
||||||
f := func(e interface{}) (ret []byte, err error) {
|
|
||||||
v := reflect.ValueOf(e)
|
|
||||||
return marshalBaseType(uint64(v.Uint()))
|
|
||||||
}
|
|
||||||
encoderCache[t.Name()] = f
|
|
||||||
case reflect.Int8:
|
|
||||||
f := func(e interface{}) (ret []byte, err error) {
|
|
||||||
v := reflect.ValueOf(e)
|
|
||||||
return marshalBaseType(int8(v.Uint()))
|
|
||||||
}
|
|
||||||
encoderCache[t.Name()] = f
|
|
||||||
case reflect.Int16:
|
|
||||||
f := func(e interface{}) (ret []byte, err error) {
|
|
||||||
v := reflect.ValueOf(e)
|
|
||||||
return marshalBaseType(int16(v.Uint()))
|
|
||||||
}
|
|
||||||
encoderCache[t.Name()] = f
|
|
||||||
case reflect.Int32:
|
|
||||||
f := func(e interface{}) (ret []byte, err error) {
|
|
||||||
v := reflect.ValueOf(e)
|
|
||||||
return marshalBaseType(int32(v.Uint()))
|
|
||||||
}
|
|
||||||
encoderCache[t.Name()] = f
|
|
||||||
case reflect.Int64:
|
|
||||||
f := func(e interface{}) (ret []byte, err error) {
|
|
||||||
v := reflect.ValueOf(e)
|
|
||||||
return marshalBaseType(int64(v.Uint()))
|
|
||||||
}
|
|
||||||
encoderCache[t.Name()] = f
|
|
||||||
case reflect.String:
|
|
||||||
f := func(e interface{}) (ret []byte, err error) {
|
|
||||||
v := reflect.ValueOf(e)
|
|
||||||
return marshalBaseType(string(v.String()))
|
|
||||||
}
|
|
||||||
encoderCache[t.Name()] = f
|
|
||||||
default:
|
|
||||||
return fmt.Errorf("ssob: %s: %w", string(t.Name()), ErrTypeUnknown)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func marshalBaseType(e interface{}) (ret []byte, err error) {
|
|
||||||
switch t := e.(type) {
|
|
||||||
case bool:
|
|
||||||
return encoderCache["bool"](t)
|
|
||||||
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, fmt.Errorf("ssob: No base type: %w", ErrTypeUnknown)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
switch t.Kind() {
|
|
||||||
case reflect.Ptr:
|
|
||||||
if v.IsNil() {
|
|
||||||
return nil, fmt.Errorf("ssob: Cannot marshal nil pointer: %w", ErrValueInvalid)
|
|
||||||
}
|
|
||||||
p := reflect.Indirect(v)
|
|
||||||
return marshal(p.Interface())
|
|
||||||
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:
|
|
||||||
key = string(t.Kind())
|
|
||||||
}
|
|
||||||
|
|
||||||
if f, ok := encoderCache[key]; ok {
|
|
||||||
return f(e)
|
|
||||||
} else {
|
|
||||||
err = encRegister(e)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return marshal(e)
|
|
||||||
}
|
|
||||||
|
|
||||||
func RegisterEncoder(name string, f MarshalFunc) {
|
|
||||||
encoderCache[name] = f
|
|
||||||
}
|
|
||||||
|
|
||||||
func baseTypeMarshaller(e interface{}, w io.Writer) (err error) {
|
|
||||||
var sb []byte
|
|
||||||
|
|
||||||
switch e.(type) {
|
|
||||||
case bool:
|
|
||||||
sb = make([]byte, ST_ID_SIZE+1)
|
|
||||||
binary.BigEndian.PutUint32(sb, ST_BOOL)
|
|
||||||
if e.(bool) == true {
|
|
||||||
sb[ST_ID_SIZE] = 0
|
|
||||||
} else {
|
|
||||||
sb[ST_ID_SIZE] = 1
|
|
||||||
}
|
|
||||||
case uint8:
|
|
||||||
sb = make([]byte, ST_ID_SIZE+1)
|
|
||||||
binary.BigEndian.PutUint32(sb, ST_UINT8)
|
|
||||||
sb[ST_ID_SIZE] = byte(e.(uint8))
|
|
||||||
case uint16:
|
|
||||||
sb = make([]byte, ST_ID_SIZE+2)
|
|
||||||
binary.BigEndian.PutUint32(sb, ST_UINT16)
|
|
||||||
binary.BigEndian.PutUint16(sb[ST_ID_SIZE:], e.(uint16))
|
|
||||||
case uint32:
|
|
||||||
sb = make([]byte, ST_ID_SIZE+4)
|
|
||||||
binary.BigEndian.PutUint32(sb, ST_UINT32)
|
|
||||||
binary.BigEndian.PutUint32(sb[ST_ID_SIZE:], e.(uint32))
|
|
||||||
case uint64:
|
|
||||||
sb = make([]byte, ST_ID_SIZE+8)
|
|
||||||
binary.BigEndian.PutUint32(sb, ST_UINT64)
|
|
||||||
binary.BigEndian.PutUint64(sb[ST_ID_SIZE:], e.(uint64))
|
|
||||||
case int8:
|
|
||||||
sb = make([]byte, ST_ID_SIZE+1)
|
|
||||||
binary.BigEndian.PutUint32(sb[ST_ID_SIZE:], ST_INT8)
|
|
||||||
sb[ST_ID_SIZE] = byte(e.(int8))
|
|
||||||
case int16:
|
|
||||||
sb = make([]byte, ST_ID_SIZE+2)
|
|
||||||
binary.BigEndian.PutUint32(sb, ST_INT16)
|
|
||||||
binary.BigEndian.PutUint16(sb[ST_ID_SIZE:], uint16(e.(int16)))
|
|
||||||
case int32:
|
|
||||||
sb = make([]byte, ST_ID_SIZE+4)
|
|
||||||
binary.BigEndian.PutUint32(sb, ST_INT32)
|
|
||||||
binary.BigEndian.PutUint32(sb[ST_ID_SIZE:], uint32(e.(int32)))
|
|
||||||
case int64:
|
|
||||||
sb = make([]byte, ST_ID_SIZE+8)
|
|
||||||
binary.BigEndian.PutUint32(sb, ST_INT64)
|
|
||||||
binary.BigEndian.PutUint64(sb[ST_ID_SIZE:], uint64(e.(int64)))
|
|
||||||
case float32:
|
|
||||||
sb = make([]byte, ST_ID_SIZE+4)
|
|
||||||
binary.BigEndian.PutUint32(sb, ST_FLOAT32)
|
|
||||||
binary.BigEndian.PutUint32(sb[ST_ID_SIZE:], math.Float32bits(e.(float32)))
|
|
||||||
case float64:
|
|
||||||
sb = make([]byte, ST_ID_SIZE+8)
|
|
||||||
binary.BigEndian.PutUint32(sb, ST_FLOAT64)
|
|
||||||
binary.BigEndian.PutUint64(sb[ST_ID_SIZE:], math.Float64bits(e.(float64)))
|
|
||||||
case string:
|
|
||||||
slen := len(e.(string))
|
|
||||||
sb = make([]byte, ST_ID_SIZE+slen+4)
|
|
||||||
binary.BigEndian.PutUint32(sb, ST_STRING)
|
|
||||||
binary.BigEndian.PutUint32(sb[ST_ID_SIZE:], uint32(slen))
|
|
||||||
copy(sb[ST_ID_SIZE+4:], []byte(e.(string)))
|
|
||||||
default:
|
|
||||||
return fmt.Errorf("ssob: Unknown type: %s: %w", reflect.TypeOf(e), ErrValueInvalid)
|
|
||||||
}
|
|
||||||
|
|
||||||
return binary.Write(w, binary.BigEndian, sb)
|
|
||||||
}
|
|
||||||
|
|
||||||
func marshalBool(e bool) (ret []byte) {
|
func marshalBool(e bool) (ret []byte) {
|
||||||
ret = make([]byte, 1)
|
ret = make([]byte, 1)
|
||||||
if e == true {
|
if e == true {
|
||||||
|
@ -565,37 +89,39 @@ func marshalNil(e uint16) (ret []byte) {
|
||||||
return marshalUint16(e)
|
return marshalUint16(e)
|
||||||
}
|
}
|
||||||
|
|
||||||
func marshalPtrIfNil(e interface{}, ntype *NType) (ie interface{}, ret []byte, isNil bool) {
|
func marshalPtrIfNil(e interface{}, ntype *NType) (ie interface{}, ret []byte, isNil bool, err error) {
|
||||||
if ntype.Indirection == 0 {
|
if ntype.Indirection == 0 {
|
||||||
return e, nil, false
|
return e, nil, false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
nl := uint16(0)
|
nl := uint16(0)
|
||||||
v := reflect.ValueOf(e)
|
v := reflect.ValueOf(e)
|
||||||
if v.Kind() == reflect.Invalid {
|
if valueIsNil(v) {
|
||||||
ret = append(ret, marshalTypeId(ST_NIL)...)
|
ret = append(ret, marshalTypeId(ST_NIL)...)
|
||||||
ret = append(ret, marshalNil(nl)...)
|
ret = append(ret, marshalNil(nl)...)
|
||||||
return e, ret, true
|
return e, ret, true, err
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := 0; i < ntype.Indirection; i++ {
|
for i := 0; i < ntype.Indirection; i++ {
|
||||||
v = reflect.Indirect(v)
|
if v, err = indirectValue(v); err != nil {
|
||||||
if v.Kind() == reflect.Invalid || (v.Kind() == reflect.Ptr && v.IsNil()) {
|
return e, ret, false, err
|
||||||
|
}
|
||||||
|
if valueIsNil(v) {
|
||||||
ret = append(ret, marshalTypeId(ST_NIL)...)
|
ret = append(ret, marshalTypeId(ST_NIL)...)
|
||||||
ret = append(ret, marshalNil(uint16(nl))...)
|
ret = append(ret, marshalNil(uint16(nl))...)
|
||||||
return e, ret, true
|
return e, ret, true, err
|
||||||
}
|
}
|
||||||
nl++
|
nl++
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = append(ret, marshalTypeId(ntype.ValType)...)
|
ret = append(ret, marshalTypeId(ntype.ValType)...)
|
||||||
return v.Interface(), ret, false
|
return v.Interface(), ret, false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func marshalError(e interface{}, ntype *NType) (ret []byte, err error) {
|
func marshalError(e interface{}, ntype *NType) (ret []byte, err error) {
|
||||||
nl := uint16(0)
|
nl := uint16(0)
|
||||||
v := reflect.ValueOf(e)
|
v := reflect.ValueOf(e)
|
||||||
if v.Kind() == reflect.Invalid {
|
if valueIsNil(v) {
|
||||||
ret = append(ret, marshalTypeId(ST_NIL)...)
|
ret = append(ret, marshalTypeId(ST_NIL)...)
|
||||||
ret = append(ret, marshalNil(nl)...)
|
ret = append(ret, marshalNil(nl)...)
|
||||||
return ret, err
|
return ret, err
|
||||||
|
@ -605,12 +131,15 @@ func marshalError(e interface{}, ntype *NType) (ret []byte, err error) {
|
||||||
for i := 0; i < ntype.Indirection; i++ {
|
for i := 0; i < ntype.Indirection; i++ {
|
||||||
t := reflect.TypeOf(v.Interface())
|
t := reflect.TypeOf(v.Interface())
|
||||||
|
|
||||||
|
// TODO: Dirty!? Better way?
|
||||||
if t.String() == "errors.errorString" {
|
if t.String() == "errors.errorString" {
|
||||||
errorString = true
|
errorString = true
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
v = reflect.Indirect(v)
|
if v, err = indirectValue(v); err != nil {
|
||||||
if v.Kind() == reflect.Invalid || v.IsNil() {
|
return ret, err
|
||||||
|
}
|
||||||
|
if valueIsNil(v) {
|
||||||
ret = append(ret, marshalTypeId(ST_NIL)...)
|
ret = append(ret, marshalTypeId(ST_NIL)...)
|
||||||
ret = append(ret, marshalNil(uint16(nl))...)
|
ret = append(ret, marshalNil(uint16(nl))...)
|
||||||
return ret, err
|
return ret, err
|
||||||
|
@ -626,7 +155,7 @@ func marshalError(e interface{}, ntype *NType) (ret []byte, err error) {
|
||||||
|
|
||||||
ierr, ok := v.Interface().(error)
|
ierr, ok := v.Interface().(error)
|
||||||
if !ok {
|
if !ok {
|
||||||
return ret, fmt.Errorf("Not an error interface '%v': %w", v.Interface(), ErrValueInvalid)
|
return ret, ErrValueInvalid
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = append(ret, marshalTypeId(ST_STRING)...)
|
ret = append(ret, marshalTypeId(ST_STRING)...)
|
||||||
|
@ -641,11 +170,14 @@ func marshalTypeId(e uint32) (ret []byte) {
|
||||||
func marshalCommon(e interface{}, ntype *NType) (ret []byte, err error) {
|
func marshalCommon(e interface{}, ntype *NType) (ret []byte, err error) {
|
||||||
ctype := getTypeById(ntype.ValType)
|
ctype := getTypeById(ntype.ValType)
|
||||||
if ctype == nil {
|
if ctype == nil {
|
||||||
return ret, fmt.Errorf("ssob: Unknown common type '%d': %w", ntype.ValType, ErrTypeUnknown)
|
return ret, ErrTypeUnknown
|
||||||
}
|
}
|
||||||
|
|
||||||
// pointer could be nil
|
// pointer could be nil
|
||||||
e, ptrNil, isNil := marshalPtrIfNil(e, ntype)
|
e, ptrNil, isNil, err := marshalPtrIfNil(e, ntype)
|
||||||
|
if err != nil {
|
||||||
|
return ptrNil, err
|
||||||
|
}
|
||||||
if ptrNil != nil {
|
if ptrNil != nil {
|
||||||
if isNil {
|
if isNil {
|
||||||
return ptrNil, err
|
return ptrNil, err
|
||||||
|
@ -656,84 +188,84 @@ func marshalCommon(e interface{}, ntype *NType) (ret []byte, err error) {
|
||||||
switch ctype.Id {
|
switch ctype.Id {
|
||||||
case ST_BOOL:
|
case ST_BOOL:
|
||||||
if ie, ok := e.(bool); !ok {
|
if ie, ok := e.(bool); !ok {
|
||||||
return ret, fmt.Errorf("ssob: Invalid interface type '%v' expected 'bool': %w", e, ErrTypeInvalid)
|
return ret, ErrTypeInvalid
|
||||||
} else {
|
} else {
|
||||||
ret = append(ret, marshalBool(ie)...)
|
ret = append(ret, marshalBool(ie)...)
|
||||||
return ret, err
|
return ret, err
|
||||||
}
|
}
|
||||||
case ST_UINT8:
|
case ST_UINT8:
|
||||||
if ie, ok := e.(uint8); !ok {
|
if ie, ok := e.(uint8); !ok {
|
||||||
return ret, fmt.Errorf("ssob: Invalid interface type '%v' expected 'uint8': %w", e, ErrTypeInvalid)
|
return ret, ErrTypeInvalid
|
||||||
} else {
|
} else {
|
||||||
ret = append(ret, marshalUint8(ie)...)
|
ret = append(ret, marshalUint8(ie)...)
|
||||||
return ret, err
|
return ret, err
|
||||||
}
|
}
|
||||||
case ST_UINT16:
|
case ST_UINT16:
|
||||||
if ie, ok := e.(uint16); !ok {
|
if ie, ok := e.(uint16); !ok {
|
||||||
return ret, fmt.Errorf("ssob: Invalid interface type '%v' expected 'uint16': %w", e, ErrTypeInvalid)
|
return ret, ErrTypeInvalid
|
||||||
} else {
|
} else {
|
||||||
ret = append(ret, marshalUint16(ie)...)
|
ret = append(ret, marshalUint16(ie)...)
|
||||||
return ret, err
|
return ret, err
|
||||||
}
|
}
|
||||||
case ST_UINT32:
|
case ST_UINT32:
|
||||||
if ie, ok := e.(uint32); !ok {
|
if ie, ok := e.(uint32); !ok {
|
||||||
return ret, fmt.Errorf("ssob: Invalid interface type '%v' expected 'uint32': %w", e, ErrTypeInvalid)
|
return ret, ErrTypeInvalid
|
||||||
} else {
|
} else {
|
||||||
ret = append(ret, marshalUint32(ie)...)
|
ret = append(ret, marshalUint32(ie)...)
|
||||||
return ret, err
|
return ret, err
|
||||||
}
|
}
|
||||||
case ST_UINT64:
|
case ST_UINT64:
|
||||||
if ie, ok := e.(uint64); !ok {
|
if ie, ok := e.(uint64); !ok {
|
||||||
return ret, fmt.Errorf("ssob: Invalid interface type '%v' expected 'uint64': %w", e, ErrTypeInvalid)
|
return ret, ErrTypeInvalid
|
||||||
} else {
|
} else {
|
||||||
ret = append(ret, marshalUint64(ie)...)
|
ret = append(ret, marshalUint64(ie)...)
|
||||||
return ret, err
|
return ret, err
|
||||||
}
|
}
|
||||||
case ST_INT8:
|
case ST_INT8:
|
||||||
if ie, ok := e.(int8); !ok {
|
if ie, ok := e.(int8); !ok {
|
||||||
return ret, fmt.Errorf("ssob: Invalid interface type '%v' expected 'int8': %w", e, ErrTypeInvalid)
|
return ret, ErrTypeInvalid
|
||||||
} else {
|
} else {
|
||||||
ret = append(ret, marshalInt8(ie)...)
|
ret = append(ret, marshalInt8(ie)...)
|
||||||
return ret, err
|
return ret, err
|
||||||
}
|
}
|
||||||
case ST_INT16:
|
case ST_INT16:
|
||||||
if ie, ok := e.(int16); !ok {
|
if ie, ok := e.(int16); !ok {
|
||||||
return ret, fmt.Errorf("ssob: Invalid interface type '%v' expected 'int16': %w", e, ErrTypeInvalid)
|
return ret, ErrTypeInvalid
|
||||||
} else {
|
} else {
|
||||||
ret = append(ret, marshalInt16(ie)...)
|
ret = append(ret, marshalInt16(ie)...)
|
||||||
return ret, err
|
return ret, err
|
||||||
}
|
}
|
||||||
case ST_INT32:
|
case ST_INT32:
|
||||||
if ie, ok := e.(int32); !ok {
|
if ie, ok := e.(int32); !ok {
|
||||||
return ret, fmt.Errorf("ssob: Invalid interface type '%v' expected 'int32': %w", e, ErrTypeInvalid)
|
return ret, ErrTypeInvalid
|
||||||
} else {
|
} else {
|
||||||
ret = append(ret, marshalInt32(ie)...)
|
ret = append(ret, marshalInt32(ie)...)
|
||||||
return ret, err
|
return ret, err
|
||||||
}
|
}
|
||||||
case ST_INT64:
|
case ST_INT64:
|
||||||
if ie, ok := e.(int64); !ok {
|
if ie, ok := e.(int64); !ok {
|
||||||
return ret, fmt.Errorf("ssob: Invalid interface type '%v' expected 'int64': %w", e, ErrTypeInvalid)
|
return ret, ErrTypeInvalid
|
||||||
} else {
|
} else {
|
||||||
ret = append(ret, marshalInt64(ie)...)
|
ret = append(ret, marshalInt64(ie)...)
|
||||||
return ret, err
|
return ret, err
|
||||||
}
|
}
|
||||||
case ST_FLOAT32:
|
case ST_FLOAT32:
|
||||||
if ie, ok := e.(float32); !ok {
|
if ie, ok := e.(float32); !ok {
|
||||||
return ret, fmt.Errorf("ssob: Invalid interface type '%v' expected 'float32': %w", e, ErrTypeInvalid)
|
return ret, ErrTypeInvalid
|
||||||
} else {
|
} else {
|
||||||
ret = append(ret, marshalFloat32(ie)...)
|
ret = append(ret, marshalFloat32(ie)...)
|
||||||
return ret, err
|
return ret, err
|
||||||
}
|
}
|
||||||
case ST_FLOAT64:
|
case ST_FLOAT64:
|
||||||
if ie, ok := e.(float64); !ok {
|
if ie, ok := e.(float64); !ok {
|
||||||
return ret, fmt.Errorf("ssob: Invalid interface type '%v' expected 'float64': %w", e, ErrTypeInvalid)
|
return ret, ErrTypeInvalid
|
||||||
} else {
|
} else {
|
||||||
ret = append(ret, marshalFloat64(ie)...)
|
ret = append(ret, marshalFloat64(ie)...)
|
||||||
return ret, err
|
return ret, err
|
||||||
}
|
}
|
||||||
case ST_STRING:
|
case ST_STRING:
|
||||||
if ie, ok := e.(string); !ok {
|
if ie, ok := e.(string); !ok {
|
||||||
return ret, fmt.Errorf("ssob: Invalid interface type '%v' expected 'string': %w", e, ErrTypeInvalid)
|
return ret, ErrTypeInvalid
|
||||||
} else {
|
} else {
|
||||||
ret = append(ret, marshalString(ie)...)
|
ret = append(ret, marshalString(ie)...)
|
||||||
return ret, err
|
return ret, err
|
||||||
|
@ -741,19 +273,19 @@ func marshalCommon(e interface{}, ntype *NType) (ret []byte, err error) {
|
||||||
case ST_ERROR:
|
case ST_ERROR:
|
||||||
return marshalError(e, ntype)
|
return marshalError(e, ntype)
|
||||||
default:
|
default:
|
||||||
return ret, fmt.Errorf("ssob: Unknown common type '%d': %w", ctype.Id, ErrTypeUnknown)
|
return ret, ErrTypeUnknown
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func marshalSlice(e interface{}, ntype *NType) (ret []byte, err error) {
|
func marshalSlice(e interface{}, ntype *NType) (ret []byte, err error) {
|
||||||
v := reflect.ValueOf(e)
|
v := reflect.ValueOf(e)
|
||||||
if v.Kind() != reflect.Slice {
|
if !v.IsValid() || v.Kind() != reflect.Slice {
|
||||||
return ret, fmt.Errorf("ssob: Invalid value '%v': %w", v.Kind(), ErrValueInvalid)
|
return ret, ErrValueInvalid
|
||||||
}
|
}
|
||||||
|
|
||||||
stype := getTypeById(ntype.ValType)
|
stype := getTypeById(ntype.ValType)
|
||||||
if stype == nil {
|
if stype == nil {
|
||||||
return ret, fmt.Errorf("ssob: Unknown type '%d': %w", ntype.ValType, ErrTypeUnknown)
|
return ret, ErrTypeUnknown
|
||||||
}
|
}
|
||||||
|
|
||||||
l := v.Len()
|
l := v.Len()
|
||||||
|
@ -771,13 +303,13 @@ func marshalSlice(e interface{}, ntype *NType) (ret []byte, err error) {
|
||||||
|
|
||||||
func marshalArray(e interface{}, ntype *NType) (ret []byte, err error) {
|
func marshalArray(e interface{}, ntype *NType) (ret []byte, err error) {
|
||||||
v := reflect.ValueOf(e)
|
v := reflect.ValueOf(e)
|
||||||
if v.Kind() != reflect.Array {
|
if !v.IsValid() || v.Kind() != reflect.Array {
|
||||||
return ret, fmt.Errorf("ssob: Invalid value '%v': %w", v.Kind(), ErrValueInvalid)
|
return ret, ErrValueInvalid
|
||||||
}
|
}
|
||||||
|
|
||||||
stype := getTypeById(ntype.ValType)
|
stype := getTypeById(ntype.ValType)
|
||||||
if stype == nil {
|
if stype == nil {
|
||||||
return ret, fmt.Errorf("ssob: Unknown type '%d': %w", ntype.ValType, ErrTypeUnknown)
|
return ret, ErrTypeUnknown
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := 0; i < ntype.arrayLen; i++ {
|
for i := 0; i < ntype.arrayLen; i++ {
|
||||||
|
@ -793,19 +325,19 @@ func marshalArray(e interface{}, ntype *NType) (ret []byte, err error) {
|
||||||
|
|
||||||
func marshalStruct(e interface{}, ntype *NType) (ret []byte, err error) {
|
func marshalStruct(e interface{}, ntype *NType) (ret []byte, err error) {
|
||||||
v := reflect.ValueOf(e)
|
v := reflect.ValueOf(e)
|
||||||
if v.Kind() != reflect.Struct {
|
if !v.IsValid() || v.Kind() != reflect.Struct {
|
||||||
return ret, fmt.Errorf("ssob: Invalid value '%v': %w", v.Kind(), ErrValueInvalid)
|
return ret, ErrValueInvalid
|
||||||
}
|
}
|
||||||
|
|
||||||
stype := getTypeById(ntype.ValType)
|
stype := getTypeById(ntype.ValType)
|
||||||
if stype == nil {
|
if stype == nil {
|
||||||
return ret, fmt.Errorf("ssob: Unknown type '%d': %w", ntype.ValType, ErrTypeUnknown)
|
return ret, ErrTypeUnknown
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, field := range stype.structFields {
|
for i, field := range stype.structFields {
|
||||||
ftype := getTypeById(field.Id)
|
ftype := getTypeById(field.Id)
|
||||||
if ftype == nil {
|
if ftype == nil {
|
||||||
return ret, fmt.Errorf("ssob: Unknown type '%d': %w", field.Id, ErrTypeUnknown)
|
return ret, ErrTypeUnknown
|
||||||
}
|
}
|
||||||
tbytes, err := marshalType(v.Field(i).Interface(), ftype)
|
tbytes, err := marshalType(v.Field(i).Interface(), ftype)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -820,7 +352,7 @@ func marshalStruct(e interface{}, ntype *NType) (ret []byte, err error) {
|
||||||
func marshalInterface(e interface{}, ntype *NType) (ret []byte, err error) {
|
func marshalInterface(e interface{}, ntype *NType) (ret []byte, err error) {
|
||||||
stype := getTypeById(ntype.ValType)
|
stype := getTypeById(ntype.ValType)
|
||||||
if stype == nil {
|
if stype == nil {
|
||||||
return ret, fmt.Errorf("ssob: Unknown type '%d': %w", ntype.ValType, ErrTypeUnknown)
|
return ret, ErrTypeUnknown
|
||||||
}
|
}
|
||||||
|
|
||||||
return marshalCommon(e, ntype)
|
return marshalCommon(e, ntype)
|
||||||
|
@ -839,14 +371,14 @@ func marshalType(e interface{}, ntype *NType) (ret []byte, err error) {
|
||||||
case ST_INTERFACE:
|
case ST_INTERFACE:
|
||||||
return marshalInterface(e, ntype)
|
return marshalInterface(e, ntype)
|
||||||
default:
|
default:
|
||||||
return ret, fmt.Errorf("ssob: Unknown type '%d': %w", ntype.MainTypeId, ErrTypeUnknown)
|
return ret, ErrTypeUnknown
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func marshalVal(e interface{}) (ret []byte, err error) {
|
func marshalVal(e interface{}) (ret []byte, err error) {
|
||||||
i, n, nl, err := indirectType(e)
|
i, n, nl, err := indirectType(e)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ret, err
|
return ret, ErrValueInvalid
|
||||||
}
|
}
|
||||||
|
|
||||||
// type id
|
// type id
|
||||||
|
@ -854,9 +386,7 @@ func marshalVal(e interface{}) (ret []byte, err error) {
|
||||||
|
|
||||||
// nil pointer
|
// nil pointer
|
||||||
if i == nil {
|
if i == nil {
|
||||||
// nil
|
|
||||||
bytes = append(bytes, marshalBool(true)...)
|
bytes = append(bytes, marshalBool(true)...)
|
||||||
//bytes = append(bytes, marshalTypeId(ST_NIL)...)
|
|
||||||
bytes = append(bytes, marshalNil(nl)...)
|
bytes = append(bytes, marshalNil(nl)...)
|
||||||
} else {
|
} else {
|
||||||
bytes = append(bytes, marshalBool(false)...)
|
bytes = append(bytes, marshalBool(false)...)
|
||||||
|
|
274
types.go
274
types.go
|
@ -4,8 +4,6 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
|
||||||
"gitea.olznet.de/OlzNet/slog"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type allocatorFunc func(vals ...interface{}) interface{}
|
type allocatorFunc func(vals ...interface{}) interface{}
|
||||||
|
@ -17,8 +15,6 @@ type nallocFunc func() interface{}
|
||||||
|
|
||||||
type RegisteredTypes struct {
|
type RegisteredTypes struct {
|
||||||
NextId uint32
|
NextId uint32
|
||||||
types map[uint32]Type
|
|
||||||
names map[string]uint32
|
|
||||||
ntypes map[uint32]*NType
|
ntypes map[uint32]*NType
|
||||||
nnames map[string]*NType
|
nnames map[string]*NType
|
||||||
}
|
}
|
||||||
|
@ -36,6 +32,7 @@ type StructField struct {
|
||||||
Id uint32
|
Id uint32
|
||||||
Name string
|
Name string
|
||||||
Tag string
|
Tag string
|
||||||
|
SId int
|
||||||
}
|
}
|
||||||
|
|
||||||
type NType struct {
|
type NType struct {
|
||||||
|
@ -86,8 +83,6 @@ const (
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
cacheTypes.NextId = 128
|
cacheTypes.NextId = 128
|
||||||
cacheTypes.types = make(map[uint32]Type)
|
|
||||||
cacheTypes.names = make(map[string]uint32)
|
|
||||||
cacheTypes.ntypes = make(map[uint32]*NType)
|
cacheTypes.ntypes = make(map[uint32]*NType)
|
||||||
cacheTypes.nnames = make(map[string]*NType)
|
cacheTypes.nnames = make(map[string]*NType)
|
||||||
|
|
||||||
|
@ -188,154 +183,6 @@ func init() {
|
||||||
}
|
}
|
||||||
cacheTypes.ntypes[ST_NIL] = nilType
|
cacheTypes.ntypes[ST_NIL] = nilType
|
||||||
cacheTypes.nnames["nil"] = nilType
|
cacheTypes.nnames["nil"] = nilType
|
||||||
|
|
||||||
cacheTypes.types[ST_BOOL] = Type{
|
|
||||||
"bool", ST_BOOL,
|
|
||||||
func(vals ...interface{}) interface{} { return new(bool) },
|
|
||||||
baseTypeMarshaller,
|
|
||||||
func(r io.Reader) (interface{}, error) { return baseTypeUnmarshaller(ST_BOOL, r) },
|
|
||||||
}
|
|
||||||
cacheTypes.names["bool"] = ST_BOOL
|
|
||||||
|
|
||||||
cacheTypes.types[ST_UINT8] = Type{
|
|
||||||
"uint8", ST_UINT8,
|
|
||||||
func(vals ...interface{}) interface{} { return new(uint8) },
|
|
||||||
baseTypeMarshaller,
|
|
||||||
func(r io.Reader) (interface{}, error) { return baseTypeUnmarshaller(ST_UINT8, r) },
|
|
||||||
}
|
|
||||||
cacheTypes.names["uint8"] = ST_UINT8
|
|
||||||
|
|
||||||
cacheTypes.types[ST_UINT16] = Type{
|
|
||||||
"uint16", ST_UINT16,
|
|
||||||
func(vals ...interface{}) interface{} { return new(uint16) },
|
|
||||||
baseTypeMarshaller,
|
|
||||||
func(r io.Reader) (interface{}, error) { return baseTypeUnmarshaller(ST_UINT16, r) },
|
|
||||||
}
|
|
||||||
cacheTypes.names["uint16"] = ST_UINT16
|
|
||||||
|
|
||||||
cacheTypes.types[ST_UINT32] = Type{
|
|
||||||
"uint32", ST_UINT32,
|
|
||||||
func(vals ...interface{}) interface{} { return new(uint32) },
|
|
||||||
baseTypeMarshaller,
|
|
||||||
func(r io.Reader) (interface{}, error) { return baseTypeUnmarshaller(ST_UINT32, r) },
|
|
||||||
}
|
|
||||||
cacheTypes.names["uint32"] = ST_UINT32
|
|
||||||
|
|
||||||
cacheTypes.types[ST_UINT64] = Type{
|
|
||||||
"uint64", ST_UINT64,
|
|
||||||
func(vals ...interface{}) interface{} { return new(uint64) },
|
|
||||||
baseTypeMarshaller,
|
|
||||||
func(r io.Reader) (interface{}, error) { return baseTypeUnmarshaller(ST_UINT64, r) },
|
|
||||||
}
|
|
||||||
cacheTypes.names["uint64"] = ST_UINT64
|
|
||||||
|
|
||||||
cacheTypes.types[ST_INT8] = Type{
|
|
||||||
"int8", ST_INT8,
|
|
||||||
func(vals ...interface{}) interface{} { return new(int8) },
|
|
||||||
baseTypeMarshaller,
|
|
||||||
func(r io.Reader) (interface{}, error) { return baseTypeUnmarshaller(ST_INT8, r) },
|
|
||||||
}
|
|
||||||
cacheTypes.names["int8"] = ST_UINT8
|
|
||||||
|
|
||||||
cacheTypes.types[ST_INT16] = Type{
|
|
||||||
"int16", ST_INT16,
|
|
||||||
func(vals ...interface{}) interface{} { return new(int16) },
|
|
||||||
baseTypeMarshaller,
|
|
||||||
func(r io.Reader) (interface{}, error) { return baseTypeUnmarshaller(ST_INT16, r) },
|
|
||||||
}
|
|
||||||
cacheTypes.names["int16"] = ST_INT16
|
|
||||||
|
|
||||||
cacheTypes.types[ST_INT32] = Type{
|
|
||||||
"int32", ST_INT32,
|
|
||||||
func(vals ...interface{}) interface{} { return new(int32) },
|
|
||||||
baseTypeMarshaller,
|
|
||||||
func(r io.Reader) (interface{}, error) { return baseTypeUnmarshaller(ST_INT32, r) },
|
|
||||||
}
|
|
||||||
cacheTypes.names["int32"] = ST_INT32
|
|
||||||
|
|
||||||
cacheTypes.types[ST_INT64] = Type{
|
|
||||||
"int64", ST_INT64,
|
|
||||||
func(vals ...interface{}) interface{} { return new(int64) },
|
|
||||||
baseTypeMarshaller,
|
|
||||||
func(r io.Reader) (interface{}, error) { return baseTypeUnmarshaller(ST_INT64, r) },
|
|
||||||
}
|
|
||||||
cacheTypes.names["int64"] = ST_INT64
|
|
||||||
|
|
||||||
cacheTypes.types[ST_FLOAT32] = Type{
|
|
||||||
"float32", ST_FLOAT32,
|
|
||||||
func(vals ...interface{}) interface{} { return new(float32) },
|
|
||||||
baseTypeMarshaller,
|
|
||||||
func(r io.Reader) (interface{}, error) { return baseTypeUnmarshaller(ST_FLOAT32, r) },
|
|
||||||
}
|
|
||||||
cacheTypes.names["float32"] = ST_FLOAT32
|
|
||||||
|
|
||||||
cacheTypes.types[ST_FLOAT64] = Type{
|
|
||||||
"float64", ST_FLOAT64,
|
|
||||||
func(vals ...interface{}) interface{} { return new(float64) },
|
|
||||||
baseTypeMarshaller,
|
|
||||||
func(r io.Reader) (interface{}, error) { return baseTypeUnmarshaller(ST_FLOAT64, r) },
|
|
||||||
}
|
|
||||||
cacheTypes.names["float64"] = ST_FLOAT64
|
|
||||||
|
|
||||||
cacheTypes.types[ST_STRING] = Type{
|
|
||||||
"string", ST_STRING,
|
|
||||||
func(vals ...interface{}) interface{} { return new(string) },
|
|
||||||
baseTypeMarshaller,
|
|
||||||
func(r io.Reader) (interface{}, error) { return baseTypeUnmarshaller(ST_STRING, r) },
|
|
||||||
}
|
|
||||||
cacheTypes.names["string"] = ST_STRING
|
|
||||||
}
|
|
||||||
|
|
||||||
func getTypeId(e interface{}, indirectLevel int) (id uint32, level int) {
|
|
||||||
level = indirectLevel
|
|
||||||
t := reflect.TypeOf(e)
|
|
||||||
|
|
||||||
if t.Kind() == reflect.Invalid {
|
|
||||||
return ST_INVALID, level
|
|
||||||
}
|
|
||||||
|
|
||||||
v := reflect.ValueOf(e)
|
|
||||||
switch t.Kind() {
|
|
||||||
case reflect.Ptr:
|
|
||||||
if v.IsNil() {
|
|
||||||
return ST_INVALID, level
|
|
||||||
}
|
|
||||||
p := reflect.Indirect(v)
|
|
||||||
level += 1
|
|
||||||
return getTypeId(p.Interface(), level)
|
|
||||||
}
|
|
||||||
|
|
||||||
if id, ok := cacheTypes.names[t.Kind().String()]; ok {
|
|
||||||
return id, level
|
|
||||||
}
|
|
||||||
|
|
||||||
return ST_INVALID, level
|
|
||||||
}
|
|
||||||
|
|
||||||
func getIndirection(e interface{}, level int) (indirection int, maintype uint32, typ reflect.Type) {
|
|
||||||
indirection = level
|
|
||||||
maintype = ST_COMMON
|
|
||||||
|
|
||||||
t := reflect.TypeOf(e)
|
|
||||||
v := reflect.ValueOf(e)
|
|
||||||
|
|
||||||
switch t.Kind() {
|
|
||||||
case reflect.Ptr:
|
|
||||||
if v.IsNil() {
|
|
||||||
return indirection, maintype, t
|
|
||||||
}
|
|
||||||
p := reflect.Indirect(v)
|
|
||||||
indirection += 1
|
|
||||||
return getIndirection(p.Interface(), indirection)
|
|
||||||
case reflect.Slice:
|
|
||||||
maintype = ST_SLICE
|
|
||||||
case reflect.Array:
|
|
||||||
maintype = ST_ARRAY
|
|
||||||
case reflect.Struct:
|
|
||||||
maintype = ST_STRUCT
|
|
||||||
}
|
|
||||||
|
|
||||||
return indirection, maintype, t
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func getTypeById(id uint32) (ret *NType) {
|
func getTypeById(id uint32) (ret *NType) {
|
||||||
|
@ -393,7 +240,7 @@ func parseType(t reflect.Type) (ret nallocFunc, mainTypeId uint32, indirection i
|
||||||
typ := reflect.TypeOf(val.Interface())
|
typ := reflect.TypeOf(val.Interface())
|
||||||
vt, err := getTypeByNameRegister(typ.Elem().String(), typ.Elem())
|
vt, err := getTypeByNameRegister(typ.Elem().String(), typ.Elem())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ret, mainTypeId, indirection, valType, base, sfields, arrayLen, fmt.Errorf("ssob: Failed receiving type '%s': %w", typ.Elem(), err)
|
return ret, mainTypeId, indirection, valType, base, sfields, arrayLen, err
|
||||||
}
|
}
|
||||||
valType = vt.Id
|
valType = vt.Id
|
||||||
base = false
|
base = false
|
||||||
|
@ -403,7 +250,7 @@ func parseType(t reflect.Type) (ret nallocFunc, mainTypeId uint32, indirection i
|
||||||
arrayLen = val.Len()
|
arrayLen = val.Len()
|
||||||
vt, err := getTypeByNameRegister(typ.Elem().String(), typ.Elem())
|
vt, err := getTypeByNameRegister(typ.Elem().String(), typ.Elem())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ret, mainTypeId, indirection, valType, base, sfields, arrayLen, fmt.Errorf("ssob: Failed receiving type '%s': %w", typ.Elem(), err)
|
return ret, mainTypeId, indirection, valType, base, sfields, arrayLen, err
|
||||||
}
|
}
|
||||||
valType = vt.Id
|
valType = vt.Id
|
||||||
base = false
|
base = false
|
||||||
|
@ -413,7 +260,7 @@ func parseType(t reflect.Type) (ret nallocFunc, mainTypeId uint32, indirection i
|
||||||
if !base {
|
if !base {
|
||||||
vt, err := getTypeByNameRegister(typ.Elem().String(), typ.Elem())
|
vt, err := getTypeByNameRegister(typ.Elem().String(), typ.Elem())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ret, mainTypeId, indirection, valType, base, sfields, arrayLen, fmt.Errorf("ssob: Failed receiving type '%s': %w", typ.Elem(), err)
|
return ret, mainTypeId, indirection, valType, base, sfields, arrayLen, err
|
||||||
}
|
}
|
||||||
valType = vt.Id
|
valType = vt.Id
|
||||||
}
|
}
|
||||||
|
@ -423,7 +270,7 @@ func parseType(t reflect.Type) (ret nallocFunc, mainTypeId uint32, indirection i
|
||||||
if !base {
|
if !base {
|
||||||
vt, err := getTypeByNameRegister(typ.String(), typ)
|
vt, err := getTypeByNameRegister(typ.String(), typ)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ret, mainTypeId, indirection, valType, base, sfields, arrayLen, fmt.Errorf("ssob: Failed receiving type '%s': %w", typ.Elem(), err)
|
return ret, mainTypeId, indirection, valType, base, sfields, arrayLen, err
|
||||||
}
|
}
|
||||||
valType = vt.Id
|
valType = vt.Id
|
||||||
} else {
|
} else {
|
||||||
|
@ -435,9 +282,10 @@ func parseType(t reflect.Type) (ret nallocFunc, mainTypeId uint32, indirection i
|
||||||
sfield.Tag = string(val.Type().Field(i).Tag)
|
sfield.Tag = string(val.Type().Field(i).Tag)
|
||||||
vt, err := getTypeByNameRegister(val.Field(i).Type().String(), val.Field(i).Type())
|
vt, err := getTypeByNameRegister(val.Field(i).Type().String(), val.Field(i).Type())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ret, mainTypeId, indirection, valType, base, sfields, arrayLen, fmt.Errorf("ssob: Failed receiving type '%s': %w", typ.Elem(), err)
|
return ret, mainTypeId, indirection, valType, base, sfields, arrayLen, err
|
||||||
}
|
}
|
||||||
sfield.Id = vt.Id
|
sfield.Id = vt.Id
|
||||||
|
sfield.SId = i
|
||||||
sfields = append(sfields, sfield)
|
sfields = append(sfields, sfield)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -449,21 +297,21 @@ func parseType(t reflect.Type) (ret nallocFunc, mainTypeId uint32, indirection i
|
||||||
if !base {
|
if !base {
|
||||||
vt, err := getTypeByNameRegister(typ.String(), typ)
|
vt, err := getTypeByNameRegister(typ.String(), typ)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ret, mainTypeId, indirection, valType, base, sfields, arrayLen, fmt.Errorf("ssob: Failed receiving type '%s': %w", typ.Elem(), err)
|
return ret, mainTypeId, indirection, valType, base, sfields, arrayLen, err
|
||||||
}
|
}
|
||||||
valType = vt.Id
|
valType = vt.Id
|
||||||
} else {
|
} else {
|
||||||
// Key
|
// Key
|
||||||
vt, err := getTypeByNameRegister(typ.Key().String(), typ.Key())
|
vt, err := getTypeByNameRegister(typ.Key().String(), typ.Key())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ret, mainTypeId, indirection, valType, base, sfields, arrayLen, fmt.Errorf("ssob: Failed receiving type '%s': %w", typ.Elem(), err)
|
return ret, mainTypeId, indirection, valType, base, sfields, arrayLen, err
|
||||||
}
|
}
|
||||||
valType = vt.Id
|
valType = vt.Id
|
||||||
|
|
||||||
// Val
|
// Val
|
||||||
vt, err = getTypeByNameRegister(typ.Elem().String(), typ.Elem())
|
vt, err = getTypeByNameRegister(typ.Elem().String(), typ.Elem())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ret, mainTypeId, indirection, valType, base, sfields, arrayLen, fmt.Errorf("ssob: Failed receiving type '%s': %w", typ.Elem(), err)
|
return ret, mainTypeId, indirection, valType, base, sfields, arrayLen, err
|
||||||
}
|
}
|
||||||
valType = vt.Id
|
valType = vt.Id
|
||||||
base = false
|
base = false
|
||||||
|
@ -474,7 +322,7 @@ func parseType(t reflect.Type) (ret nallocFunc, mainTypeId uint32, indirection i
|
||||||
if !base {
|
if !base {
|
||||||
vt, err := getTypeByNameRegister(typ.Kind().String(), typ)
|
vt, err := getTypeByNameRegister(typ.Kind().String(), typ)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ret, mainTypeId, indirection, valType, base, sfields, arrayLen, fmt.Errorf("ssob: Failed receiving type '%s': %w", typ.Elem(), err)
|
return ret, mainTypeId, indirection, valType, base, sfields, arrayLen, err
|
||||||
}
|
}
|
||||||
valType = vt.Id
|
valType = vt.Id
|
||||||
}
|
}
|
||||||
|
@ -517,7 +365,7 @@ func createType(t reflect.Type) (ret *NType, base bool, err error) {
|
||||||
|
|
||||||
func registerType(t reflect.Type) (err error) {
|
func registerType(t reflect.Type) (err error) {
|
||||||
if t == nil || t.Kind() == reflect.Invalid {
|
if t == nil || t.Kind() == reflect.Invalid {
|
||||||
return fmt.Errorf("ssob: Cannot register nil: %w", ErrTypeInvalid)
|
return ErrTypeInvalid
|
||||||
}
|
}
|
||||||
|
|
||||||
if getTypeByName(t.String()) != nil {
|
if getTypeByName(t.String()) != nil {
|
||||||
|
@ -527,7 +375,7 @@ func registerType(t reflect.Type) (err error) {
|
||||||
var base bool
|
var base bool
|
||||||
ntype, base, err := createType(t)
|
ntype, base, err := createType(t)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("ssob: Cannot register type '%s': %w", t, err)
|
return err
|
||||||
}
|
}
|
||||||
ntype.Id = cacheTypes.NextId
|
ntype.Id = cacheTypes.NextId
|
||||||
if base {
|
if base {
|
||||||
|
@ -537,25 +385,18 @@ func registerType(t reflect.Type) (err error) {
|
||||||
cacheTypes.nnames[ntype.Name] = ntype
|
cacheTypes.nnames[ntype.Name] = ntype
|
||||||
cacheTypes.NextId += 1
|
cacheTypes.NextId += 1
|
||||||
|
|
||||||
if ntype.MainTypeId == ST_STRUCT {
|
|
||||||
for _, f := range ntype.structFields {
|
|
||||||
slog.LOG_DEBUGFLN(" Field: %v", f)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
slog.LOG_DEBUGFLN("Type: %v registered", t)
|
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func splitType(e interface{}) (t reflect.Type, v reflect.Value, err error) {
|
func splitType(e interface{}) (t reflect.Type, v reflect.Value, err error) {
|
||||||
t = reflect.TypeOf(e)
|
t = reflect.TypeOf(e)
|
||||||
if t == nil || t.Kind() != reflect.Ptr {
|
if t == nil || t.Kind() != reflect.Ptr {
|
||||||
return t, v, fmt.Errorf("ssob: Interface is not a valid address: %w", ErrTypeInvalid)
|
return t, v, ErrTypeInvalid
|
||||||
}
|
}
|
||||||
|
|
||||||
v = reflect.ValueOf(e)
|
v = reflect.ValueOf(e)
|
||||||
if v.IsNil() {
|
if v.IsNil() {
|
||||||
return t, v, fmt.Errorf("ssob: Got nil: %w", ErrValueInvalid)
|
return t, v, ErrValueInvalid
|
||||||
}
|
}
|
||||||
|
|
||||||
return t, v, err
|
return t, v, err
|
||||||
|
@ -575,37 +416,42 @@ func indirectType(e interface{}) (ret interface{}, ntype *NType, nilLevel uint16
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := 0; i < ntype.Indirection; i++ {
|
for i := 0; i < ntype.Indirection; i++ {
|
||||||
v = reflect.Indirect(v)
|
if v, err = indirectValue(v); err != nil {
|
||||||
if v.IsNil() {
|
return nil, ntype, nilLevel, ErrValueInvalid
|
||||||
|
}
|
||||||
|
if v.IsValid() && v.IsNil() {
|
||||||
nilLevel += uint16(i)
|
nilLevel += uint16(i)
|
||||||
return nil, ntype, nilLevel, err
|
return nil, ntype, nilLevel, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return reflect.Indirect(v).Interface(), ntype, nilLevel, err
|
if v, err = indirectValue(v); err != nil {
|
||||||
|
return nil, ntype, nilLevel, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return v.Interface(), ntype, nilLevel, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func setTypeNil(e interface{}, indirection int) (err error) {
|
func setTypeNil(e interface{}, indirection int) (err error) {
|
||||||
v := reflect.ValueOf(e)
|
var v reflect.Value
|
||||||
|
|
||||||
if v.Kind() != reflect.Ptr || v.IsNil() {
|
if v, err = getValPtr(e); err != nil {
|
||||||
return fmt.Errorf("ssob: Not a pointer: %w", ErrValueInvalid)
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
v = reflect.Indirect(v)
|
if v, err = indirectValue(v); err != nil {
|
||||||
if (v.Kind() != reflect.Ptr || v.IsNil()) && indirection > 0 {
|
if indirection > 0 {
|
||||||
return fmt.Errorf("ssob: Not a pointer: %w", ErrValueInvalid)
|
return ErrValueInvalid
|
||||||
}
|
|
||||||
|
|
||||||
for i := 0; i < indirection; i++ {
|
|
||||||
v = reflect.Indirect(v)
|
|
||||||
if v.Kind() != reflect.Ptr || v.IsNil() {
|
|
||||||
return fmt.Errorf("ssob: Not a pointer: %w", ErrValueInvalid)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
slog.LOG_DEBUGFLN("test")
|
for i := 0; i < indirection; i++ {
|
||||||
if !v.IsNil() {
|
if v, err = indirectValue(v); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if v.IsValid() && !v.IsNil() {
|
||||||
v.Set(reflect.Zero(reflect.TypeOf(v.Interface())))
|
v.Set(reflect.Zero(reflect.TypeOf(v.Interface())))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -613,33 +459,61 @@ func setTypeNil(e interface{}, indirection int) (err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func setTypeVal(e interface{}, val interface{}, ntype *NType) (err error) {
|
func setTypeVal(e interface{}, val interface{}, ntype *NType) (err error) {
|
||||||
v := reflect.ValueOf(e)
|
var v reflect.Value
|
||||||
|
|
||||||
if v.Kind() != reflect.Ptr || v.IsNil() {
|
if v, err = getValPtr(e); err != nil {
|
||||||
return fmt.Errorf("ssob: Not a pointer: %w", ErrValueInvalid)
|
return err
|
||||||
|
}
|
||||||
|
if v, err = indirectValue(v); err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
v = reflect.Indirect(v)
|
|
||||||
for i := 0; i < ntype.Indirection; i++ {
|
for i := 0; i < ntype.Indirection; i++ {
|
||||||
if v.Kind() != reflect.Ptr || v.IsNil() {
|
if v, err = indirectValue(v); err != nil {
|
||||||
return fmt.Errorf("ssob: Not a pointer: %w", ErrValueInvalid)
|
return err
|
||||||
}
|
}
|
||||||
v = reflect.Indirect(v)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
v.Set(reflect.ValueOf(val))
|
v.Set(reflect.ValueOf(val))
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getValPtr(e interface{}) (ret reflect.Value, err error) {
|
||||||
|
v := reflect.ValueOf(e)
|
||||||
|
|
||||||
|
if !v.IsValid() || v.Kind() != reflect.Ptr || v.IsNil() {
|
||||||
|
err = ErrValueInvalid
|
||||||
|
}
|
||||||
|
|
||||||
|
return v, err
|
||||||
|
}
|
||||||
|
|
||||||
func getVal(e interface{}) (ret reflect.Value) {
|
func getVal(e interface{}) (ret reflect.Value) {
|
||||||
v := reflect.ValueOf(e)
|
v := reflect.ValueOf(e)
|
||||||
|
|
||||||
if v.Kind() != reflect.Ptr || v.IsNil() {
|
if !v.IsValid() || v.Kind() != reflect.Ptr || v.IsNil() {
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
return reflect.Indirect(v)
|
return reflect.Indirect(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func indirectValue(v reflect.Value) (ret reflect.Value, err error) {
|
||||||
|
if !v.IsValid() || v.Kind() != reflect.Ptr {
|
||||||
|
return v, ErrValueInvalid
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = reflect.Indirect(v)
|
||||||
|
return ret, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func valueIsNil(v reflect.Value) (ret bool) {
|
||||||
|
ret = false
|
||||||
|
|
||||||
|
if !v.IsValid() || v.Kind() == reflect.Invalid || (v.Kind() == reflect.Ptr && v.IsNil()) {
|
||||||
|
ret = true
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
func RegisterType(e interface{}) (err error) {
|
func RegisterType(e interface{}) (err error) {
|
||||||
t := reflect.TypeOf(e)
|
t := reflect.TypeOf(e)
|
||||||
if t == nil || t.Kind() != reflect.Ptr {
|
if t == nil || t.Kind() != reflect.Ptr {
|
||||||
|
|
951
unmarshal.go
951
unmarshal.go
File diff suppressed because it is too large
Load Diff
|
@ -1,56 +0,0 @@
|
||||||
package ssob
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/binary"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"reflect"
|
|
||||||
"sync"
|
|
||||||
)
|
|
||||||
|
|
||||||
type UnsafeDecoder struct {
|
|
||||||
mutex sync.Mutex
|
|
||||||
r io.Reader
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewUnsafeDecoder(r io.Reader) *UnsafeDecoder {
|
|
||||||
dec := new(UnsafeDecoder)
|
|
||||||
dec.r = r
|
|
||||||
return dec
|
|
||||||
}
|
|
||||||
|
|
||||||
func (dec *UnsafeDecoder) Decode(e interface{}) (err error) {
|
|
||||||
return dec.DecodeValue(reflect.ValueOf(e))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (dec *UnsafeDecoder) DecodeValue(value reflect.Value) (err error) {
|
|
||||||
if value.Kind() == reflect.Invalid {
|
|
||||||
return fmt.Errorf("ssob: Cannot decode nil: %w", ErrValueInvalid)
|
|
||||||
}
|
|
||||||
|
|
||||||
if value.Kind() == reflect.Ptr && value.IsNil() {
|
|
||||||
return fmt.Errorf("ssob: Cannot decode nil of type %s: %w", value.Type().String(), ErrValueInvalid)
|
|
||||||
}
|
|
||||||
|
|
||||||
dec.mutex.Lock()
|
|
||||||
defer dec.mutex.Unlock()
|
|
||||||
|
|
||||||
lb := make([]byte, 4)
|
|
||||||
err = binary.Read(dec.r, binary.BigEndian, lb)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
l, n, err := UnsafeUnmarshalInt32(lb)
|
|
||||||
if err != nil || n != 4 {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
bb := make([]byte, l)
|
|
||||||
err = binary.Read(dec.r, binary.BigEndian, bb)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = unsafeUnmarshal(value.Interface(), bb)
|
|
||||||
return err
|
|
||||||
}
|
|
|
@ -1,49 +0,0 @@
|
||||||
package ssob
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/binary"
|
|
||||||
"fmt"
|
|
||||||
"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 fmt.Errorf("ssob: Cannot encode nil: %w", ErrValueInvalid)
|
|
||||||
}
|
|
||||||
|
|
||||||
if value.Kind() == reflect.Ptr && value.IsNil() {
|
|
||||||
return fmt.Errorf("ssob: Cannot encode nil of type %s: %w", value.Type().String(), ErrValueInvalid)
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
|
|
@ -1,527 +0,0 @@
|
||||||
package ssob
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"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 UnsafeMarshalBool(in bool) (ret []byte) {
|
|
||||||
if in {
|
|
||||||
return []byte{byte(0)}
|
|
||||||
}
|
|
||||||
|
|
||||||
return []byte{byte(1)}
|
|
||||||
}
|
|
||||||
|
|
||||||
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("bool", func(e interface{}) (ret []byte, err error) {
|
|
||||||
if i, ok := e.(bool); ok {
|
|
||||||
return UnsafeMarshalBool(i), nil
|
|
||||||
}
|
|
||||||
return nil, fmt.Errorf("ssob: Incompatible type - expected bool: %w", ErrTypeMismatch)
|
|
||||||
})
|
|
||||||
RegisterUnsafeEncoder("int8", func(e interface{}) (ret []byte, err error) {
|
|
||||||
if i, ok := e.(int8); ok {
|
|
||||||
return UnsafeMarshalInt8(i), nil
|
|
||||||
}
|
|
||||||
return nil, fmt.Errorf("ssob: Incompatible type - expected int8: %w", ErrTypeMismatch)
|
|
||||||
})
|
|
||||||
RegisterUnsafeEncoder("uint8", func(e interface{}) (ret []byte, err error) {
|
|
||||||
if i, ok := e.(uint8); ok {
|
|
||||||
return UnsafeMarshalUint8(i), nil
|
|
||||||
}
|
|
||||||
return nil, fmt.Errorf("ssob: Incompatible type - expected uint8: %w", ErrTypeMismatch)
|
|
||||||
})
|
|
||||||
RegisterUnsafeEncoder("int16", func(e interface{}) (ret []byte, err error) {
|
|
||||||
if i, ok := e.(int16); ok {
|
|
||||||
return UnsafeMarshalInt16(i), nil
|
|
||||||
}
|
|
||||||
return nil, fmt.Errorf("ssob: Incompatible type - expected int16: %w", ErrTypeMismatch)
|
|
||||||
})
|
|
||||||
RegisterUnsafeEncoder("uint16", func(e interface{}) (ret []byte, err error) {
|
|
||||||
if i, ok := e.(uint16); ok {
|
|
||||||
return UnsafeMarshalUint16(i), nil
|
|
||||||
}
|
|
||||||
return nil, fmt.Errorf("ssob: Incompatible type - expected uint16: %w", ErrTypeMismatch)
|
|
||||||
})
|
|
||||||
RegisterUnsafeEncoder("int32", func(e interface{}) (ret []byte, err error) {
|
|
||||||
if i, ok := e.(int32); ok {
|
|
||||||
return UnsafeMarshalInt32(i), nil
|
|
||||||
}
|
|
||||||
return nil, fmt.Errorf("ssob: Incompatible type - expected int32: %w", ErrTypeMismatch)
|
|
||||||
})
|
|
||||||
RegisterUnsafeEncoder("uint32", func(e interface{}) (ret []byte, err error) {
|
|
||||||
if i, ok := e.(uint32); ok {
|
|
||||||
return UnsafeMarshalUint32(i), nil
|
|
||||||
}
|
|
||||||
return nil, fmt.Errorf("ssob: Incompatible type - expected uint32: %w", ErrTypeMismatch)
|
|
||||||
})
|
|
||||||
RegisterUnsafeEncoder("float32", func(e interface{}) (ret []byte, err error) {
|
|
||||||
if i, ok := e.(float32); ok {
|
|
||||||
return UnsafeMarshalFloat32(i), nil
|
|
||||||
}
|
|
||||||
return nil, fmt.Errorf("ssob: Incompatible type - expected float32: %w", ErrTypeMismatch)
|
|
||||||
})
|
|
||||||
RegisterUnsafeEncoder("int64", func(e interface{}) (ret []byte, err error) {
|
|
||||||
if i, ok := e.(int64); ok {
|
|
||||||
return UnsafeMarshalInt64(i), nil
|
|
||||||
}
|
|
||||||
return nil, fmt.Errorf("ssob: Incompatible type - expected int64: %w", ErrTypeMismatch)
|
|
||||||
})
|
|
||||||
RegisterUnsafeEncoder("uint64", func(e interface{}) (ret []byte, err error) {
|
|
||||||
if i, ok := e.(uint64); ok {
|
|
||||||
return UnsafeMarshalUint64(i), nil
|
|
||||||
}
|
|
||||||
return nil, fmt.Errorf("ssob: Incompatible type - expected uint64: %w", ErrTypeMismatch)
|
|
||||||
})
|
|
||||||
RegisterUnsafeEncoder("float64", func(e interface{}) (ret []byte, err error) {
|
|
||||||
if i, ok := e.(float64); ok {
|
|
||||||
return UnsafeMarshalFloat64(i), nil
|
|
||||||
}
|
|
||||||
return nil, fmt.Errorf("ssob: Incompatible type - expected float64: %w", ErrTypeMismatch)
|
|
||||||
})
|
|
||||||
RegisterUnsafeEncoder("string", func(e interface{}) (ret []byte, err error) {
|
|
||||||
if i, ok := e.(string); ok {
|
|
||||||
return UnsafeMarshalString(i), nil
|
|
||||||
}
|
|
||||||
return nil, fmt.Errorf("ssob: Incompatible type - expected string: %w", ErrTypeMismatch)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func encRegisterUnsafe(e interface{}) (err error) {
|
|
||||||
t := reflect.TypeOf(e)
|
|
||||||
if t == nil {
|
|
||||||
return fmt.Errorf("ssob: nil type: %w", ErrTypeInvalid)
|
|
||||||
}
|
|
||||||
|
|
||||||
switch t.Kind() {
|
|
||||||
case reflect.Invalid:
|
|
||||||
return fmt.Errorf("ssob: invalid type: %w", ErrTypeInvalid)
|
|
||||||
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
|
|
||||||
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:
|
|
||||||
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 fmt.Errorf("ssob: No exported fields for %s: %w", string(t.Name()), ErrParseFailed)
|
|
||||||
}
|
|
||||||
|
|
||||||
f := func(e interface{}) (ret []byte, err error) {
|
|
||||||
v := reflect.ValueOf(e)
|
|
||||||
bs := make([][]byte, n)
|
|
||||||
blen := 0
|
|
||||||
for _, i := range mfields {
|
|
||||||
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
|
|
||||||
case reflect.Bool:
|
|
||||||
f := func(e interface{}) (ret []byte, err error) {
|
|
||||||
v := reflect.ValueOf(e)
|
|
||||||
return unsafeMarshalBaseType(bool(v.Bool()))
|
|
||||||
}
|
|
||||||
unsafeEncoderCache[t.Name()] = f
|
|
||||||
case reflect.Uint8:
|
|
||||||
f := func(e interface{}) (ret []byte, err error) {
|
|
||||||
v := reflect.ValueOf(e)
|
|
||||||
return unsafeMarshalBaseType(string(v.String()))
|
|
||||||
}
|
|
||||||
unsafeEncoderCache[t.Name()] = f
|
|
||||||
case reflect.Uint16:
|
|
||||||
f := func(e interface{}) (ret []byte, err error) {
|
|
||||||
v := reflect.ValueOf(e)
|
|
||||||
return unsafeMarshalBaseType(string(v.String()))
|
|
||||||
}
|
|
||||||
unsafeEncoderCache[t.Name()] = f
|
|
||||||
case reflect.Uint32:
|
|
||||||
f := func(e interface{}) (ret []byte, err error) {
|
|
||||||
v := reflect.ValueOf(e)
|
|
||||||
return unsafeMarshalBaseType(string(v.String()))
|
|
||||||
}
|
|
||||||
unsafeEncoderCache[t.Name()] = f
|
|
||||||
case reflect.Uint64:
|
|
||||||
f := func(e interface{}) (ret []byte, err error) {
|
|
||||||
v := reflect.ValueOf(e)
|
|
||||||
return unsafeMarshalBaseType(string(v.String()))
|
|
||||||
}
|
|
||||||
unsafeEncoderCache[t.Name()] = f
|
|
||||||
case reflect.Int8:
|
|
||||||
f := func(e interface{}) (ret []byte, err error) {
|
|
||||||
v := reflect.ValueOf(e)
|
|
||||||
return unsafeMarshalBaseType(string(v.String()))
|
|
||||||
}
|
|
||||||
unsafeEncoderCache[t.Name()] = f
|
|
||||||
case reflect.Int16:
|
|
||||||
f := func(e interface{}) (ret []byte, err error) {
|
|
||||||
v := reflect.ValueOf(e)
|
|
||||||
return unsafeMarshalBaseType(string(v.String()))
|
|
||||||
}
|
|
||||||
unsafeEncoderCache[t.Name()] = f
|
|
||||||
case reflect.Int32:
|
|
||||||
f := func(e interface{}) (ret []byte, err error) {
|
|
||||||
v := reflect.ValueOf(e)
|
|
||||||
return unsafeMarshalBaseType(string(v.String()))
|
|
||||||
}
|
|
||||||
unsafeEncoderCache[t.Name()] = f
|
|
||||||
case reflect.Int64:
|
|
||||||
f := func(e interface{}) (ret []byte, err error) {
|
|
||||||
v := reflect.ValueOf(e)
|
|
||||||
return unsafeMarshalBaseType(string(v.String()))
|
|
||||||
}
|
|
||||||
unsafeEncoderCache[t.Name()] = f
|
|
||||||
case reflect.String:
|
|
||||||
f := func(e interface{}) (ret []byte, err error) {
|
|
||||||
v := reflect.ValueOf(e)
|
|
||||||
return unsafeMarshalBaseType(string(v.String()))
|
|
||||||
}
|
|
||||||
unsafeEncoderCache[t.Name()] = f
|
|
||||||
default:
|
|
||||||
return fmt.Errorf("ssob: %s: %w", string(t.Name()), ErrTypeUnknown)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func unsafeMarshalBaseType(e interface{}) (ret []byte, err error) {
|
|
||||||
switch t := e.(type) {
|
|
||||||
case bool:
|
|
||||||
return unsafeEncoderCache["bool"](t)
|
|
||||||
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, fmt.Errorf("ssob: No base type: %w", ErrTypeUnknown)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
switch t.Kind() {
|
|
||||||
case reflect.Ptr:
|
|
||||||
if v.IsNil() {
|
|
||||||
return nil, fmt.Errorf("ssob: Cannot marshal nil pointer: %w", ErrValueInvalid)
|
|
||||||
}
|
|
||||||
p := reflect.Indirect(v)
|
|
||||||
return unsafeMarshal(p.Interface())
|
|
||||||
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:
|
|
||||||
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
|
|
||||||
}
|
|
|
@ -1,720 +0,0 @@
|
||||||
package ssob
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/binary"
|
|
||||||
"fmt"
|
|
||||||
"reflect"
|
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
|
|
||||||
func UnsafeUnmarshalString(in []byte) (ret string, n int, err error) {
|
|
||||||
if len(in) < 4 {
|
|
||||||
return "", 0, fmt.Errorf("ssob: Decoding string: %w", ErrTypeInvalid)
|
|
||||||
}
|
|
||||||
l := int32(binary.BigEndian.Uint32(in))
|
|
||||||
|
|
||||||
if len(in[4:]) < int(l) {
|
|
||||||
return "", 0, fmt.Errorf("ssob: Invalid length of string: %w", ErrValueInvalid)
|
|
||||||
}
|
|
||||||
return string(in[4 : l+4]), int(l) + 4, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func UnsafeUnmarshalBool(in []byte) (ret bool, n int, err error) {
|
|
||||||
if len(in) < 1 {
|
|
||||||
return false, 0, fmt.Errorf("ssob: Decoding bool: %w", ErrTypeInvalid)
|
|
||||||
}
|
|
||||||
|
|
||||||
if in[0] == byte(0) {
|
|
||||||
return true, 1, nil
|
|
||||||
}
|
|
||||||
return false, 1, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func UnsafeUnmarshalInt8(in []byte) (ret int8, n int, err error) {
|
|
||||||
if len(in) < 1 {
|
|
||||||
return 0, 0, fmt.Errorf("ssob: Decoding int8: %w", ErrTypeInvalid)
|
|
||||||
}
|
|
||||||
|
|
||||||
return int8(in[0]), 1, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func UnsafeUnmarshalUint8(in []byte) (ret uint8, n int, err error) {
|
|
||||||
if len(in) < 1 {
|
|
||||||
return 0, 0, fmt.Errorf("ssob: Decoding uint8: %w", ErrTypeInvalid)
|
|
||||||
}
|
|
||||||
|
|
||||||
return uint8(in[0]), 1, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func UnsafeUnmarshalInt16(in []byte) (ret int16, n int, err error) {
|
|
||||||
if len(in) < 2 {
|
|
||||||
return 0, 0, fmt.Errorf("ssob: Decoding int16: %w", ErrTypeInvalid)
|
|
||||||
}
|
|
||||||
|
|
||||||
var out int16
|
|
||||||
start := unsafe.Pointer(&out)
|
|
||||||
if littleEndian {
|
|
||||||
*(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(0))) = in[1]
|
|
||||||
*(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(1))) = in[0]
|
|
||||||
} else {
|
|
||||||
*(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(0))) = in[0]
|
|
||||||
*(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(1))) = in[1]
|
|
||||||
}
|
|
||||||
|
|
||||||
return out, 2, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func UnsafeUnmarshalUint16(in []byte) (ret uint16, n int, err error) {
|
|
||||||
if len(in) < 2 {
|
|
||||||
return 0, 0, fmt.Errorf("ssob: Decoding uint16: %w", ErrTypeInvalid)
|
|
||||||
}
|
|
||||||
|
|
||||||
var out uint16
|
|
||||||
start := unsafe.Pointer(&out)
|
|
||||||
if littleEndian {
|
|
||||||
*(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(0))) = in[1]
|
|
||||||
*(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(1))) = in[0]
|
|
||||||
} else {
|
|
||||||
*(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(0))) = in[0]
|
|
||||||
*(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(1))) = in[1]
|
|
||||||
}
|
|
||||||
|
|
||||||
return out, 2, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func UnsafeUnmarshalInt32(in []byte) (ret int32, n int, err error) {
|
|
||||||
if len(in) < 4 {
|
|
||||||
return 0, 0, fmt.Errorf("ssob: Decoding int32: %w", ErrTypeInvalid)
|
|
||||||
}
|
|
||||||
|
|
||||||
var out int32
|
|
||||||
start := unsafe.Pointer(&out)
|
|
||||||
if littleEndian {
|
|
||||||
*(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(0))) = in[3]
|
|
||||||
*(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(1))) = in[2]
|
|
||||||
*(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(2))) = in[1]
|
|
||||||
*(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(3))) = in[0]
|
|
||||||
} else {
|
|
||||||
*(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(0))) = in[0]
|
|
||||||
*(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(1))) = in[1]
|
|
||||||
*(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(2))) = in[2]
|
|
||||||
*(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(3))) = in[3]
|
|
||||||
}
|
|
||||||
|
|
||||||
return out, 4, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func UnsafeUnmarshalUint32(in []byte) (ret uint32, n int, err error) {
|
|
||||||
if len(in) < 4 {
|
|
||||||
return 0, 0, fmt.Errorf("ssob: Decoding uint32: %w", ErrTypeInvalid)
|
|
||||||
}
|
|
||||||
|
|
||||||
var out uint32
|
|
||||||
start := unsafe.Pointer(&out)
|
|
||||||
if littleEndian {
|
|
||||||
*(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(0))) = in[3]
|
|
||||||
*(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(1))) = in[2]
|
|
||||||
*(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(2))) = in[1]
|
|
||||||
*(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(3))) = in[0]
|
|
||||||
} else {
|
|
||||||
*(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(0))) = in[0]
|
|
||||||
*(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(1))) = in[1]
|
|
||||||
*(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(2))) = in[2]
|
|
||||||
*(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(3))) = in[3]
|
|
||||||
}
|
|
||||||
|
|
||||||
return out, 4, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func UnsafeUnmarshalFloat32(in []byte) (ret float32, n int, err error) {
|
|
||||||
if len(in) < 4 {
|
|
||||||
return 0, 0, fmt.Errorf("ssob: Decoding float32: %w", ErrTypeInvalid)
|
|
||||||
}
|
|
||||||
|
|
||||||
var out float32
|
|
||||||
start := unsafe.Pointer(&out)
|
|
||||||
if littleEndian {
|
|
||||||
*(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(0))) = in[3]
|
|
||||||
*(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(1))) = in[2]
|
|
||||||
*(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(2))) = in[1]
|
|
||||||
*(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(3))) = in[0]
|
|
||||||
} else {
|
|
||||||
*(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(0))) = in[0]
|
|
||||||
*(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(1))) = in[1]
|
|
||||||
*(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(2))) = in[2]
|
|
||||||
*(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(3))) = in[3]
|
|
||||||
}
|
|
||||||
|
|
||||||
return out, 4, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func UnsafeUnmarshalInt64(in []byte) (ret int64, n int, err error) {
|
|
||||||
if len(in) < 8 {
|
|
||||||
return 0, 0, fmt.Errorf("ssob: Decoding int64: %w", ErrTypeInvalid)
|
|
||||||
}
|
|
||||||
|
|
||||||
var out int64
|
|
||||||
start := unsafe.Pointer(&out)
|
|
||||||
if littleEndian {
|
|
||||||
*(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(0))) = in[7]
|
|
||||||
*(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(1))) = in[6]
|
|
||||||
*(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(2))) = in[5]
|
|
||||||
*(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(3))) = in[4]
|
|
||||||
*(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(4))) = in[3]
|
|
||||||
*(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(5))) = in[2]
|
|
||||||
*(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(6))) = in[1]
|
|
||||||
*(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(7))) = in[0]
|
|
||||||
} else {
|
|
||||||
*(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(0))) = in[0]
|
|
||||||
*(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(1))) = in[1]
|
|
||||||
*(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(2))) = in[2]
|
|
||||||
*(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(3))) = in[3]
|
|
||||||
*(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(4))) = in[4]
|
|
||||||
*(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(5))) = in[5]
|
|
||||||
*(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(6))) = in[6]
|
|
||||||
*(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(7))) = in[7]
|
|
||||||
}
|
|
||||||
|
|
||||||
return out, 8, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func UnsafeUnmarshalUint64(in []byte) (ret uint64, n int, err error) {
|
|
||||||
if len(in) < 8 {
|
|
||||||
return 0, 0, fmt.Errorf("ssob: Decoding uint64: %w", ErrTypeInvalid)
|
|
||||||
}
|
|
||||||
|
|
||||||
var out uint64
|
|
||||||
start := unsafe.Pointer(&out)
|
|
||||||
if littleEndian {
|
|
||||||
*(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(0))) = in[7]
|
|
||||||
*(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(1))) = in[6]
|
|
||||||
*(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(2))) = in[5]
|
|
||||||
*(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(3))) = in[4]
|
|
||||||
*(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(4))) = in[3]
|
|
||||||
*(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(5))) = in[2]
|
|
||||||
*(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(6))) = in[1]
|
|
||||||
*(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(7))) = in[0]
|
|
||||||
} else {
|
|
||||||
*(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(0))) = in[0]
|
|
||||||
*(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(1))) = in[1]
|
|
||||||
*(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(2))) = in[2]
|
|
||||||
*(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(3))) = in[3]
|
|
||||||
*(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(4))) = in[4]
|
|
||||||
*(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(5))) = in[5]
|
|
||||||
*(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(6))) = in[6]
|
|
||||||
*(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(7))) = in[7]
|
|
||||||
}
|
|
||||||
|
|
||||||
return out, 8, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func UnsafeUnmarshalFloat64(in []byte) (ret float64, n int, err error) {
|
|
||||||
if len(in) < 8 {
|
|
||||||
return 0, 0, fmt.Errorf("ssob: Decoding float64: %w", ErrTypeInvalid)
|
|
||||||
}
|
|
||||||
|
|
||||||
var out float64
|
|
||||||
start := unsafe.Pointer(&out)
|
|
||||||
if littleEndian {
|
|
||||||
*(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(0))) = in[7]
|
|
||||||
*(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(1))) = in[6]
|
|
||||||
*(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(2))) = in[5]
|
|
||||||
*(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(3))) = in[4]
|
|
||||||
*(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(4))) = in[3]
|
|
||||||
*(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(5))) = in[2]
|
|
||||||
*(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(6))) = in[1]
|
|
||||||
*(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(7))) = in[0]
|
|
||||||
} else {
|
|
||||||
*(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(0))) = in[0]
|
|
||||||
*(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(1))) = in[1]
|
|
||||||
*(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(2))) = in[2]
|
|
||||||
*(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(3))) = in[3]
|
|
||||||
*(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(4))) = in[4]
|
|
||||||
*(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(5))) = in[5]
|
|
||||||
*(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(6))) = in[6]
|
|
||||||
*(*byte)(unsafe.Pointer(uintptr(start) + sPtr*uintptr(7))) = in[7]
|
|
||||||
}
|
|
||||||
|
|
||||||
return out, 8, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var unsafeDecoderCache map[string]unmarshalFunc
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
unsafeDecoderCache = make(map[string]unmarshalFunc)
|
|
||||||
RegisterUnsafeDecoder("bool", func(e interface{}, in []byte) (n int, err error) {
|
|
||||||
if i, ok := e.(*bool); ok {
|
|
||||||
*i, n, err = UnsafeUnmarshalBool(in)
|
|
||||||
return n, nil
|
|
||||||
}
|
|
||||||
return 0, fmt.Errorf("ssob: Incompatible type - expected bool: %w", ErrTypeMismatch)
|
|
||||||
})
|
|
||||||
RegisterUnsafeDecoder("int8", func(e interface{}, in []byte) (n int, err error) {
|
|
||||||
if i, ok := e.(*int8); ok {
|
|
||||||
*i, n, err = UnsafeUnmarshalInt8(in)
|
|
||||||
return n, nil
|
|
||||||
}
|
|
||||||
return 0, fmt.Errorf("ssob: Incompatible type - expected int8: %w", ErrTypeMismatch)
|
|
||||||
})
|
|
||||||
RegisterUnsafeDecoder("uint8", func(e interface{}, in []byte) (n int, err error) {
|
|
||||||
if i, ok := e.(*uint8); ok {
|
|
||||||
*i, n, err = UnsafeUnmarshalUint8(in)
|
|
||||||
return n, nil
|
|
||||||
}
|
|
||||||
return 0, fmt.Errorf("ssob: Incompatible type - expected uint8: %w", ErrTypeMismatch)
|
|
||||||
})
|
|
||||||
RegisterUnsafeDecoder("int16", func(e interface{}, in []byte) (n int, err error) {
|
|
||||||
if i, ok := e.(*int16); ok {
|
|
||||||
*i, n, err = UnsafeUnmarshalInt16(in)
|
|
||||||
return n, nil
|
|
||||||
}
|
|
||||||
return 0, fmt.Errorf("ssob: Incompatible type - expected int16: %w", ErrTypeMismatch)
|
|
||||||
})
|
|
||||||
RegisterUnsafeDecoder("uint16", func(e interface{}, in []byte) (n int, err error) {
|
|
||||||
if i, ok := e.(*uint16); ok {
|
|
||||||
*i, n, err = UnsafeUnmarshalUint16(in)
|
|
||||||
return n, nil
|
|
||||||
}
|
|
||||||
return 0, fmt.Errorf("ssob: Incompatible type - expected uint16: %w", ErrTypeMismatch)
|
|
||||||
})
|
|
||||||
RegisterUnsafeDecoder("int32", func(e interface{}, in []byte) (n int, err error) {
|
|
||||||
if i, ok := e.(*int32); ok {
|
|
||||||
*i, n, err = UnsafeUnmarshalInt32(in)
|
|
||||||
return n, nil
|
|
||||||
}
|
|
||||||
return 0, fmt.Errorf("ssob: Incompatible type - expected int32: %w", ErrTypeMismatch)
|
|
||||||
})
|
|
||||||
RegisterUnsafeDecoder("uint32", func(e interface{}, in []byte) (n int, err error) {
|
|
||||||
if i, ok := e.(*uint32); ok {
|
|
||||||
*i, n, err = UnsafeUnmarshalUint32(in)
|
|
||||||
return n, nil
|
|
||||||
}
|
|
||||||
return 0, fmt.Errorf("ssob: Incompatible type - expected uint32: %w", ErrTypeMismatch)
|
|
||||||
})
|
|
||||||
RegisterUnsafeDecoder("float32", func(e interface{}, in []byte) (n int, err error) {
|
|
||||||
if i, ok := e.(*float32); ok {
|
|
||||||
*i, n, err = UnsafeUnmarshalFloat32(in)
|
|
||||||
return n, nil
|
|
||||||
}
|
|
||||||
return 0, fmt.Errorf("ssob: Incompatible type - expected float32: %w", ErrTypeMismatch)
|
|
||||||
})
|
|
||||||
RegisterUnsafeDecoder("int64", func(e interface{}, in []byte) (n int, err error) {
|
|
||||||
if i, ok := e.(*int64); ok {
|
|
||||||
*i, n, err = UnsafeUnmarshalInt64(in)
|
|
||||||
return n, nil
|
|
||||||
}
|
|
||||||
return 0, fmt.Errorf("ssob: Incompatible type - expected int64: %w", ErrTypeMismatch)
|
|
||||||
})
|
|
||||||
RegisterUnsafeDecoder("uint64", func(e interface{}, in []byte) (n int, err error) {
|
|
||||||
if i, ok := e.(*uint64); ok {
|
|
||||||
*i, n, err = UnsafeUnmarshalUint64(in)
|
|
||||||
return n, nil
|
|
||||||
}
|
|
||||||
return 0, fmt.Errorf("ssob: Incompatible type - expected uint64: %w", ErrTypeMismatch)
|
|
||||||
})
|
|
||||||
RegisterUnsafeDecoder("float64", func(e interface{}, in []byte) (n int, err error) {
|
|
||||||
if i, ok := e.(*float64); ok {
|
|
||||||
*i, n, err = UnsafeUnmarshalFloat64(in)
|
|
||||||
return n, nil
|
|
||||||
}
|
|
||||||
return 0, fmt.Errorf("ssob: Incompatible type - expected float64: %w", ErrTypeMismatch)
|
|
||||||
})
|
|
||||||
RegisterUnsafeDecoder("string", func(e interface{}, in []byte) (n int, err error) {
|
|
||||||
if i, ok := e.(*string); ok {
|
|
||||||
*i, n, err = UnsafeUnmarshalString(in)
|
|
||||||
return n, nil
|
|
||||||
}
|
|
||||||
return 0, fmt.Errorf("ssob: Incompatible type - expected string: %w", ErrTypeMismatch)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func decRegisterUnsafe(e interface{}) (err error) {
|
|
||||||
t := reflect.TypeOf(e)
|
|
||||||
if t == nil {
|
|
||||||
return fmt.Errorf("ssob: nil type: %w", ErrTypeInvalid)
|
|
||||||
}
|
|
||||||
|
|
||||||
switch t.Kind() {
|
|
||||||
case reflect.Invalid:
|
|
||||||
return fmt.Errorf("ssob: invalid type: %w", ErrTypeInvalid)
|
|
||||||
case reflect.Array:
|
|
||||||
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, fmt.Errorf("ssob: Cannot unmarshal to nil pointer: %w", ErrValueInvalid)
|
|
||||||
}
|
|
||||||
|
|
||||||
l, r, err := UnsafeUnmarshalInt32(in)
|
|
||||||
pos += r
|
|
||||||
if err != nil {
|
|
||||||
return pos, err
|
|
||||||
}
|
|
||||||
|
|
||||||
ti := v.Elem()
|
|
||||||
if int(l) != ti.Len() {
|
|
||||||
return pos, fmt.Errorf("ssob: Invalid array length. Expected %s got %s: %w", string(l), string(ti.Len()), ErrValueInvalid)
|
|
||||||
}
|
|
||||||
for i := 0; i < int(l); i++ {
|
|
||||||
e := reflect.New(reflect.TypeOf(ti.Interface()).Elem())
|
|
||||||
r, err := unsafeUnmarshal(e.Interface(), in[pos:])
|
|
||||||
pos += r
|
|
||||||
if err != nil {
|
|
||||||
return pos, err
|
|
||||||
}
|
|
||||||
ti.Index(i).Set(reflect.Indirect(e))
|
|
||||||
}
|
|
||||||
return pos, nil
|
|
||||||
}
|
|
||||||
unsafeDecoderCache[string(t.Kind())] = f
|
|
||||||
case reflect.Slice:
|
|
||||||
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, fmt.Errorf("ssob: Cannot unmarshal to nil pointer: %w", ErrValueInvalid)
|
|
||||||
}
|
|
||||||
|
|
||||||
l, r, err := UnsafeUnmarshalInt32(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 := unsafeUnmarshal(e.Interface(), in[pos:])
|
|
||||||
pos += r
|
|
||||||
if err != nil {
|
|
||||||
return pos, err
|
|
||||||
}
|
|
||||||
ti.Set(reflect.Append(ti, reflect.Indirect(e)))
|
|
||||||
}
|
|
||||||
return pos, nil
|
|
||||||
}
|
|
||||||
unsafeDecoderCache[string(t.Kind())] = f
|
|
||||||
case reflect.Struct:
|
|
||||||
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 fmt.Errorf("ssob: No exported fields for %s: %w", string(t.Name()), ErrParseFailed)
|
|
||||||
}
|
|
||||||
|
|
||||||
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, fmt.Errorf("ssob: Cannot unmarshal to nil pointer: %w", ErrValueInvalid)
|
|
||||||
}
|
|
||||||
|
|
||||||
vi := reflect.Indirect(v)
|
|
||||||
for _, i := range mfields {
|
|
||||||
ni, err := unsafeUnmarshal(vi.Field(i).Addr().Interface(), in[pos:])
|
|
||||||
pos += ni
|
|
||||||
if err != nil {
|
|
||||||
return pos, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return pos, nil
|
|
||||||
}
|
|
||||||
unsafeDecoderCache[t.Name()] = f
|
|
||||||
case reflect.Map:
|
|
||||||
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, fmt.Errorf("ssob: Cannot unmarshal to nil pointer: %w", ErrValueInvalid)
|
|
||||||
}
|
|
||||||
|
|
||||||
l, r, err := UnsafeUnmarshalInt32(in)
|
|
||||||
pos += r
|
|
||||||
if err != nil {
|
|
||||||
return pos, err
|
|
||||||
}
|
|
||||||
|
|
||||||
vi := reflect.Indirect(v)
|
|
||||||
vt := reflect.TypeOf(vi.Interface())
|
|
||||||
tk := vt.Key()
|
|
||||||
tv := vt.Elem()
|
|
||||||
for i := int32(0); i < l; i++ {
|
|
||||||
ek := reflect.New(tk)
|
|
||||||
ev := reflect.New(tv)
|
|
||||||
r, err := unsafeUnmarshal(ek.Interface(), in[pos:])
|
|
||||||
pos += r
|
|
||||||
if err != nil {
|
|
||||||
return pos, err
|
|
||||||
}
|
|
||||||
r, err = unsafeUnmarshal(ev.Interface(), in[pos:])
|
|
||||||
pos += r
|
|
||||||
if err != nil {
|
|
||||||
return pos, err
|
|
||||||
}
|
|
||||||
vi.SetMapIndex(reflect.Indirect(ek), reflect.Indirect(ev))
|
|
||||||
}
|
|
||||||
|
|
||||||
return pos, nil
|
|
||||||
}
|
|
||||||
unsafeDecoderCache[string(t.Kind())] = f
|
|
||||||
case reflect.Bool:
|
|
||||||
f := func(e interface{}, in []byte) (n int, err error) {
|
|
||||||
v := reflect.ValueOf(e)
|
|
||||||
i := bool(false)
|
|
||||||
pos := 0
|
|
||||||
|
|
||||||
r, err := unsafeUnmarshalBaseType(&i, in[pos:])
|
|
||||||
pos += r
|
|
||||||
if err != nil {
|
|
||||||
return pos, err
|
|
||||||
}
|
|
||||||
v.Elem().SetBool(bool(i))
|
|
||||||
|
|
||||||
return pos, nil
|
|
||||||
}
|
|
||||||
unsafeDecoderCache[t.Name()] = f
|
|
||||||
case reflect.Uint8:
|
|
||||||
f := func(e interface{}, in []byte) (n int, err error) {
|
|
||||||
v := reflect.ValueOf(e)
|
|
||||||
i := uint8(0)
|
|
||||||
pos := 0
|
|
||||||
|
|
||||||
r, err := unsafeUnmarshalBaseType(&i, in[pos:])
|
|
||||||
pos += r
|
|
||||||
if err != nil {
|
|
||||||
return pos, err
|
|
||||||
}
|
|
||||||
v.Elem().SetUint(uint64(i))
|
|
||||||
|
|
||||||
return pos, nil
|
|
||||||
}
|
|
||||||
unsafeDecoderCache[t.Name()] = f
|
|
||||||
case reflect.Uint16:
|
|
||||||
f := func(e interface{}, in []byte) (n int, err error) {
|
|
||||||
v := reflect.ValueOf(e)
|
|
||||||
i := uint16(0)
|
|
||||||
pos := 0
|
|
||||||
|
|
||||||
r, err := unsafeUnmarshalBaseType(&i, in[pos:])
|
|
||||||
pos += r
|
|
||||||
if err != nil {
|
|
||||||
return pos, err
|
|
||||||
}
|
|
||||||
v.Elem().SetUint(uint64(i))
|
|
||||||
|
|
||||||
return pos, nil
|
|
||||||
}
|
|
||||||
unsafeDecoderCache[t.Name()] = f
|
|
||||||
case reflect.Uint32:
|
|
||||||
f := func(e interface{}, in []byte) (n int, err error) {
|
|
||||||
v := reflect.ValueOf(e)
|
|
||||||
i := uint32(0)
|
|
||||||
pos := 0
|
|
||||||
|
|
||||||
r, err := unsafeUnmarshalBaseType(&i, in[pos:])
|
|
||||||
pos += r
|
|
||||||
if err != nil {
|
|
||||||
return pos, err
|
|
||||||
}
|
|
||||||
v.Elem().SetUint(uint64(i))
|
|
||||||
|
|
||||||
return pos, nil
|
|
||||||
}
|
|
||||||
unsafeDecoderCache[t.Name()] = f
|
|
||||||
case reflect.Uint64:
|
|
||||||
f := func(e interface{}, in []byte) (n int, err error) {
|
|
||||||
v := reflect.ValueOf(e)
|
|
||||||
i := uint64(0)
|
|
||||||
pos := 0
|
|
||||||
|
|
||||||
r, err := unsafeUnmarshalBaseType(&i, in[pos:])
|
|
||||||
pos += r
|
|
||||||
if err != nil {
|
|
||||||
return pos, err
|
|
||||||
}
|
|
||||||
v.Elem().SetUint(uint64(i))
|
|
||||||
|
|
||||||
return pos, nil
|
|
||||||
}
|
|
||||||
unsafeDecoderCache[t.Name()] = f
|
|
||||||
case reflect.Int8:
|
|
||||||
f := func(e interface{}, in []byte) (n int, err error) {
|
|
||||||
v := reflect.ValueOf(e)
|
|
||||||
i := int8(0)
|
|
||||||
pos := 0
|
|
||||||
|
|
||||||
r, err := unsafeUnmarshalBaseType(&i, in[pos:])
|
|
||||||
pos += r
|
|
||||||
if err != nil {
|
|
||||||
return pos, err
|
|
||||||
}
|
|
||||||
v.Elem().SetInt(int64(i))
|
|
||||||
|
|
||||||
return pos, nil
|
|
||||||
}
|
|
||||||
unsafeDecoderCache[t.Name()] = f
|
|
||||||
case reflect.Int16:
|
|
||||||
f := func(e interface{}, in []byte) (n int, err error) {
|
|
||||||
v := reflect.ValueOf(e)
|
|
||||||
i := int16(0)
|
|
||||||
pos := 0
|
|
||||||
|
|
||||||
r, err := unsafeUnmarshalBaseType(&i, in[pos:])
|
|
||||||
pos += r
|
|
||||||
if err != nil {
|
|
||||||
return pos, err
|
|
||||||
}
|
|
||||||
v.Elem().SetInt(int64(i))
|
|
||||||
|
|
||||||
return pos, nil
|
|
||||||
}
|
|
||||||
unsafeDecoderCache[t.Name()] = f
|
|
||||||
case reflect.Int32:
|
|
||||||
f := func(e interface{}, in []byte) (n int, err error) {
|
|
||||||
v := reflect.ValueOf(e)
|
|
||||||
i := int32(0)
|
|
||||||
pos := 0
|
|
||||||
|
|
||||||
r, err := unsafeUnmarshalBaseType(&i, in[pos:])
|
|
||||||
pos += r
|
|
||||||
if err != nil {
|
|
||||||
return pos, err
|
|
||||||
}
|
|
||||||
v.Elem().SetInt(int64(i))
|
|
||||||
|
|
||||||
return pos, nil
|
|
||||||
}
|
|
||||||
unsafeDecoderCache[t.Name()] = f
|
|
||||||
case reflect.Int64:
|
|
||||||
f := func(e interface{}, in []byte) (n int, err error) {
|
|
||||||
v := reflect.ValueOf(e)
|
|
||||||
i := int64(0)
|
|
||||||
pos := 0
|
|
||||||
|
|
||||||
r, err := unsafeUnmarshalBaseType(&i, in[pos:])
|
|
||||||
pos += r
|
|
||||||
if err != nil {
|
|
||||||
return pos, err
|
|
||||||
}
|
|
||||||
v.Elem().SetInt(int64(i))
|
|
||||||
|
|
||||||
return pos, nil
|
|
||||||
}
|
|
||||||
unsafeDecoderCache[t.Name()] = f
|
|
||||||
case reflect.String:
|
|
||||||
f := func(e interface{}, in []byte) (n int, err error) {
|
|
||||||
v := reflect.ValueOf(e)
|
|
||||||
i := string("")
|
|
||||||
pos := 0
|
|
||||||
|
|
||||||
r, err := unsafeUnmarshalBaseType(&i, in[pos:])
|
|
||||||
pos += r
|
|
||||||
if err != nil {
|
|
||||||
return pos, err
|
|
||||||
}
|
|
||||||
v.Elem().SetString(i)
|
|
||||||
|
|
||||||
return pos, nil
|
|
||||||
}
|
|
||||||
unsafeDecoderCache[t.Name()] = f
|
|
||||||
default:
|
|
||||||
return fmt.Errorf("ssob: %s: %w", string(t.Name()), ErrTypeUnknown)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func unsafeUnmarshalBaseType(e interface{}, in []byte) (n int, err error) {
|
|
||||||
switch t := e.(type) {
|
|
||||||
case *bool:
|
|
||||||
return unsafeDecoderCache["bool"](t, in)
|
|
||||||
case *int8:
|
|
||||||
return unsafeDecoderCache["int8"](t, in)
|
|
||||||
case *uint8:
|
|
||||||
return unsafeDecoderCache["uint8"](t, in)
|
|
||||||
case *int16:
|
|
||||||
return unsafeDecoderCache["int16"](t, in)
|
|
||||||
case *uint16:
|
|
||||||
return unsafeDecoderCache["uint16"](t, in)
|
|
||||||
case *int32:
|
|
||||||
return unsafeDecoderCache["int32"](t, in)
|
|
||||||
case *uint32:
|
|
||||||
return unsafeDecoderCache["uint32"](t, in)
|
|
||||||
case *int64:
|
|
||||||
return unsafeDecoderCache["int64"](t, in)
|
|
||||||
case *uint64:
|
|
||||||
return unsafeDecoderCache["uint64"](t, in)
|
|
||||||
case *float32:
|
|
||||||
return unsafeDecoderCache["float32"](t, in)
|
|
||||||
case *float64:
|
|
||||||
return unsafeDecoderCache["float64"](t, in)
|
|
||||||
case *string:
|
|
||||||
return unsafeDecoderCache["string"](t, in)
|
|
||||||
default:
|
|
||||||
return 0, fmt.Errorf("ssob: No base type: %w", ErrTypeUnknown)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func unsafeUnmarshal(e interface{}, in []byte) (n int, err error) {
|
|
||||||
n, err = unsafeUnmarshalBaseType(e, in)
|
|
||||||
if err == nil {
|
|
||||||
return n, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var key string
|
|
||||||
t := reflect.TypeOf(e)
|
|
||||||
v := reflect.ValueOf(e)
|
|
||||||
if t.Kind() != reflect.Ptr || v.IsNil() {
|
|
||||||
return 0, fmt.Errorf("ssob: Need a pointer that is fully allocated for unmarshalling: %w", ErrValueInvalid)
|
|
||||||
}
|
|
||||||
|
|
||||||
p := reflect.Indirect(v)
|
|
||||||
if p.Kind() != reflect.Ptr {
|
|
||||||
switch p.Kind() {
|
|
||||||
case reflect.Bool, reflect.Int8, reflect.Int16, reflect.Int32,
|
|
||||||
reflect.Int64, reflect.Uint8, reflect.Uint16, reflect.Uint32,
|
|
||||||
reflect.Uint64, reflect.String, reflect.Struct:
|
|
||||||
key = reflect.TypeOf(p.Interface()).Name()
|
|
||||||
default:
|
|
||||||
key = string(p.Kind())
|
|
||||||
}
|
|
||||||
|
|
||||||
if f, ok := unsafeDecoderCache[key]; ok {
|
|
||||||
return f(v.Interface(), in)
|
|
||||||
} else {
|
|
||||||
err = decRegisterUnsafe(p.Interface())
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
return unsafeUnmarshal(e, in)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !p.Elem().IsValid() {
|
|
||||||
err = allocType(v)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
p = reflect.Indirect(v)
|
|
||||||
}
|
|
||||||
|
|
||||||
return unsafeUnmarshal(p.Interface(), in)
|
|
||||||
}
|
|
||||||
|
|
||||||
func RegisterUnsafeDecoder(name string, f func(e interface{}, in []byte) (n int, err error)) {
|
|
||||||
unsafeDecoderCache[name] = f
|
|
||||||
}
|
|
Loading…
Reference in New Issue