Unmarshalling implemented

This commit is contained in:
Matthias Fulz 2021-09-06 23:33:50 +02:00
parent 8023e70530
commit a8d0eabd84
5 changed files with 449 additions and 49 deletions

View File

@ -81,10 +81,17 @@ func (dec *Decoder) NDecode() (ret interface{}, err error) {
return nil, err return nil, err
} }
stype := binary.BigEndian.Uint32(st) l := binary.BigEndian.Uint32(st)
if t, ok := cacheTypes.types[stype]; !ok { b := make([]byte, l)
return nil, fmt.Errorf("ssob: Decode type '%d' not registered: %w", stype, ErrTypeUnknown)
} else { var rl int
return t.unmarshal(dec.r) if rl, err = dec.r.Read(b); err != nil || rl != int(l) {
return nil, fmt.Errorf("ssob: Cannot decode value: %w", err)
} }
_, ret, err = unmarshalVal(b)
if err != nil {
return ret, err
}
return getVal(ret).Interface(), err
} }

View File

@ -69,7 +69,23 @@ func (enc *Encoder) EncodeValue(value reflect.Value) (err error) {
func (enc *Encoder) NEncode(e interface{}) (err error) { func (enc *Encoder) NEncode(e interface{}) (err error) {
RegisterType(e) RegisterType(e)
return enc.encode(e, 0) for _, t := range cacheTypes.ntypes {
slog.LOG_DEBUGFLN("t: %v", t)
}
var b []byte
if b, err = marshalVal(e); err != nil {
return fmt.Errorf("ssob: Cannot encode value: %w", err)
}
enc.mutex.Lock()
defer enc.mutex.Unlock()
if _, err = enc.w.Write(b); err != nil {
return fmt.Errorf("ssob: Cannot encode value: %w", err)
}
return nil
} }
func (enc *Encoder) encode(e interface{}, indirectLevel int) (err error) { func (enc *Encoder) encode(e interface{}, indirectLevel int) (err error) {

View File

@ -6,8 +6,6 @@ import (
"io" "io"
"math" "math"
"reflect" "reflect"
"gitea.olznet.de/OlzNet/slog"
) )
func MarshalString(in string) (ret []byte) { func MarshalString(in string) (ret []byte) {
@ -486,10 +484,11 @@ func baseTypeMarshaller(e interface{}, w io.Writer) (err error) {
} }
func marshalBool(e bool) (ret []byte) { func marshalBool(e bool) (ret []byte) {
ret = make([]byte, ST_ID_SIZE+1) ret = make([]byte, 1)
ret[0] = 1
if e == true { if e == true {
ret[0] = 0 ret[0] = 0
} else {
ret[0] = 1
} }
return ret return ret
} }
@ -581,12 +580,12 @@ func marshalPtrIfNil(e interface{}, ntype *NType) (ie interface{}, ret []byte, i
for i := 0; i < ntype.Indirection; i++ { for i := 0; i < ntype.Indirection; i++ {
v = reflect.Indirect(v) v = reflect.Indirect(v)
nl++
if v.Kind() == reflect.Invalid || (v.Kind() == reflect.Ptr && v.IsNil()) { if v.Kind() == reflect.Invalid || (v.Kind() == reflect.Ptr && v.IsNil()) {
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
} }
nl++
} }
ret = append(ret, marshalTypeId(ntype.ValType)...) ret = append(ret, marshalTypeId(ntype.ValType)...)
@ -602,14 +601,27 @@ func marshalError(e interface{}, ntype *NType) (ret []byte, err error) {
return ret, err return ret, err
} }
errorString := false
for i := 0; i < ntype.Indirection; i++ { for i := 0; i < ntype.Indirection; i++ {
t := reflect.TypeOf(v.Interface())
if t.String() == "errors.errorString" {
errorString = true
break
}
v = reflect.Indirect(v) v = reflect.Indirect(v)
nl++
if v.Kind() == reflect.Invalid || v.IsNil() { if v.Kind() == reflect.Invalid || v.IsNil() {
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
} }
nl++
}
if errorString {
ret = append(ret, marshalTypeId(ST_STRING)...)
ret = append(ret, marshalString(fmt.Sprintf("%v", v.Interface()))...)
return ret, err
} }
ierr, ok := v.Interface().(error) ierr, ok := v.Interface().(error)
@ -795,7 +807,6 @@ func marshalStruct(e interface{}, ntype *NType) (ret []byte, err error) {
if ftype == nil { if ftype == nil {
return ret, fmt.Errorf("ssob: Unknown type '%d': %w", field.Id, ErrTypeUnknown) return ret, fmt.Errorf("ssob: Unknown type '%d': %w", field.Id, ErrTypeUnknown)
} }
slog.LOG_DEBUGFLN("sfield: %v", ftype)
tbytes, err := marshalType(v.Field(i).Interface(), ftype) tbytes, err := marshalType(v.Field(i).Interface(), ftype)
if err != nil { if err != nil {
return ret, err return ret, err
@ -837,16 +848,18 @@ func marshalVal(e interface{}) (ret []byte, err error) {
if err != nil { if err != nil {
return ret, err return ret, err
} }
slog.LOG_DEBUGFLN("i: %v | n: %v | nl: %v | err: %v", i, n, nl, err)
// type id // type id
bytes := marshalTypeId(n.Id) bytes := marshalTypeId(n.Id)
// nil pointer // nil pointer
if i == nil { if i == nil {
bytes = append(bytes, marshalTypeId(ST_NIL)...) // nil
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)...)
if tbytes, err := marshalType(i, n); err != nil { if tbytes, err := marshalType(i, n); err != nil {
return ret, err return ret, err
} else { } else {

View File

@ -368,6 +368,7 @@ func parseType(t reflect.Type) (ret nallocFunc, mainTypeId uint32, indirection i
break break
} }
} }
//return vret
return vret.Interface() return vret.Interface()
} }
@ -386,18 +387,11 @@ func parseType(t reflect.Type) (ret nallocFunc, mainTypeId uint32, indirection i
val = val.Elem() val = val.Elem()
indirection += 1 indirection += 1
base = false base = false
slog.LOG_DEBUGFLN("Indirection: %d", indirection)
} else { } else {
slog.LOG_DEBUGFLN("ELSE: %v", t)
switch val.Kind() { switch val.Kind() {
case reflect.Slice: case reflect.Slice:
typ := reflect.TypeOf(val.Interface()) typ := reflect.TypeOf(val.Interface())
slog.LOG_DEBUGFLN("typ.Kind(): %s", typ.Kind())
slog.LOG_DEBUGFLN("val.Type(): %s", typ.Elem())
slog.LOG_DEBUGFLN("SLICE")
vt, err := getTypeByNameRegister(typ.Elem().String(), typ.Elem()) vt, err := getTypeByNameRegister(typ.Elem().String(), typ.Elem())
slog.LOG_DEBUGFLN("vt: %v", vt)
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, fmt.Errorf("ssob: Failed receiving type '%s': %w", typ.Elem(), err)
} }
@ -407,11 +401,7 @@ func parseType(t reflect.Type) (ret nallocFunc, mainTypeId uint32, indirection i
case reflect.Array: case reflect.Array:
typ := reflect.TypeOf(val.Interface()) typ := reflect.TypeOf(val.Interface())
arrayLen = val.Len() arrayLen = val.Len()
slog.LOG_DEBUGFLN("typ.Kind(): %s", typ.Kind())
slog.LOG_DEBUGFLN("val.Type(): %s", typ.Elem())
slog.LOG_DEBUGFLN("ARRAY")
vt, err := getTypeByNameRegister(typ.Elem().String(), typ.Elem()) vt, err := getTypeByNameRegister(typ.Elem().String(), typ.Elem())
slog.LOG_DEBUGFLN("vt: %v", vt)
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, fmt.Errorf("ssob: Failed receiving type '%s': %w", typ.Elem(), err)
} }
@ -420,11 +410,8 @@ func parseType(t reflect.Type) (ret nallocFunc, mainTypeId uint32, indirection i
mainTypeId = ST_ARRAY mainTypeId = ST_ARRAY
case reflect.Interface: case reflect.Interface:
typ := reflect.TypeOf(nval.Interface()) typ := reflect.TypeOf(nval.Interface())
slog.LOG_DEBUGFLN("val.Type(): %s", typ.Elem())
slog.LOG_DEBUGFLN("INTERFACE")
if !base { if !base {
vt, err := getTypeByNameRegister(typ.Elem().String(), typ.Elem()) vt, err := getTypeByNameRegister(typ.Elem().String(), typ.Elem())
slog.LOG_DEBUGFLN("vt: %v", vt)
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, fmt.Errorf("ssob: Failed receiving type '%s': %w", typ.Elem(), err)
} }
@ -433,11 +420,8 @@ func parseType(t reflect.Type) (ret nallocFunc, mainTypeId uint32, indirection i
mainTypeId = ST_INTERFACE mainTypeId = ST_INTERFACE
case reflect.Struct: case reflect.Struct:
typ := reflect.TypeOf(val.Interface()) typ := reflect.TypeOf(val.Interface())
slog.LOG_DEBUGFLN("typ.Kind(): %s", typ.String())
slog.LOG_DEBUGFLN("STRUCT")
if !base { if !base {
vt, err := getTypeByNameRegister(typ.String(), typ) vt, err := getTypeByNameRegister(typ.String(), typ)
slog.LOG_DEBUGFLN("vt: %v", vt)
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, fmt.Errorf("ssob: Failed receiving type '%s': %w", typ.Elem(), err)
} }
@ -446,7 +430,6 @@ func parseType(t reflect.Type) (ret nallocFunc, mainTypeId uint32, indirection i
sl := val.NumField() sl := val.NumField()
for i := 0; i < sl; i++ { for i := 0; i < sl; i++ {
if val.Field(i).CanSet() { if val.Field(i).CanSet() {
slog.LOG_DEBUGFLN("Struct '%s': Field '%d' '%s' -> '%v'", typ.String(), i, val.Type().Field(i).Name, val.Field(i).Type())
sfield := new(StructField) sfield := new(StructField)
sfield.Name = val.Type().Field(i).Name sfield.Name = val.Type().Field(i).Name
sfield.Tag = string(val.Type().Field(i).Tag) sfield.Tag = string(val.Type().Field(i).Tag)
@ -458,18 +441,13 @@ func parseType(t reflect.Type) (ret nallocFunc, mainTypeId uint32, indirection i
sfields = append(sfields, sfield) sfields = append(sfields, sfield)
} }
} }
base = false base = true
} }
mainTypeId = ST_STRUCT mainTypeId = ST_STRUCT
case reflect.Map: case reflect.Map:
typ := reflect.TypeOf(val.Interface()) typ := reflect.TypeOf(val.Interface())
slog.LOG_DEBUGFLN("typ.Kind(): %s", typ.String())
slog.LOG_DEBUGFLN("MAP")
slog.LOG_DEBUGFLN("key: %s", typ.Key())
slog.LOG_DEBUGFLN("val: %s", typ.Elem())
if !base { if !base {
vt, err := getTypeByNameRegister(typ.String(), typ) vt, err := getTypeByNameRegister(typ.String(), typ)
slog.LOG_DEBUGFLN("vt: %v", vt)
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, fmt.Errorf("ssob: Failed receiving type '%s': %w", typ.Elem(), err)
} }
@ -477,7 +455,6 @@ func parseType(t reflect.Type) (ret nallocFunc, mainTypeId uint32, indirection i
} else { } else {
// Key // Key
vt, err := getTypeByNameRegister(typ.Key().String(), typ.Key()) vt, err := getTypeByNameRegister(typ.Key().String(), typ.Key())
slog.LOG_DEBUGFLN("vt: %v", vt)
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, fmt.Errorf("ssob: Failed receiving type '%s': %w", typ.Elem(), err)
} }
@ -485,7 +462,6 @@ func parseType(t reflect.Type) (ret nallocFunc, mainTypeId uint32, indirection i
// Val // Val
vt, err = getTypeByNameRegister(typ.Elem().String(), typ.Elem()) vt, err = getTypeByNameRegister(typ.Elem().String(), typ.Elem())
slog.LOG_DEBUGFLN("vt: %v", vt)
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, fmt.Errorf("ssob: Failed receiving type '%s': %w", typ.Elem(), err)
} }
@ -495,11 +471,8 @@ func parseType(t reflect.Type) (ret nallocFunc, mainTypeId uint32, indirection i
mainTypeId = ST_MAP mainTypeId = ST_MAP
default: default:
typ := reflect.TypeOf(val.Interface()) typ := reflect.TypeOf(val.Interface())
slog.LOG_DEBUGFLN("typ.Kind(): %s", typ.Kind())
slog.LOG_DEBUGFLN("COMMON")
if !base { if !base {
vt, err := getTypeByNameRegister(typ.Kind().String(), typ) vt, err := getTypeByNameRegister(typ.Kind().String(), typ)
slog.LOG_DEBUGFLN("vt: %v", vt)
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, fmt.Errorf("ssob: Failed receiving type '%s': %w", typ.Elem(), err)
} }
@ -537,7 +510,6 @@ func createType(t reflect.Type) (ret *NType, base bool, err error) {
ret = new(NType) ret = new(NType)
ret.Name = t.String() ret.Name = t.String()
slog.LOG_DEBUGFLN("t.Name(): %s", t)
ret.alloc, ret.MainTypeId, ret.Indirection, ret.ValType, base, ret.structFields, ret.arrayLen, err = parseType(t) ret.alloc, ret.MainTypeId, ret.Indirection, ret.ValType, base, ret.structFields, ret.arrayLen, err = parseType(t)
return ret, base, err return ret, base, err
@ -565,12 +537,12 @@ func registerType(t reflect.Type) (err error) {
cacheTypes.nnames[ntype.Name] = ntype cacheTypes.nnames[ntype.Name] = ntype
cacheTypes.NextId += 1 cacheTypes.NextId += 1
slog.LOG_DEBUGFLN("Registered type: %v", ntype)
if ntype.MainTypeId == ST_STRUCT { if ntype.MainTypeId == ST_STRUCT {
for _, f := range ntype.structFields { for _, f := range ntype.structFields {
slog.LOG_DEBUGFLN(" Field: %v", f) slog.LOG_DEBUGFLN(" Field: %v", f)
} }
} }
slog.LOG_DEBUGFLN("Type: %v registered", t)
return err return err
} }
@ -613,6 +585,61 @@ func indirectType(e interface{}) (ret interface{}, ntype *NType, nilLevel uint16
return reflect.Indirect(v).Interface(), ntype, nilLevel, err return reflect.Indirect(v).Interface(), ntype, nilLevel, err
} }
func setTypeNil(e interface{}, indirection int) (err error) {
v := reflect.ValueOf(e)
if v.Kind() != reflect.Ptr || v.IsNil() {
return fmt.Errorf("ssob: Not a pointer: %w", ErrValueInvalid)
}
v = reflect.Indirect(v)
if (v.Kind() != reflect.Ptr || v.IsNil()) && indirection > 0 {
return fmt.Errorf("ssob: Not a pointer: %w", 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")
if !v.IsNil() {
v.Set(reflect.Zero(reflect.TypeOf(v.Interface())))
}
return err
}
func setTypeVal(e interface{}, val interface{}, ntype *NType) (err error) {
v := reflect.ValueOf(e)
if v.Kind() != reflect.Ptr || v.IsNil() {
return fmt.Errorf("ssob: Not a pointer: %w", ErrValueInvalid)
}
v = reflect.Indirect(v)
for i := 0; i < ntype.Indirection; i++ {
if v.Kind() != reflect.Ptr || v.IsNil() {
return fmt.Errorf("ssob: Not a pointer: %w", ErrValueInvalid)
}
v = reflect.Indirect(v)
}
v.Set(reflect.ValueOf(val))
return err
}
func getVal(e interface{}) (ret reflect.Value) {
v := reflect.ValueOf(e)
if v.Kind() != reflect.Ptr || v.IsNil() {
return v
}
return reflect.Indirect(v)
}
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 {
@ -623,7 +650,5 @@ func RegisterType(e interface{}) (err error) {
return err return err
} }
b, ee := marshalVal(e) return nil
slog.LOG_DEBUGFLN("Bytes: %v | err: %v", b, ee)
return ee
} }

View File

@ -696,3 +696,342 @@ func baseTypeUnmarshaller(e uint32, r io.Reader) (ret interface{}, err error) {
return ret, err return ret, err
} }
func unmarshalBool(e []byte) (ie []byte, ret bool) {
if e[0] == 0 {
ret = true
} else {
ret = false
}
return e[1:], ret
}
func unmarshalUint8(e []byte) (ie []byte, ret uint8) {
return e[1:], uint8(byte(e[0]))
}
func unmarshalUint16(e []byte) (ie []byte, ret uint16) {
return e[2:], binary.BigEndian.Uint16(e)
}
func unmarshalUint32(e []byte) (ie []byte, ret uint32) {
return e[4:], binary.BigEndian.Uint32(e)
}
func unmarshalUint64(e []byte) (ie []byte, ret uint64) {
return e[8:], binary.BigEndian.Uint64(e)
}
func unmarshalInt8(e []byte) (ie []byte, ret int8) {
return e[1:], int8(byte(e[0]))
}
func unmarshalInt16(e []byte) (ie []byte, ret int16) {
return e[2:], int16(binary.BigEndian.Uint16(e))
}
func unmarshalInt32(e []byte) (ie []byte, ret int32) {
return e[4:], int32(binary.BigEndian.Uint32(e))
}
func unmarshalInt64(e []byte) (ie []byte, ret int64) {
return e[8:], int64(binary.BigEndian.Uint64(e))
}
func unmarshalFloat32(e []byte) (ie []byte, ret float32) {
return e[4:], float32(math.Float32frombits(binary.BigEndian.Uint32(e)))
}
func unmarshalFloat64(e []byte) (ie []byte, ret float64) {
return e[8:], float64(math.Float64frombits(binary.BigEndian.Uint64(e)))
}
func unmarshalString(e []byte) (ie []byte, ret string) {
slen := binary.BigEndian.Uint32(e)
ret = string(e[4 : 4+slen])
return e[4+slen:], ret
}
func unmarshalNil(e []byte) (ie []byte, ret uint16) {
return unmarshalUint16(e)
}
func unmarshalPtrIfNil(e []byte, ntype *NType) (ie []byte, ret interface{}, isNil bool, err error) {
if ntype.Indirection == 0 {
return e, nil, false, err
}
ret = ntype.alloc()
var nl uint16
ie, eId := unmarshalTypeId(e)
if eId == ST_NIL {
ie, nl = unmarshalNil(ie)
err = setTypeNil(ret, int(nl))
return ie, ret, true, err
}
if ntype.ValType == ST_ERROR {
return e, ret, false, err
}
if eId != ntype.ValType {
return ie, ret, false, fmt.Errorf("Type mismatch")
}
return ie, ret, false, err
}
func unmarshalError(e []byte, ntype *NType) (ie []byte, ret interface{}, err error) {
ret = ntype.alloc()
var nl uint16
ie, eId := unmarshalTypeId(e)
if eId == ST_NIL {
ie, nl = unmarshalNil(ie)
err = setTypeNil(ret, int(nl))
return ie, ret, err
}
if eId != ST_STRING {
return ie, ret, fmt.Errorf("Type mismatch")
}
ie, v := unmarshalString(ie)
err = setTypeVal(ret, fmt.Errorf(v), ntype)
return ie, ret, err
}
func unmarshalTypeId(e []byte) (ie []byte, ret uint32) {
return unmarshalUint32(e)
}
func unmarshalCommon(e []byte, ntype *NType) (ie []byte, ret interface{}, err error) {
ctype := getTypeById(ntype.ValType)
if ctype == nil {
return e, ret, fmt.Errorf("ssob: Unknown common type '%d': %w", ntype.ValType, ErrTypeUnknown)
}
// pointer could be nil
ie, ptrNil, isNil, err := unmarshalPtrIfNil(e, ntype)
if err != nil {
return ie, ret, fmt.Errorf("ssob: Cannot unmarshal common type '%s': %w", ntype.Name, err)
}
if ptrNil != nil {
if isNil {
return ie, ptrNil, err
}
ret = ptrNil
}
if ret == nil {
ret = ntype.alloc()
}
switch ctype.Id {
case ST_BOOL:
var v bool
ie, v = unmarshalBool(ie)
setTypeVal(ret, v, ntype)
return ie, ret, err
case ST_UINT8:
var v uint8
ie, v = unmarshalUint8(ie)
setTypeVal(ret, v, ntype)
return ie, ret, err
case ST_UINT16:
var v uint16
ie, v = unmarshalUint16(ie)
setTypeVal(ret, v, ntype)
return ie, ret, err
case ST_UINT32:
var v uint32
ie, v = unmarshalUint32(ie)
setTypeVal(ret, v, ntype)
return ie, ret, err
case ST_UINT64:
var v uint64
ie, v = unmarshalUint64(ie)
setTypeVal(ret, v, ntype)
return ie, ret, err
case ST_INT8:
var v int8
ie, v = unmarshalInt8(ie)
setTypeVal(ret, v, ntype)
return ie, ret, err
case ST_INT16:
var v int16
ie, v = unmarshalInt16(ie)
setTypeVal(ret, v, ntype)
return ie, ret, err
case ST_INT32:
var v int32
ie, v = unmarshalInt32(ie)
setTypeVal(ret, v, ntype)
return ie, ret, err
case ST_INT64:
var v int64
ie, v = unmarshalInt64(ie)
setTypeVal(ret, v, ntype)
return ie, ret, err
case ST_FLOAT32:
var v float32
ie, v = unmarshalFloat32(ie)
setTypeVal(ret, v, ntype)
return ie, ret, err
case ST_FLOAT64:
var v float64
ie, v = unmarshalFloat64(ie)
setTypeVal(ret, v, ntype)
return ie, ret, err
case ST_STRING:
var v string
ie, v = unmarshalString(ie)
setTypeVal(ret, v, ntype)
return ie, ret, err
case ST_ERROR:
return unmarshalError(ie, ntype)
default:
return ie, ret, fmt.Errorf("ssob: Unknown common type '%d': %w", ctype.Id, ErrTypeUnknown)
}
}
func unmarshalSlice(e []byte, ntype *NType) (ie []byte, ret interface{}, err error) {
ret = ntype.alloc()
rv := getVal(ret)
ie, l := unmarshalUint32(e)
stype := getTypeById(ntype.ValType)
if stype == nil {
return ie, ret, fmt.Errorf("ssob: Unknown type '%d': %w", ntype.ValType, ErrTypeUnknown)
}
var v interface{}
for i := 0; i < int(l); i++ {
ie, v, err = unmarshalType(ie, stype)
if err != nil {
return ie, ret, err
}
rv.Set(reflect.Append(rv, getVal(v)))
}
return ie, ret, err
}
func unmarshalArray(e []byte, ntype *NType) (ie []byte, ret interface{}, err error) {
ret = ntype.alloc()
rv := getVal(ret)
stype := getTypeById(ntype.ValType)
if stype == nil {
return ie, ret, fmt.Errorf("ssob: Unknown type '%d': %w", ntype.ValType, ErrTypeUnknown)
}
var v interface{}
ie = e
for i := 0; i < ntype.arrayLen; i++ {
ie, v, err = unmarshalType(ie, stype)
if err != nil {
return ie, ret, err
}
rv.Index(i).Set(getVal(v))
}
return ie, ret, err
}
func unmarshalStruct(e []byte, ntype *NType) (ie []byte, ret interface{}, err error) {
ret = ntype.alloc()
rv := getVal(ret)
ie = e
stype := getTypeById(ntype.ValType)
if stype == nil {
return ie, ret, fmt.Errorf("ssob: Unknown type '%d': %w", ntype.ValType, ErrTypeUnknown)
}
var v interface{}
for i, field := range stype.structFields {
for j := i; j < rv.NumField(); j++ {
if rv.Field(j).CanSet() {
ftype := getTypeById(field.Id)
if ftype == nil {
return ie, ret, fmt.Errorf("ssob: Unknown type '%d': %w", field.Id, ErrTypeUnknown)
}
ie, v, err = unmarshalType(ie, ftype)
if err != nil {
return ie, ret, err
}
rv.Field(j).Set(getVal(v))
break
}
}
}
return ie, ret, err
}
func unmarshalInterface(e []byte, ntype *NType) (ie []byte, ret interface{}, err error) {
ie = e
stype := getTypeById(ntype.ValType)
if stype == nil {
return ie, ret, fmt.Errorf("ssob: Unknown type '%d': %w", ntype.ValType, ErrTypeUnknown)
}
return unmarshalCommon(ie, ntype)
}
func unmarshalType(e []byte, ntype *NType) (ie []byte, ret interface{}, err error) {
switch ntype.MainTypeId {
case ST_COMMON:
return unmarshalCommon(e, ntype)
case ST_SLICE:
return unmarshalSlice(e, ntype)
case ST_ARRAY:
return unmarshalArray(e, ntype)
case ST_STRUCT:
return unmarshalStruct(e, ntype)
case ST_INTERFACE:
return unmarshalInterface(e, ntype)
default:
return e, ret, fmt.Errorf("ssob: Unknown type '%d': %w", ntype.MainTypeId, ErrTypeUnknown)
}
}
func unmarshalVal(e []byte) (ie []byte, ret interface{}, err error) {
if len(e) < ST_ID_SIZE {
return ie, ret, fmt.Errorf("ssob: Cannot unmarshal: %w", ErrValueInvalid)
}
// type id
var tid uint32
ie, tid = unmarshalTypeId(e)
vt := getTypeById(tid)
if vt == nil {
return ie, ret, fmt.Errorf("ssob: Unknown type '%d': %w", tid, ErrTypeUnknown)
}
// alloc
ret = vt.alloc()
// check for nil
if len(ie) < 1 {
return ie, ret, fmt.Errorf("ssob: Cannot unmarshal: %w", ErrValueInvalid)
}
ie, isNil := unmarshalBool(ie)
if isNil {
if len(ie) < 2 {
return ie, ret, fmt.Errorf("ssob: Cannot unmarshal: %w", ErrValueInvalid)
}
ie, nl := unmarshalNil(ie)
if int(nl) > vt.Indirection {
return ie, ret, fmt.Errorf("ssob: Cannot unmarshal: %w", ErrValueInvalid)
}
err = setTypeNil(ret, int(nl))
return ie, ret, err
}
return unmarshalType(ie, vt)
}