2019-10-04 12:28:45 +02:00
|
|
|
package ssob
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/binary"
|
2021-08-21 22:29:18 +02:00
|
|
|
"fmt"
|
2021-09-02 00:08:59 +02:00
|
|
|
"io"
|
2020-05-24 19:05:04 +02:00
|
|
|
"math"
|
2019-10-04 12:28:45 +02:00
|
|
|
"reflect"
|
|
|
|
)
|
|
|
|
|
2019-10-04 17:58:17 +02:00
|
|
|
func UnmarshalString(in []byte) (ret string, n int, err error) {
|
2019-10-05 01:42:09 +02:00
|
|
|
if len(in) < 4 {
|
2021-08-21 22:29:18 +02:00
|
|
|
return "", 0, fmt.Errorf("ssob: Decoding string: %w", ErrTypeInvalid)
|
2019-10-04 12:28:45 +02:00
|
|
|
}
|
2019-10-05 01:42:09 +02:00
|
|
|
l := int32(binary.BigEndian.Uint32(in))
|
2019-10-04 12:28:45 +02:00
|
|
|
|
2019-10-05 01:42:09 +02:00
|
|
|
if len(in[4:]) < int(l) {
|
2021-08-21 22:29:18 +02:00
|
|
|
return "", 0, fmt.Errorf("ssob: Invalid length of string: %w", ErrValueInvalid)
|
2019-10-04 12:28:45 +02:00
|
|
|
}
|
2019-10-05 01:42:09 +02:00
|
|
|
return string(in[4 : l+4]), int(l) + 4, nil
|
2019-10-04 12:28:45 +02:00
|
|
|
}
|
|
|
|
|
2019-10-05 22:12:53 +02:00
|
|
|
func UnmarshalBool(in []byte) (ret bool, n int, err error) {
|
|
|
|
if len(in) < 1 {
|
2021-08-21 22:29:18 +02:00
|
|
|
return false, 0, fmt.Errorf("ssob: Decoding bool: %w", ErrTypeInvalid)
|
2019-10-05 22:12:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if in[0] == byte(0) {
|
|
|
|
return true, 1, nil
|
|
|
|
}
|
|
|
|
return false, 1, nil
|
|
|
|
}
|
|
|
|
|
2019-10-04 17:58:17 +02:00
|
|
|
func UnmarshalInt8(in []byte) (ret int8, n int, err error) {
|
2019-10-04 12:28:45 +02:00
|
|
|
if len(in) < 1 {
|
2021-08-21 22:29:18 +02:00
|
|
|
return 0, 0, fmt.Errorf("ssob: Decoding int8: %w", ErrTypeInvalid)
|
2019-10-04 12:28:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return int8(in[0]), 1, nil
|
|
|
|
}
|
|
|
|
|
2019-10-04 17:58:17 +02:00
|
|
|
func UnmarshalUint8(in []byte) (ret uint8, n int, err error) {
|
2019-10-04 12:28:45 +02:00
|
|
|
if len(in) < 1 {
|
2021-08-21 22:29:18 +02:00
|
|
|
return 0, 0, fmt.Errorf("ssob: Decoding uint8: %w", ErrTypeInvalid)
|
2019-10-04 12:28:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return uint8(in[0]), 1, nil
|
|
|
|
}
|
|
|
|
|
2019-10-04 17:58:17 +02:00
|
|
|
func UnmarshalInt16(in []byte) (ret int16, n int, err error) {
|
2019-10-04 12:28:45 +02:00
|
|
|
if len(in) < 2 {
|
2021-08-21 22:29:18 +02:00
|
|
|
return 0, 0, fmt.Errorf("ssob: Decoding int16: %w", ErrTypeInvalid)
|
2019-10-04 12:28:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return int16(binary.BigEndian.Uint16(in[0:2])), 2, nil
|
|
|
|
}
|
|
|
|
|
2019-10-04 17:58:17 +02:00
|
|
|
func UnmarshalUint16(in []byte) (ret uint16, n int, err error) {
|
2019-10-04 12:28:45 +02:00
|
|
|
if len(in) < 2 {
|
2021-08-21 22:29:18 +02:00
|
|
|
return 0, 0, fmt.Errorf("ssob: Decoding uint16: %w", ErrTypeInvalid)
|
2019-10-04 12:28:45 +02:00
|
|
|
}
|
|
|
|
|
2019-10-22 11:15:20 +02:00
|
|
|
return binary.BigEndian.Uint16(in[0:2]), 2, nil
|
2019-10-04 12:28:45 +02:00
|
|
|
}
|
|
|
|
|
2019-10-04 17:58:17 +02:00
|
|
|
func UnmarshalInt32(in []byte) (ret int32, n int, err error) {
|
2019-10-04 12:28:45 +02:00
|
|
|
if len(in) < 4 {
|
2021-08-21 22:29:18 +02:00
|
|
|
return 0, 0, fmt.Errorf("ssob: Decoding int32: %w", ErrTypeInvalid)
|
2019-10-04 12:28:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return int32(binary.BigEndian.Uint32(in[0:4])), 4, nil
|
|
|
|
}
|
|
|
|
|
2019-10-04 17:58:17 +02:00
|
|
|
func UnmarshalUint32(in []byte) (ret uint32, n int, err error) {
|
2019-10-04 12:28:45 +02:00
|
|
|
if len(in) < 4 {
|
2021-08-21 22:29:18 +02:00
|
|
|
return 0, 0, fmt.Errorf("ssob: Decoding uint32: %w", ErrTypeInvalid)
|
2019-10-04 12:28:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return binary.BigEndian.Uint32(in[0:4]), 4, nil
|
|
|
|
}
|
|
|
|
|
2019-10-04 17:58:17 +02:00
|
|
|
func UnmarshalFloat32(in []byte) (ret float32, n int, err error) {
|
2019-10-04 12:28:45 +02:00
|
|
|
if len(in) < 4 {
|
2021-08-21 22:29:18 +02:00
|
|
|
return 0, 0, fmt.Errorf("ssob: Decoding float32: %w", ErrTypeInvalid)
|
2019-10-04 12:28:45 +02:00
|
|
|
}
|
|
|
|
|
2020-05-24 19:05:04 +02:00
|
|
|
return float32(math.Float32frombits(binary.BigEndian.Uint32(in[0:4]))), 4, nil
|
2019-10-04 12:28:45 +02:00
|
|
|
}
|
|
|
|
|
2019-10-04 17:58:17 +02:00
|
|
|
func UnmarshalInt64(in []byte) (ret int64, n int, err error) {
|
2019-10-04 12:28:45 +02:00
|
|
|
if len(in) < 8 {
|
2021-08-21 22:29:18 +02:00
|
|
|
return 0, 0, fmt.Errorf("ssob: Decoding int64: %w", ErrTypeInvalid)
|
2019-10-04 12:28:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return int64(binary.BigEndian.Uint64(in[0:8])), 8, nil
|
|
|
|
}
|
|
|
|
|
2019-10-04 17:58:17 +02:00
|
|
|
func UnmarshalUint64(in []byte) (ret uint64, n int, err error) {
|
2019-10-04 12:28:45 +02:00
|
|
|
if len(in) < 8 {
|
2021-08-21 22:29:18 +02:00
|
|
|
return 0, 0, fmt.Errorf("ssob: Decoding uint64: %w", ErrTypeInvalid)
|
2019-10-04 12:28:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return binary.BigEndian.Uint64(in[0:8]), 8, nil
|
|
|
|
}
|
|
|
|
|
2019-10-04 17:58:17 +02:00
|
|
|
func UnmarshalFloat64(in []byte) (ret float64, n int, err error) {
|
2019-10-04 12:28:45 +02:00
|
|
|
if len(in) < 8 {
|
2021-08-21 22:29:18 +02:00
|
|
|
return 0, 0, fmt.Errorf("ssob: Decoding float64: %w", ErrTypeInvalid)
|
2019-10-04 12:28:45 +02:00
|
|
|
}
|
|
|
|
|
2020-05-24 19:05:04 +02:00
|
|
|
return float64(math.Float64frombits(binary.BigEndian.Uint64(in[0:8]))), 8, nil
|
2019-10-04 12:28:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
type unmarshalFunc func(e interface{}, in []byte) (n int, err error)
|
|
|
|
|
|
|
|
var decoderCache map[string]unmarshalFunc
|
|
|
|
|
|
|
|
func init() {
|
|
|
|
decoderCache = make(map[string]unmarshalFunc)
|
2019-10-05 22:12:53 +02:00
|
|
|
RegisterDecoder("bool", func(e interface{}, in []byte) (n int, err error) {
|
|
|
|
if i, ok := e.(*bool); ok {
|
|
|
|
*i, n, err = UnmarshalBool(in)
|
2020-02-14 13:57:44 +01:00
|
|
|
return n, err
|
2019-10-05 22:12:53 +02:00
|
|
|
}
|
2021-08-21 22:29:18 +02:00
|
|
|
return 0, fmt.Errorf("ssob: Incompatible type - expected bool: %w", ErrTypeMismatch)
|
2019-10-05 22:12:53 +02:00
|
|
|
})
|
2019-10-05 01:42:09 +02:00
|
|
|
RegisterDecoder("int8", func(e interface{}, in []byte) (n int, err error) {
|
|
|
|
if i, ok := e.(*int8); ok {
|
|
|
|
*i, n, err = UnmarshalInt8(in)
|
2020-02-14 13:57:44 +01:00
|
|
|
return n, err
|
2019-10-05 01:42:09 +02:00
|
|
|
}
|
2021-08-21 22:29:18 +02:00
|
|
|
return 0, fmt.Errorf("ssob: Incompatible type - expected int8: %w", ErrTypeMismatch)
|
2019-10-05 01:42:09 +02:00
|
|
|
})
|
|
|
|
RegisterDecoder("uint8", func(e interface{}, in []byte) (n int, err error) {
|
|
|
|
if i, ok := e.(*uint8); ok {
|
|
|
|
*i, n, err = UnmarshalUint8(in)
|
2020-02-14 13:57:44 +01:00
|
|
|
return n, err
|
2019-10-05 01:42:09 +02:00
|
|
|
}
|
2021-08-21 22:29:18 +02:00
|
|
|
return 0, fmt.Errorf("ssob: Incompatible type - expected uint8: %w", ErrTypeMismatch)
|
2019-10-05 01:42:09 +02:00
|
|
|
})
|
|
|
|
RegisterDecoder("int16", func(e interface{}, in []byte) (n int, err error) {
|
|
|
|
if i, ok := e.(*int16); ok {
|
|
|
|
*i, n, err = UnmarshalInt16(in)
|
2020-02-14 13:57:44 +01:00
|
|
|
return n, err
|
2019-10-05 01:42:09 +02:00
|
|
|
}
|
2021-08-21 22:29:18 +02:00
|
|
|
return 0, fmt.Errorf("ssob: Incompatible type - expected int16: %w", ErrTypeMismatch)
|
2019-10-05 01:42:09 +02:00
|
|
|
})
|
|
|
|
RegisterDecoder("uint16", func(e interface{}, in []byte) (n int, err error) {
|
|
|
|
if i, ok := e.(*uint16); ok {
|
|
|
|
*i, n, err = UnmarshalUint16(in)
|
2020-02-14 13:57:44 +01:00
|
|
|
return n, err
|
2019-10-05 01:42:09 +02:00
|
|
|
}
|
2021-08-21 22:29:18 +02:00
|
|
|
return 0, fmt.Errorf("ssob: Incompatible type - expected uint16: %w", ErrTypeMismatch)
|
2019-10-05 01:42:09 +02:00
|
|
|
})
|
|
|
|
RegisterDecoder("int32", func(e interface{}, in []byte) (n int, err error) {
|
|
|
|
if i, ok := e.(*int32); ok {
|
|
|
|
*i, n, err = UnmarshalInt32(in)
|
2020-02-14 13:57:44 +01:00
|
|
|
return n, err
|
2019-10-05 01:42:09 +02:00
|
|
|
}
|
2021-08-21 22:29:18 +02:00
|
|
|
return 0, fmt.Errorf("ssob: Incompatible type - expected int32: %w", ErrTypeMismatch)
|
2019-10-05 01:42:09 +02:00
|
|
|
})
|
|
|
|
RegisterDecoder("uint32", func(e interface{}, in []byte) (n int, err error) {
|
|
|
|
if i, ok := e.(*uint32); ok {
|
|
|
|
*i, n, err = UnmarshalUint32(in)
|
2020-02-14 13:57:44 +01:00
|
|
|
return n, err
|
2019-10-05 01:42:09 +02:00
|
|
|
}
|
2021-08-21 22:29:18 +02:00
|
|
|
return 0, fmt.Errorf("ssob: Incompatible type - expected uint32: %w", ErrTypeMismatch)
|
2019-10-05 01:42:09 +02:00
|
|
|
})
|
|
|
|
RegisterDecoder("float32", func(e interface{}, in []byte) (n int, err error) {
|
|
|
|
if i, ok := e.(*float32); ok {
|
|
|
|
*i, n, err = UnmarshalFloat32(in)
|
2020-02-14 13:57:44 +01:00
|
|
|
return n, err
|
2019-10-05 01:42:09 +02:00
|
|
|
}
|
2021-08-21 22:29:18 +02:00
|
|
|
return 0, fmt.Errorf("ssob: Incompatible type - expected float32: %w", ErrTypeMismatch)
|
2019-10-05 01:42:09 +02:00
|
|
|
})
|
|
|
|
RegisterDecoder("int64", func(e interface{}, in []byte) (n int, err error) {
|
|
|
|
if i, ok := e.(*int64); ok {
|
|
|
|
*i, n, err = UnmarshalInt64(in)
|
2020-02-14 13:57:44 +01:00
|
|
|
return n, err
|
2019-10-05 01:42:09 +02:00
|
|
|
}
|
2021-08-21 22:29:18 +02:00
|
|
|
return 0, fmt.Errorf("ssob: Incompatible type - expected int64: %w", ErrTypeMismatch)
|
2019-10-05 01:42:09 +02:00
|
|
|
})
|
|
|
|
RegisterDecoder("uint64", func(e interface{}, in []byte) (n int, err error) {
|
|
|
|
if i, ok := e.(*uint64); ok {
|
|
|
|
*i, n, err = UnmarshalUint64(in)
|
2020-02-14 13:57:44 +01:00
|
|
|
return n, err
|
2019-10-05 01:42:09 +02:00
|
|
|
}
|
2021-08-21 22:29:18 +02:00
|
|
|
return 0, fmt.Errorf("ssob: Incompatible type - expected uint64: %w", ErrTypeMismatch)
|
2019-10-05 01:42:09 +02:00
|
|
|
})
|
|
|
|
RegisterDecoder("float64", func(e interface{}, in []byte) (n int, err error) {
|
|
|
|
if i, ok := e.(*float64); ok {
|
|
|
|
*i, n, err = UnmarshalFloat64(in)
|
2020-02-14 13:57:44 +01:00
|
|
|
return n, err
|
2019-10-05 01:42:09 +02:00
|
|
|
}
|
2021-08-21 22:29:18 +02:00
|
|
|
return 0, fmt.Errorf("ssob: Incompatible type - expected float64: %w", ErrTypeMismatch)
|
2019-10-05 01:42:09 +02:00
|
|
|
})
|
|
|
|
RegisterDecoder("string", func(e interface{}, in []byte) (n int, err error) {
|
|
|
|
if i, ok := e.(*string); ok {
|
|
|
|
*i, n, err = UnmarshalString(in)
|
2020-02-14 13:57:44 +01:00
|
|
|
return n, err
|
2019-10-05 01:42:09 +02:00
|
|
|
}
|
2021-08-21 22:29:18 +02:00
|
|
|
return 0, fmt.Errorf("ssob: Incompatible type - expected string: %w", ErrTypeMismatch)
|
2019-10-05 01:42:09 +02:00
|
|
|
})
|
2019-10-04 12:28:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func decRegister(e interface{}) (err error) {
|
|
|
|
t := reflect.TypeOf(e)
|
2020-02-23 03:23:17 +01:00
|
|
|
if t == nil {
|
2021-08-21 22:29:18 +02:00
|
|
|
return fmt.Errorf("ssob: nil type: %w", ErrTypeInvalid)
|
2020-02-23 03:23:17 +01:00
|
|
|
}
|
|
|
|
|
2019-10-04 12:28:45 +02:00
|
|
|
switch t.Kind() {
|
|
|
|
case reflect.Invalid:
|
2021-08-21 22:29:18 +02:00
|
|
|
return fmt.Errorf("ssob: invalid type: %w", ErrTypeInvalid)
|
2019-10-05 22:12:53 +02:00
|
|
|
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() {
|
2021-08-21 22:29:18 +02:00
|
|
|
return 0, fmt.Errorf("ssob: Cannot unmarshal to nil pointer: %w", ErrValueInvalid)
|
2019-10-05 22:12:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
l, r, err := UnmarshalInt32(in)
|
|
|
|
pos += r
|
|
|
|
if err != nil {
|
|
|
|
return pos, err
|
|
|
|
}
|
|
|
|
|
|
|
|
ti := v.Elem()
|
|
|
|
if int(l) != ti.Len() {
|
2021-08-21 22:29:18 +02:00
|
|
|
return pos, fmt.Errorf("ssob: Invalid array length. Expected %s got %s: %w", string(l), string(ti.Len()), ErrValueInvalid)
|
2019-10-05 22:12:53 +02:00
|
|
|
}
|
|
|
|
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
|
2019-10-04 12:28:45 +02:00
|
|
|
case reflect.Slice:
|
2019-10-05 01:42:09 +02:00
|
|
|
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() {
|
2021-08-21 22:29:18 +02:00
|
|
|
return 0, fmt.Errorf("ssob: Cannot unmarshal to nil pointer: %w", ErrValueInvalid)
|
2019-10-05 01:42:09 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
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
|
2019-10-04 12:28:45 +02:00
|
|
|
case reflect.Struct:
|
2019-11-03 21:30:50 +01:00
|
|
|
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 {
|
2021-08-21 22:29:18 +02:00
|
|
|
return fmt.Errorf("ssob: No exported fields for %s: %w", string(t.Name()), ErrParseFailed)
|
2019-11-03 21:30:50 +01:00
|
|
|
}
|
|
|
|
|
2019-10-04 12:28:45 +02:00
|
|
|
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() {
|
2021-08-21 22:29:18 +02:00
|
|
|
return 0, fmt.Errorf("ssob: Cannot unmarshal to nil pointer: %w", ErrValueInvalid)
|
2019-10-04 12:28:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
vi := reflect.Indirect(v)
|
2019-11-03 21:30:50 +01:00
|
|
|
for _, i := range mfields {
|
2019-10-04 12:28:45 +02:00
|
|
|
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
|
2019-10-05 01:42:09 +02:00
|
|
|
case reflect.Map:
|
2019-10-05 13:40:18 +02:00
|
|
|
f := func(e interface{}, in []byte) (n int, err error) {
|
|
|
|
t := reflect.TypeOf(e)
|
|
|
|
v := reflect.ValueOf(e)
|
|
|
|
pos := 0
|
2019-10-05 01:42:09 +02:00
|
|
|
|
2019-10-05 13:40:18 +02:00
|
|
|
if t.Kind() != reflect.Ptr || v.IsNil() {
|
2021-08-21 22:29:18 +02:00
|
|
|
return 0, fmt.Errorf("ssob: Cannot unmarshal to nil pointer: %w", ErrValueInvalid)
|
2019-10-05 13:40:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
l, r, err := UnmarshalInt32(in)
|
|
|
|
pos += r
|
|
|
|
if err != nil {
|
|
|
|
return pos, err
|
|
|
|
}
|
2019-10-05 01:42:09 +02:00
|
|
|
|
2019-10-05 13:40:18 +02:00
|
|
|
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))
|
|
|
|
}
|
2019-10-05 01:42:09 +02:00
|
|
|
|
2019-10-05 13:40:18 +02:00
|
|
|
return pos, nil
|
|
|
|
}
|
|
|
|
decoderCache[string(t.Kind())] = f
|
2019-10-22 13:44:08 +02:00
|
|
|
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
|
2019-10-04 12:28:45 +02:00
|
|
|
default:
|
2021-08-21 22:29:18 +02:00
|
|
|
return fmt.Errorf("ssob: %s: %w", string(t.Name()), ErrTypeUnknown)
|
2019-10-04 12:28:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2019-10-05 01:42:09 +02:00
|
|
|
func unmarshalBaseType(e interface{}, in []byte) (n int, err error) {
|
|
|
|
switch t := e.(type) {
|
2019-10-05 22:12:53 +02:00
|
|
|
case *bool:
|
|
|
|
return decoderCache["bool"](t, in)
|
2019-10-05 01:42:09 +02:00
|
|
|
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:
|
2021-08-21 22:29:18 +02:00
|
|
|
return 0, fmt.Errorf("ssob: No base type: %w", ErrTypeUnknown)
|
2019-10-05 01:42:09 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-04 12:28:45 +02:00
|
|
|
func unmarshal(e interface{}, in []byte) (n int, err error) {
|
2019-10-05 01:42:09 +02:00
|
|
|
n, err = unmarshalBaseType(e, in)
|
|
|
|
if err == nil {
|
|
|
|
return n, err
|
|
|
|
}
|
|
|
|
|
2019-10-04 12:28:45 +02:00
|
|
|
var key string
|
|
|
|
t := reflect.TypeOf(e)
|
|
|
|
v := reflect.ValueOf(e)
|
2020-03-25 10:08:25 +01:00
|
|
|
if !v.IsValid() || t.Kind() != reflect.Ptr || v.IsNil() {
|
2021-08-21 22:29:18 +02:00
|
|
|
return 0, fmt.Errorf("ssob: Need a pointer that is fully allocated for unmarshalling: %w", ErrValueInvalid)
|
2019-10-04 12:28:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
p := reflect.Indirect(v)
|
2020-03-25 10:08:25 +01:00
|
|
|
if p.Kind() != reflect.Ptr && p.Kind() != reflect.Interface {
|
2019-10-22 13:44:08 +02:00
|
|
|
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:
|
2019-10-04 12:28:45 +02:00
|
|
|
key = reflect.TypeOf(p.Interface()).Name()
|
2019-10-22 13:44:08 +02:00
|
|
|
default:
|
2019-10-04 12:28:45 +02:00
|
|
|
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
|
|
|
|
}
|
2019-10-22 14:36:28 +02:00
|
|
|
return unmarshal(e, in)
|
2019-10-04 12:28:45 +02:00
|
|
|
}
|
|
|
|
}
|
2019-12-17 00:42:05 +01:00
|
|
|
if !p.Elem().IsValid() {
|
|
|
|
err = allocType(v)
|
|
|
|
if err != nil {
|
|
|
|
return 0, err
|
|
|
|
}
|
|
|
|
p = reflect.Indirect(v)
|
|
|
|
}
|
2019-10-04 12:28:45 +02:00
|
|
|
|
2019-12-17 00:42:05 +01:00
|
|
|
return unmarshal(p.Interface(), in)
|
2019-10-04 12:28:45 +02:00
|
|
|
}
|
2019-10-04 17:58:17 +02:00
|
|
|
|
|
|
|
func RegisterDecoder(name string, f func(e interface{}, in []byte) (n int, err error)) {
|
|
|
|
decoderCache[name] = f
|
|
|
|
}
|
2021-09-02 00:08:59 +02:00
|
|
|
|
|
|
|
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
|
|
|
|
}
|
2021-09-06 23:33:50 +02:00
|
|
|
|
|
|
|
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)
|
|
|
|
}
|