Unmarshalling implemented
This commit is contained in:
parent
8023e70530
commit
a8d0eabd84
17
decoder.go
17
decoder.go
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
18
encoder.go
18
encoder.go
|
@ -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) {
|
||||||
|
|
31
marshal.go
31
marshal.go
|
@ -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 {
|
||||||
|
|
93
types.go
93
types.go
|
@ -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
|
|
||||||
}
|
}
|
||||||
|
|
339
unmarshal.go
339
unmarshal.go
|
@ -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)
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue