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
}
stype := binary.BigEndian.Uint32(st)
if t, ok := cacheTypes.types[stype]; !ok {
return nil, fmt.Errorf("ssob: Decode type '%d' not registered: %w", stype, ErrTypeUnknown)
} else {
return t.unmarshal(dec.r)
l := binary.BigEndian.Uint32(st)
b := make([]byte, l)
var rl int
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) {
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) {

View File

@ -6,8 +6,6 @@ import (
"io"
"math"
"reflect"
"gitea.olznet.de/OlzNet/slog"
)
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) {
ret = make([]byte, ST_ID_SIZE+1)
ret[0] = 1
ret = make([]byte, 1)
if e == true {
ret[0] = 0
} else {
ret[0] = 1
}
return ret
}
@ -581,12 +580,12 @@ func marshalPtrIfNil(e interface{}, ntype *NType) (ie interface{}, ret []byte, i
for i := 0; i < ntype.Indirection; i++ {
v = reflect.Indirect(v)
nl++
if v.Kind() == reflect.Invalid || (v.Kind() == reflect.Ptr && v.IsNil()) {
ret = append(ret, marshalTypeId(ST_NIL)...)
ret = append(ret, marshalNil(uint16(nl))...)
return e, ret, true
}
nl++
}
ret = append(ret, marshalTypeId(ntype.ValType)...)
@ -602,14 +601,27 @@ func marshalError(e interface{}, ntype *NType) (ret []byte, err error) {
return ret, err
}
errorString := false
for i := 0; i < ntype.Indirection; i++ {
t := reflect.TypeOf(v.Interface())
if t.String() == "errors.errorString" {
errorString = true
break
}
v = reflect.Indirect(v)
nl++
if v.Kind() == reflect.Invalid || v.IsNil() {
ret = append(ret, marshalTypeId(ST_NIL)...)
ret = append(ret, marshalNil(uint16(nl))...)
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)
@ -795,7 +807,6 @@ func marshalStruct(e interface{}, ntype *NType) (ret []byte, err error) {
if ftype == nil {
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)
if err != nil {
return ret, err
@ -837,16 +848,18 @@ func marshalVal(e interface{}) (ret []byte, err error) {
if err != nil {
return ret, err
}
slog.LOG_DEBUGFLN("i: %v | n: %v | nl: %v | err: %v", i, n, nl, err)
// type id
bytes := marshalTypeId(n.Id)
// nil pointer
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)...)
} else {
bytes = append(bytes, marshalBool(false)...)
if tbytes, err := marshalType(i, n); err != nil {
return ret, err
} else {

View File

@ -368,6 +368,7 @@ func parseType(t reflect.Type) (ret nallocFunc, mainTypeId uint32, indirection i
break
}
}
//return vret
return vret.Interface()
}
@ -386,18 +387,11 @@ func parseType(t reflect.Type) (ret nallocFunc, mainTypeId uint32, indirection i
val = val.Elem()
indirection += 1
base = false
slog.LOG_DEBUGFLN("Indirection: %d", indirection)
} else {
slog.LOG_DEBUGFLN("ELSE: %v", t)
switch val.Kind() {
case reflect.Slice:
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())
slog.LOG_DEBUGFLN("vt: %v", vt)
if err != nil {
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:
typ := reflect.TypeOf(val.Interface())
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())
slog.LOG_DEBUGFLN("vt: %v", vt)
if err != nil {
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
case reflect.Interface:
typ := reflect.TypeOf(nval.Interface())
slog.LOG_DEBUGFLN("val.Type(): %s", typ.Elem())
slog.LOG_DEBUGFLN("INTERFACE")
if !base {
vt, err := getTypeByNameRegister(typ.Elem().String(), typ.Elem())
slog.LOG_DEBUGFLN("vt: %v", vt)
if err != nil {
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
case reflect.Struct:
typ := reflect.TypeOf(val.Interface())
slog.LOG_DEBUGFLN("typ.Kind(): %s", typ.String())
slog.LOG_DEBUGFLN("STRUCT")
if !base {
vt, err := getTypeByNameRegister(typ.String(), typ)
slog.LOG_DEBUGFLN("vt: %v", vt)
if err != nil {
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()
for i := 0; i < sl; i++ {
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.Name = val.Type().Field(i).Name
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)
}
}
base = false
base = true
}
mainTypeId = ST_STRUCT
case reflect.Map:
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 {
vt, err := getTypeByNameRegister(typ.String(), typ)
slog.LOG_DEBUGFLN("vt: %v", vt)
if err != nil {
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 {
// Key
vt, err := getTypeByNameRegister(typ.Key().String(), typ.Key())
slog.LOG_DEBUGFLN("vt: %v", vt)
if err != nil {
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
vt, err = getTypeByNameRegister(typ.Elem().String(), typ.Elem())
slog.LOG_DEBUGFLN("vt: %v", vt)
if err != nil {
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
default:
typ := reflect.TypeOf(val.Interface())
slog.LOG_DEBUGFLN("typ.Kind(): %s", typ.Kind())
slog.LOG_DEBUGFLN("COMMON")
if !base {
vt, err := getTypeByNameRegister(typ.Kind().String(), typ)
slog.LOG_DEBUGFLN("vt: %v", vt)
if err != nil {
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.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)
return ret, base, err
@ -565,12 +537,12 @@ func registerType(t reflect.Type) (err error) {
cacheTypes.nnames[ntype.Name] = ntype
cacheTypes.NextId += 1
slog.LOG_DEBUGFLN("Registered type: %v", ntype)
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
}
@ -613,6 +585,61 @@ func indirectType(e interface{}) (ret interface{}, ntype *NType, nilLevel uint16
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) {
t := reflect.TypeOf(e)
if t == nil || t.Kind() != reflect.Ptr {
@ -623,7 +650,5 @@ func RegisterType(e interface{}) (err error) {
return err
}
b, ee := marshalVal(e)
slog.LOG_DEBUGFLN("Bytes: %v | err: %v", b, ee)
return ee
return nil
}

View File

@ -696,3 +696,342 @@ func baseTypeUnmarshaller(e uint32, r io.Reader) (ret interface{}, err error) {
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)
}