package ssob import ( "encoding/binary" "fmt" "io" "math" "reflect" ) func UnmarshalString(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 UnmarshalBool(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 UnmarshalInt8(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 UnmarshalUint8(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 UnmarshalInt16(in []byte) (ret int16, n int, err error) { if len(in) < 2 { return 0, 0, fmt.Errorf("ssob: Decoding int16: %w", ErrTypeInvalid) } return int16(binary.BigEndian.Uint16(in[0:2])), 2, nil } func UnmarshalUint16(in []byte) (ret uint16, n int, err error) { if len(in) < 2 { return 0, 0, fmt.Errorf("ssob: Decoding uint16: %w", ErrTypeInvalid) } return binary.BigEndian.Uint16(in[0:2]), 2, nil } func UnmarshalInt32(in []byte) (ret int32, n int, err error) { if len(in) < 4 { return 0, 0, fmt.Errorf("ssob: Decoding int32: %w", ErrTypeInvalid) } return int32(binary.BigEndian.Uint32(in[0:4])), 4, nil } func UnmarshalUint32(in []byte) (ret uint32, n int, err error) { if len(in) < 4 { return 0, 0, fmt.Errorf("ssob: Decoding uint32: %w", ErrTypeInvalid) } return binary.BigEndian.Uint32(in[0:4]), 4, nil } func UnmarshalFloat32(in []byte) (ret float32, n int, err error) { if len(in) < 4 { return 0, 0, fmt.Errorf("ssob: Decoding float32: %w", ErrTypeInvalid) } return float32(math.Float32frombits(binary.BigEndian.Uint32(in[0:4]))), 4, nil } func UnmarshalInt64(in []byte) (ret int64, n int, err error) { if len(in) < 8 { return 0, 0, fmt.Errorf("ssob: Decoding int64: %w", ErrTypeInvalid) } return int64(binary.BigEndian.Uint64(in[0:8])), 8, nil } func UnmarshalUint64(in []byte) (ret uint64, n int, err error) { if len(in) < 8 { return 0, 0, fmt.Errorf("ssob: Decoding uint64: %w", ErrTypeInvalid) } return binary.BigEndian.Uint64(in[0:8]), 8, nil } func UnmarshalFloat64(in []byte) (ret float64, n int, err error) { if len(in) < 8 { return 0, 0, fmt.Errorf("ssob: Decoding float64: %w", ErrTypeInvalid) } return float64(math.Float64frombits(binary.BigEndian.Uint64(in[0:8]))), 8, nil } type unmarshalFunc func(e interface{}, in []byte) (n int, err error) var decoderCache map[string]unmarshalFunc func init() { decoderCache = make(map[string]unmarshalFunc) RegisterDecoder("bool", func(e interface{}, in []byte) (n int, err error) { if i, ok := e.(*bool); ok { *i, n, err = UnmarshalBool(in) return n, err } return 0, fmt.Errorf("ssob: Incompatible type - expected bool: %w", ErrTypeMismatch) }) RegisterDecoder("int8", func(e interface{}, in []byte) (n int, err error) { if i, ok := e.(*int8); ok { *i, n, err = UnmarshalInt8(in) return n, err } return 0, fmt.Errorf("ssob: Incompatible type - expected int8: %w", ErrTypeMismatch) }) RegisterDecoder("uint8", func(e interface{}, in []byte) (n int, err error) { if i, ok := e.(*uint8); ok { *i, n, err = UnmarshalUint8(in) return n, err } return 0, fmt.Errorf("ssob: Incompatible type - expected uint8: %w", ErrTypeMismatch) }) RegisterDecoder("int16", func(e interface{}, in []byte) (n int, err error) { if i, ok := e.(*int16); ok { *i, n, err = UnmarshalInt16(in) return n, err } return 0, fmt.Errorf("ssob: Incompatible type - expected int16: %w", ErrTypeMismatch) }) RegisterDecoder("uint16", func(e interface{}, in []byte) (n int, err error) { if i, ok := e.(*uint16); ok { *i, n, err = UnmarshalUint16(in) return n, err } return 0, fmt.Errorf("ssob: Incompatible type - expected uint16: %w", ErrTypeMismatch) }) RegisterDecoder("int32", func(e interface{}, in []byte) (n int, err error) { if i, ok := e.(*int32); ok { *i, n, err = UnmarshalInt32(in) return n, err } return 0, fmt.Errorf("ssob: Incompatible type - expected int32: %w", ErrTypeMismatch) }) RegisterDecoder("uint32", func(e interface{}, in []byte) (n int, err error) { if i, ok := e.(*uint32); ok { *i, n, err = UnmarshalUint32(in) return n, err } return 0, fmt.Errorf("ssob: Incompatible type - expected uint32: %w", ErrTypeMismatch) }) RegisterDecoder("float32", func(e interface{}, in []byte) (n int, err error) { if i, ok := e.(*float32); ok { *i, n, err = UnmarshalFloat32(in) return n, err } return 0, fmt.Errorf("ssob: Incompatible type - expected float32: %w", ErrTypeMismatch) }) RegisterDecoder("int64", func(e interface{}, in []byte) (n int, err error) { if i, ok := e.(*int64); ok { *i, n, err = UnmarshalInt64(in) return n, err } return 0, fmt.Errorf("ssob: Incompatible type - expected int64: %w", ErrTypeMismatch) }) RegisterDecoder("uint64", func(e interface{}, in []byte) (n int, err error) { if i, ok := e.(*uint64); ok { *i, n, err = UnmarshalUint64(in) return n, err } return 0, fmt.Errorf("ssob: Incompatible type - expected uint64: %w", ErrTypeMismatch) }) RegisterDecoder("float64", func(e interface{}, in []byte) (n int, err error) { if i, ok := e.(*float64); ok { *i, n, err = UnmarshalFloat64(in) return n, err } return 0, fmt.Errorf("ssob: Incompatible type - expected float64: %w", ErrTypeMismatch) }) RegisterDecoder("string", func(e interface{}, in []byte) (n int, err error) { if i, ok := e.(*string); ok { *i, n, err = UnmarshalString(in) return n, err } return 0, fmt.Errorf("ssob: Incompatible type - expected string: %w", ErrTypeMismatch) }) } func decRegister(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 := UnmarshalInt32(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 := unmarshal(e.Interface(), in[pos:]) pos += r if err != nil { return pos, err } ti.Index(i).Set(reflect.Indirect(e)) } return pos, nil } decoderCache[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 := UnmarshalInt32(in) pos += r if err != nil { return pos, err } ti := v.Elem() ti.Set(reflect.MakeSlice(reflect.TypeOf(ti.Interface()), 0, ti.Cap())) for i := 0; i < int(l); i++ { e := reflect.New(reflect.TypeOf(ti.Interface()).Elem()) r, err := unmarshal(e.Interface(), in[pos:]) pos += r if err != nil { return pos, err } ti.Set(reflect.Append(ti, reflect.Indirect(e))) } return pos, nil } decoderCache[string(t.Kind())] = f case reflect.Struct: 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 := unmarshal(vi.Field(i).Addr().Interface(), in[pos:]) pos += ni if err != nil { return pos, err } } return pos, nil } decoderCache[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 := UnmarshalInt32(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 := unmarshal(ek.Interface(), in[pos:]) pos += r if err != nil { return pos, err } r, err = unmarshal(ev.Interface(), in[pos:]) pos += r if err != nil { return pos, err } vi.SetMapIndex(reflect.Indirect(ek), reflect.Indirect(ev)) } return pos, nil } decoderCache[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 := unmarshalBaseType(&i, in[pos:]) pos += r if err != nil { return pos, err } v.Elem().SetBool(bool(i)) return pos, nil } decoderCache[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 := unmarshalBaseType(&i, in[pos:]) pos += r if err != nil { return pos, err } v.Elem().SetUint(uint64(i)) return pos, nil } decoderCache[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 := unmarshalBaseType(&i, in[pos:]) pos += r if err != nil { return pos, err } v.Elem().SetUint(uint64(i)) return pos, nil } decoderCache[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 := unmarshalBaseType(&i, in[pos:]) pos += r if err != nil { return pos, err } v.Elem().SetUint(uint64(i)) return pos, nil } decoderCache[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 := unmarshalBaseType(&i, in[pos:]) pos += r if err != nil { return pos, err } v.Elem().SetUint(uint64(i)) return pos, nil } decoderCache[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 := unmarshalBaseType(&i, in[pos:]) pos += r if err != nil { return pos, err } v.Elem().SetInt(int64(i)) return pos, nil } decoderCache[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 := unmarshalBaseType(&i, in[pos:]) pos += r if err != nil { return pos, err } v.Elem().SetInt(int64(i)) return pos, nil } decoderCache[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 := unmarshalBaseType(&i, in[pos:]) pos += r if err != nil { return pos, err } v.Elem().SetInt(int64(i)) return pos, nil } decoderCache[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 := unmarshalBaseType(&i, in[pos:]) pos += r if err != nil { return pos, err } v.Elem().SetInt(int64(i)) return pos, nil } decoderCache[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 := unmarshalBaseType(&i, in[pos:]) pos += r if err != nil { return pos, err } v.Elem().SetString(i) return pos, nil } decoderCache[t.Name()] = f default: return fmt.Errorf("ssob: %s: %w", string(t.Name()), ErrTypeUnknown) } return nil } func unmarshalBaseType(e interface{}, in []byte) (n int, err error) { switch t := e.(type) { case *bool: return decoderCache["bool"](t, in) case *int8: return decoderCache["int8"](t, in) case *uint8: return decoderCache["uint8"](t, in) case *int16: return decoderCache["int16"](t, in) case *uint16: return decoderCache["uint16"](t, in) case *int32: return decoderCache["int32"](t, in) case *uint32: return decoderCache["uint32"](t, in) case *int64: return decoderCache["int64"](t, in) case *uint64: return decoderCache["uint64"](t, in) case *float32: return decoderCache["float32"](t, in) case *float64: return decoderCache["float64"](t, in) case *string: return decoderCache["string"](t, in) default: return 0, fmt.Errorf("ssob: No base type: %w", ErrTypeUnknown) } } func unmarshal(e interface{}, in []byte) (n int, err error) { n, err = unmarshalBaseType(e, in) if err == nil { return n, err } var key string t := reflect.TypeOf(e) v := reflect.ValueOf(e) if !v.IsValid() || 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 && p.Kind() != reflect.Interface { 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 := decoderCache[key]; ok { return f(v.Interface(), in) } else { err = decRegister(p.Interface()) if err != nil { return 0, err } return unmarshal(e, in) } } if !p.Elem().IsValid() { err = allocType(v) if err != nil { return 0, err } p = reflect.Indirect(v) } return unmarshal(p.Interface(), in) } func RegisterDecoder(name string, f func(e interface{}, in []byte) (n int, err error)) { decoderCache[name] = f } func baseTypeUnmarshaller(e uint32, r io.Reader) (ret interface{}, err error) { switch e { case ST_BOOL: sb := make([]byte, 1) if err = binary.Read(r, binary.BigEndian, sb); err != nil { return nil, fmt.Errorf("ssob: Decode bool failed: %w: %s", ErrValueInvalid, err.Error()) } ret = cacheTypes.types[ST_BOOL].alloc() if sb[0] == byte(0) { *(ret.(*bool)) = true } else { *(ret.(*bool)) = false } case ST_UINT8: sb := make([]byte, 1) if err = binary.Read(r, binary.BigEndian, sb); err != nil { return nil, fmt.Errorf("ssob: Decode uint8 failed: %w: %s", ErrValueInvalid, err.Error()) } ret = cacheTypes.types[ST_UINT8].alloc() *(ret.(*uint8)) = uint8(sb[0]) case ST_UINT16: sb := make([]byte, 2) if err = binary.Read(r, binary.BigEndian, sb); err != nil { return nil, fmt.Errorf("ssob: Decode uint16 failed: %w: %s", ErrValueInvalid, err.Error()) } ret = cacheTypes.types[ST_UINT16].alloc() *(ret.(*uint16)) = binary.BigEndian.Uint16(sb[0:2]) case ST_UINT32: sb := make([]byte, 4) if err = binary.Read(r, binary.BigEndian, sb); err != nil { return nil, fmt.Errorf("ssob: Decode uint32 failed: %w: %s", ErrValueInvalid, err.Error()) } ret = cacheTypes.types[ST_UINT32].alloc() *(ret.(*uint32)) = binary.BigEndian.Uint32(sb[0:4]) case ST_UINT64: sb := make([]byte, 8) if err = binary.Read(r, binary.BigEndian, sb); err != nil { return nil, fmt.Errorf("ssob: Decode uint64 failed: %w: %s", ErrValueInvalid, err.Error()) } ret = cacheTypes.types[ST_UINT64].alloc() *(ret.(*uint64)) = binary.BigEndian.Uint64(sb[0:8]) case ST_INT8: sb := make([]byte, 1) if err = binary.Read(r, binary.BigEndian, sb); err != nil { return nil, fmt.Errorf("ssob: Decode int8 failed: %w: %s", ErrValueInvalid, err.Error()) } ret = cacheTypes.types[ST_INT8].alloc() *(ret.(*int8)) = int8(sb[0]) case ST_INT16: sb := make([]byte, 2) if err = binary.Read(r, binary.BigEndian, sb); err != nil { return nil, fmt.Errorf("ssob: Decode int16 failed: %w: %s", ErrValueInvalid, err.Error()) } ret = cacheTypes.types[ST_INT16].alloc() *(ret.(*int16)) = int16(binary.BigEndian.Uint16(sb[0:2])) case ST_INT32: sb := make([]byte, 4) if err = binary.Read(r, binary.BigEndian, sb); err != nil { return nil, fmt.Errorf("ssob: Decode int32 failed: %w: %s", ErrValueInvalid, err.Error()) } ret = cacheTypes.types[ST_INT32].alloc() *(ret.(*int32)) = int32(binary.BigEndian.Uint32(sb[0:4])) case ST_INT64: sb := make([]byte, 8) if err = binary.Read(r, binary.BigEndian, sb); err != nil { return nil, fmt.Errorf("ssob: Decode int64 failed: %w: %s", ErrValueInvalid, err.Error()) } ret = cacheTypes.types[ST_INT64].alloc() *(ret.(*int64)) = int64(binary.BigEndian.Uint64(sb[0:8])) case ST_FLOAT32: sb := make([]byte, 4) if err = binary.Read(r, binary.BigEndian, sb); err != nil { return nil, fmt.Errorf("ssob: Decode float32 failed: %w: %s", ErrValueInvalid, err.Error()) } ret = cacheTypes.types[ST_FLOAT32].alloc() *(ret.(*float32)) = float32(math.Float32frombits(binary.BigEndian.Uint32(sb[0:4]))) case ST_FLOAT64: sb := make([]byte, 8) if err = binary.Read(r, binary.BigEndian, sb); err != nil { return nil, fmt.Errorf("ssob: Decode float64 failed: %w: %s", ErrValueInvalid, err.Error()) } ret = cacheTypes.types[ST_FLOAT64].alloc() *(ret.(*float64)) = float64(math.Float64frombits(binary.BigEndian.Uint64(sb[0:8]))) case ST_STRING: sb := make([]byte, 4) if err = binary.Read(r, binary.BigEndian, sb); err != nil { return nil, fmt.Errorf("ssob: Decode string failed: %w: %s", ErrValueInvalid, err.Error()) } slen := binary.BigEndian.Uint32(sb[0:4]) ret = cacheTypes.types[ST_STRING].alloc() sb = make([]byte, slen) if err = binary.Read(r, binary.BigEndian, sb); err != nil { return nil, fmt.Errorf("ssob: Decode string failed: %w: %s", ErrValueInvalid, err.Error()) } *(ret.(*string)) = string(sb) default: return nil, fmt.Errorf("ssob: Unknown type: %d: %w", e, ErrTypeInvalid) } 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) }