Serializing rewrite
This commit is contained in:
parent
5d63c6d16a
commit
0603ba907c
34
decoder.go
34
decoder.go
|
@ -7,6 +7,8 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"reflect"
|
"reflect"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"gitea.olznet.de/OlzNet/slog"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Decoder struct {
|
type Decoder struct {
|
||||||
|
@ -21,21 +23,23 @@ func NewDecoder(r io.Reader) *Decoder {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dec *Decoder) Decode(e interface{}) (err error) {
|
func (dec *Decoder) Decode(e interface{}) (err error) {
|
||||||
return dec.DecodeValue(reflect.ValueOf(e))
|
t := reflect.TypeOf(e)
|
||||||
}
|
slog.LOG_DEBUGFLN("Dec: %v", t)
|
||||||
|
if t == reflect.TypeOf(errors.New("")) || t == reflect.TypeOf((*error)(nil)) {
|
||||||
func (dec *Decoder) DecodeValue(value reflect.Value) (err error) {
|
|
||||||
if value.Type() == reflect.TypeOf(errors.New("")) || value.Type() == reflect.TypeOf((*error)(nil)) {
|
|
||||||
var errstr string
|
var errstr string
|
||||||
if err = dec.Decode(&errstr); err != nil {
|
if err = dec.Decode(&errstr); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if errstr != "" {
|
if errstr != "" {
|
||||||
*value.Interface().(*error) = errors.New(errstr)
|
*e.(*error) = errors.New(errstr)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return dec.DecodeValue(reflect.ValueOf(e))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dec *Decoder) DecodeValue(value reflect.Value) (err error) {
|
||||||
if value.Kind() == reflect.Invalid {
|
if value.Kind() == reflect.Invalid {
|
||||||
return fmt.Errorf("ssob: Cannot decode nil: %w", ErrValueInvalid)
|
return fmt.Errorf("ssob: Cannot decode nil: %w", ErrValueInvalid)
|
||||||
}
|
}
|
||||||
|
@ -66,3 +70,21 @@ func (dec *Decoder) DecodeValue(value reflect.Value) (err error) {
|
||||||
_, err = unmarshal(value.Interface(), bb)
|
_, err = unmarshal(value.Interface(), bb)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (dec *Decoder) NDecode() (ret interface{}, err error) {
|
||||||
|
st := make([]byte, ST_ID_SIZE)
|
||||||
|
|
||||||
|
dec.mutex.Lock()
|
||||||
|
defer dec.mutex.Unlock()
|
||||||
|
|
||||||
|
if err = binary.Read(dec.r, binary.BigEndian, st); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
stype := binary.BigEndian.Uint32(st)
|
||||||
|
if t, ok := cacheTypes.types[stype]; !ok {
|
||||||
|
return nil, fmt.Errorf("ssob: Decode type '%d' not registered: %w", stype, ErrTypeUnknown)
|
||||||
|
} else {
|
||||||
|
return t.unmarshal(dec.r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
66
encoder.go
66
encoder.go
|
@ -7,6 +7,8 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"reflect"
|
"reflect"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"gitea.olznet.de/OlzNet/slog"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Encoder struct {
|
type Encoder struct {
|
||||||
|
@ -21,18 +23,26 @@ func NewEncoder(w io.Writer) *Encoder {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (enc *Encoder) Encode(e interface{}) (err error) {
|
func (enc *Encoder) Encode(e interface{}) (err error) {
|
||||||
|
t := reflect.TypeOf(e)
|
||||||
|
slog.LOG_DEBUGFLN("Enc: %v", t)
|
||||||
|
if t == reflect.TypeOf(errors.New("")) || t == reflect.TypeOf((*error)(nil)).Elem() {
|
||||||
|
if reflect.ValueOf(e).IsNil() {
|
||||||
|
return enc.Encode(string(""))
|
||||||
|
} else {
|
||||||
|
return enc.Encode(e.(error).Error())
|
||||||
|
}
|
||||||
|
} else if t == reflect.TypeOf((*error)(nil)) {
|
||||||
|
if reflect.Indirect(reflect.ValueOf(e)).IsNil() {
|
||||||
|
return enc.Encode(string(""))
|
||||||
|
} else {
|
||||||
|
return enc.Encode((*e.(*error)).Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return enc.EncodeValue(reflect.ValueOf(e))
|
return enc.EncodeValue(reflect.ValueOf(e))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (enc *Encoder) EncodeValue(value reflect.Value) (err error) {
|
func (enc *Encoder) EncodeValue(value reflect.Value) (err error) {
|
||||||
if value.Type() == reflect.TypeOf(errors.New("")) || value.Type() == reflect.TypeOf((*error)(nil)).Elem() {
|
|
||||||
if value.IsNil() {
|
|
||||||
return enc.Encode(string(""))
|
|
||||||
} else {
|
|
||||||
return enc.Encode(value.Interface().(error).Error())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if value.Kind() == reflect.Invalid {
|
if value.Kind() == reflect.Invalid {
|
||||||
return fmt.Errorf("ssob: Cannot encode nil: %w", ErrValueInvalid)
|
return fmt.Errorf("ssob: Cannot encode nil: %w", ErrValueInvalid)
|
||||||
}
|
}
|
||||||
|
@ -56,3 +66,43 @@ func (enc *Encoder) EncodeValue(value reflect.Value) (err error) {
|
||||||
|
|
||||||
return binary.Write(enc.w, binary.BigEndian, w)
|
return binary.Write(enc.w, binary.BigEndian, w)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (enc *Encoder) NEncode(e interface{}) (err error) {
|
||||||
|
RegisterType(e)
|
||||||
|
return enc.encode(e, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (enc *Encoder) encode(e interface{}, indirectLevel int) (err error) {
|
||||||
|
t := reflect.TypeOf(e)
|
||||||
|
|
||||||
|
if t.Kind() == reflect.Invalid {
|
||||||
|
return fmt.Errorf("ssob: Cannot encode nil: %w", ErrValueInvalid)
|
||||||
|
}
|
||||||
|
|
||||||
|
v := reflect.ValueOf(e)
|
||||||
|
//slog.LOG_DEBUGFLN("ssob: encode t.name: %s", t.Name())
|
||||||
|
//slog.LOG_DEBUGFLN("ssob: encode t.kind: %s", t.Kind())
|
||||||
|
slog.LOG_DEBUGFLN("ssob: encode v.type: %s", v.Type())
|
||||||
|
switch t.Kind() {
|
||||||
|
case reflect.Ptr:
|
||||||
|
if v.IsNil() {
|
||||||
|
return fmt.Errorf("ssob: Cannot encode nil pointer: %w", ErrValueInvalid)
|
||||||
|
}
|
||||||
|
p := reflect.Indirect(v)
|
||||||
|
return enc.encode(p.Interface(), indirectLevel+1)
|
||||||
|
case reflect.Struct:
|
||||||
|
return fmt.Errorf("ssob: Type '%s' named '%s' unknown: %w", t.Kind().String(), t.Name(), ErrTypeUnknown)
|
||||||
|
case reflect.Slice:
|
||||||
|
return fmt.Errorf("ssob: Type '%s' with types '%s' unknown: %w", t.Kind().String(), t.Elem().Kind().String(), ErrTypeUnknown)
|
||||||
|
case reflect.Array:
|
||||||
|
return fmt.Errorf("ssob: Type '%s' with types '%s' unknown: %w", t.Kind().String(), t.Name(), ErrTypeUnknown)
|
||||||
|
default:
|
||||||
|
if v, ok := cacheTypes.names[t.Kind().String()]; !ok {
|
||||||
|
return fmt.Errorf("ssob: Type '%s' unknown: %w", t.Kind().String(), ErrTypeUnknown)
|
||||||
|
} else {
|
||||||
|
enc.mutex.Lock()
|
||||||
|
defer enc.mutex.Unlock()
|
||||||
|
return cacheTypes.types[v].marshal(e, enc.w)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
2
go.mod
2
go.mod
|
@ -1,3 +1,5 @@
|
||||||
module gitea.olznet.de/OlzNet/ssob
|
module gitea.olznet.de/OlzNet/ssob
|
||||||
|
|
||||||
go 1.15
|
go 1.15
|
||||||
|
|
||||||
|
require gitea.olznet.de/OlzNet/slog v1.2.4
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
gitea.olznet.de/OlzNet/slog v1.2.4 h1:22/+57/2J7EnFQAwT6xRENgvPeI2RwSmOWuXwkujpf4=
|
||||||
|
gitea.olznet.de/OlzNet/slog v1.2.4/go.mod h1:xHB0ZnXIXFdnISKpWvDnrBSl4dGB3rzQji36n2sbJXg=
|
66
marshal.go
66
marshal.go
|
@ -3,6 +3,7 @@ package ssob
|
||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"math"
|
"math"
|
||||||
"reflect"
|
"reflect"
|
||||||
)
|
)
|
||||||
|
@ -416,3 +417,68 @@ func marshal(e interface{}) (ret []byte, err error) {
|
||||||
func RegisterEncoder(name string, f MarshalFunc) {
|
func RegisterEncoder(name string, f MarshalFunc) {
|
||||||
encoderCache[name] = f
|
encoderCache[name] = f
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func baseTypeMarshaller(e interface{}, w io.Writer) (err error) {
|
||||||
|
var sb []byte
|
||||||
|
|
||||||
|
switch e.(type) {
|
||||||
|
case bool:
|
||||||
|
sb = make([]byte, ST_ID_SIZE+1)
|
||||||
|
binary.BigEndian.PutUint32(sb, ST_BOOL)
|
||||||
|
if e.(bool) == true {
|
||||||
|
sb[ST_ID_SIZE] = 0
|
||||||
|
} else {
|
||||||
|
sb[ST_ID_SIZE] = 1
|
||||||
|
}
|
||||||
|
case uint8:
|
||||||
|
sb = make([]byte, ST_ID_SIZE+1)
|
||||||
|
binary.BigEndian.PutUint32(sb, ST_UINT8)
|
||||||
|
sb[ST_ID_SIZE] = byte(e.(uint8))
|
||||||
|
case uint16:
|
||||||
|
sb = make([]byte, ST_ID_SIZE+2)
|
||||||
|
binary.BigEndian.PutUint32(sb, ST_UINT16)
|
||||||
|
binary.BigEndian.PutUint16(sb[ST_ID_SIZE:], e.(uint16))
|
||||||
|
case uint32:
|
||||||
|
sb = make([]byte, ST_ID_SIZE+4)
|
||||||
|
binary.BigEndian.PutUint32(sb, ST_UINT32)
|
||||||
|
binary.BigEndian.PutUint32(sb[ST_ID_SIZE:], e.(uint32))
|
||||||
|
case uint64:
|
||||||
|
sb = make([]byte, ST_ID_SIZE+8)
|
||||||
|
binary.BigEndian.PutUint32(sb, ST_UINT64)
|
||||||
|
binary.BigEndian.PutUint64(sb[ST_ID_SIZE:], e.(uint64))
|
||||||
|
case int8:
|
||||||
|
sb = make([]byte, ST_ID_SIZE+1)
|
||||||
|
binary.BigEndian.PutUint32(sb[ST_ID_SIZE:], ST_INT8)
|
||||||
|
sb[ST_ID_SIZE] = byte(e.(int8))
|
||||||
|
case int16:
|
||||||
|
sb = make([]byte, ST_ID_SIZE+2)
|
||||||
|
binary.BigEndian.PutUint32(sb, ST_INT16)
|
||||||
|
binary.BigEndian.PutUint16(sb[ST_ID_SIZE:], uint16(e.(int16)))
|
||||||
|
case int32:
|
||||||
|
sb = make([]byte, ST_ID_SIZE+4)
|
||||||
|
binary.BigEndian.PutUint32(sb, ST_INT32)
|
||||||
|
binary.BigEndian.PutUint32(sb[ST_ID_SIZE:], uint32(e.(int32)))
|
||||||
|
case int64:
|
||||||
|
sb = make([]byte, ST_ID_SIZE+8)
|
||||||
|
binary.BigEndian.PutUint32(sb, ST_INT64)
|
||||||
|
binary.BigEndian.PutUint64(sb[ST_ID_SIZE:], uint64(e.(int64)))
|
||||||
|
case float32:
|
||||||
|
sb = make([]byte, ST_ID_SIZE+4)
|
||||||
|
binary.BigEndian.PutUint32(sb, ST_FLOAT32)
|
||||||
|
binary.BigEndian.PutUint32(sb[ST_ID_SIZE:], math.Float32bits(e.(float32)))
|
||||||
|
case float64:
|
||||||
|
sb = make([]byte, ST_ID_SIZE+8)
|
||||||
|
binary.BigEndian.PutUint32(sb, ST_FLOAT64)
|
||||||
|
binary.BigEndian.PutUint64(sb[ST_ID_SIZE:], math.Float64bits(e.(float64)))
|
||||||
|
case string:
|
||||||
|
slen := len(e.(string))
|
||||||
|
sb = make([]byte, ST_ID_SIZE+slen+4)
|
||||||
|
binary.BigEndian.PutUint32(sb, ST_STRING)
|
||||||
|
binary.BigEndian.PutUint32(sb[ST_ID_SIZE:], uint32(slen))
|
||||||
|
copy(sb[ST_ID_SIZE+4:], []byte(e.(string)))
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("ssob: Unknown type: %s: %w", reflect.TypeOf(e), ErrValueInvalid)
|
||||||
|
}
|
||||||
|
|
||||||
|
return binary.Write(w, binary.BigEndian, sb)
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,569 @@
|
||||||
|
package ssob
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"reflect"
|
||||||
|
|
||||||
|
"gitea.olznet.de/OlzNet/slog"
|
||||||
|
)
|
||||||
|
|
||||||
|
type allocatorFunc func(vals ...interface{}) interface{}
|
||||||
|
type marshallerFunc func(interface{}, io.Writer) error
|
||||||
|
type unmarshallerFunc func(io.Reader) (interface{}, error)
|
||||||
|
|
||||||
|
type nallocFunc func() interface{}
|
||||||
|
|
||||||
|
type RegisteredTypes struct {
|
||||||
|
NextId uint32
|
||||||
|
types map[uint32]Type
|
||||||
|
names map[string]uint32
|
||||||
|
ntypes map[uint32]*NType
|
||||||
|
nnames map[string]*NType
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
ST_COMMON = 0
|
||||||
|
ST_SLICE = 1
|
||||||
|
ST_ARRAY = 2
|
||||||
|
ST_STRUCT = 3
|
||||||
|
ST_MAP = 4
|
||||||
|
ST_INTERFACE = 5
|
||||||
|
ST_STRUCT_FIELD = 6
|
||||||
|
)
|
||||||
|
|
||||||
|
type StructField struct {
|
||||||
|
Name string
|
||||||
|
Tag string
|
||||||
|
}
|
||||||
|
|
||||||
|
type NType struct {
|
||||||
|
Name string
|
||||||
|
Id uint32
|
||||||
|
Indirection int
|
||||||
|
MainTypeId uint32
|
||||||
|
ValTypes []uint32
|
||||||
|
structFields []*StructField
|
||||||
|
alloc nallocFunc
|
||||||
|
}
|
||||||
|
|
||||||
|
type Type struct {
|
||||||
|
Name string
|
||||||
|
Id uint32
|
||||||
|
alloc allocatorFunc
|
||||||
|
marshal marshallerFunc
|
||||||
|
unmarshal unmarshallerFunc
|
||||||
|
}
|
||||||
|
|
||||||
|
type baseType struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
var cacheTypes RegisteredTypes
|
||||||
|
|
||||||
|
const (
|
||||||
|
ST_ID_SIZE = 4
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
ST_INVALID = 0
|
||||||
|
ST_BOOL = 1
|
||||||
|
ST_UINT8 = 2
|
||||||
|
ST_UINT16 = 3
|
||||||
|
ST_UINT32 = 4
|
||||||
|
ST_UINT64 = 5
|
||||||
|
ST_INT8 = 6
|
||||||
|
ST_INT16 = 7
|
||||||
|
ST_INT32 = 8
|
||||||
|
ST_INT64 = 9
|
||||||
|
ST_FLOAT32 = 10
|
||||||
|
ST_FLOAT64 = 11
|
||||||
|
ST_STRING = 12
|
||||||
|
ST_ERROR = 13
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
cacheTypes.NextId = 128
|
||||||
|
cacheTypes.types = make(map[uint32]Type)
|
||||||
|
cacheTypes.names = make(map[string]uint32)
|
||||||
|
cacheTypes.ntypes = make(map[uint32]*NType)
|
||||||
|
cacheTypes.nnames = make(map[string]*NType)
|
||||||
|
|
||||||
|
boolType := &NType{
|
||||||
|
"bool", ST_BOOL, 0, ST_COMMON, []uint32{ST_BOOL},
|
||||||
|
nil, func() interface{} { return new(bool) },
|
||||||
|
}
|
||||||
|
cacheTypes.ntypes[ST_BOOL] = boolType
|
||||||
|
cacheTypes.nnames["bool"] = boolType
|
||||||
|
|
||||||
|
uint8Type := &NType{
|
||||||
|
"uint8", ST_UINT8, 0, ST_COMMON, []uint32{ST_UINT8},
|
||||||
|
nil, func() interface{} { return new(uint8) },
|
||||||
|
}
|
||||||
|
cacheTypes.ntypes[ST_UINT8] = uint8Type
|
||||||
|
cacheTypes.nnames["uint8"] = uint8Type
|
||||||
|
|
||||||
|
uint16Type := &NType{
|
||||||
|
"uint16", ST_UINT16, 0, ST_COMMON, []uint32{ST_UINT16},
|
||||||
|
nil, func() interface{} { return new(uint16) },
|
||||||
|
}
|
||||||
|
cacheTypes.ntypes[ST_UINT16] = uint16Type
|
||||||
|
cacheTypes.nnames["uint16"] = uint16Type
|
||||||
|
|
||||||
|
uint32Type := &NType{
|
||||||
|
"uint32", ST_UINT32, 0, ST_COMMON, []uint32{ST_UINT32},
|
||||||
|
nil, func() interface{} { return new(uint32) },
|
||||||
|
}
|
||||||
|
cacheTypes.ntypes[ST_UINT32] = uint32Type
|
||||||
|
cacheTypes.nnames["uint32"] = uint32Type
|
||||||
|
|
||||||
|
uint64Type := &NType{
|
||||||
|
"uint64", ST_UINT64, 0, ST_COMMON, []uint32{ST_UINT64},
|
||||||
|
nil, func() interface{} { return new(uint64) },
|
||||||
|
}
|
||||||
|
cacheTypes.ntypes[ST_UINT64] = uint64Type
|
||||||
|
cacheTypes.nnames["uint64"] = uint64Type
|
||||||
|
|
||||||
|
int8Type := &NType{
|
||||||
|
"int8", ST_INT8, 0, ST_COMMON, []uint32{ST_INT8},
|
||||||
|
nil, func() interface{} { return new(int8) },
|
||||||
|
}
|
||||||
|
cacheTypes.ntypes[ST_INT8] = int8Type
|
||||||
|
cacheTypes.nnames["int8"] = int8Type
|
||||||
|
|
||||||
|
int16Type := &NType{
|
||||||
|
"int16", ST_INT16, 0, ST_COMMON, []uint32{ST_INT16},
|
||||||
|
nil, func() interface{} { return new(int16) },
|
||||||
|
}
|
||||||
|
cacheTypes.ntypes[ST_INT16] = int16Type
|
||||||
|
cacheTypes.nnames["int16"] = int16Type
|
||||||
|
|
||||||
|
int32Type := &NType{
|
||||||
|
"int32", ST_INT32, 0, ST_COMMON, []uint32{ST_INT32},
|
||||||
|
nil, func() interface{} { return new(int32) },
|
||||||
|
}
|
||||||
|
cacheTypes.ntypes[ST_INT32] = int32Type
|
||||||
|
cacheTypes.nnames["int32"] = int32Type
|
||||||
|
|
||||||
|
int64Type := &NType{
|
||||||
|
"int64", ST_INT64, 0, ST_COMMON, []uint32{ST_INT64},
|
||||||
|
nil, func() interface{} { return new(int64) },
|
||||||
|
}
|
||||||
|
cacheTypes.ntypes[ST_INT64] = int64Type
|
||||||
|
cacheTypes.nnames["int64"] = int64Type
|
||||||
|
|
||||||
|
float32Type := &NType{
|
||||||
|
"float32", ST_FLOAT32, 0, ST_COMMON, []uint32{ST_FLOAT32},
|
||||||
|
nil, func() interface{} { return new(float32) },
|
||||||
|
}
|
||||||
|
cacheTypes.ntypes[ST_FLOAT32] = float32Type
|
||||||
|
cacheTypes.nnames["float32"] = float32Type
|
||||||
|
|
||||||
|
float64Type := &NType{
|
||||||
|
"float64", ST_FLOAT64, 0, ST_COMMON, []uint32{ST_FLOAT64},
|
||||||
|
nil, func() interface{} { return new(float64) },
|
||||||
|
}
|
||||||
|
cacheTypes.ntypes[ST_FLOAT64] = float64Type
|
||||||
|
cacheTypes.nnames["float64"] = float64Type
|
||||||
|
|
||||||
|
stringType := &NType{
|
||||||
|
"string", ST_STRING, 0, ST_COMMON, []uint32{ST_STRING},
|
||||||
|
nil, func() interface{} { return new(string) },
|
||||||
|
}
|
||||||
|
cacheTypes.ntypes[ST_STRING] = stringType
|
||||||
|
cacheTypes.nnames["string"] = stringType
|
||||||
|
|
||||||
|
errorType := &NType{
|
||||||
|
"error", ST_ERROR, 0, ST_COMMON, []uint32{ST_ERROR},
|
||||||
|
nil, func() interface{} { return new(error) },
|
||||||
|
}
|
||||||
|
cacheTypes.ntypes[ST_ERROR] = errorType
|
||||||
|
cacheTypes.nnames["error"] = errorType
|
||||||
|
|
||||||
|
cacheTypes.types[ST_BOOL] = Type{
|
||||||
|
"bool", ST_BOOL,
|
||||||
|
func(vals ...interface{}) interface{} { return new(bool) },
|
||||||
|
baseTypeMarshaller,
|
||||||
|
func(r io.Reader) (interface{}, error) { return baseTypeUnmarshaller(ST_BOOL, r) },
|
||||||
|
}
|
||||||
|
cacheTypes.names["bool"] = ST_BOOL
|
||||||
|
|
||||||
|
cacheTypes.types[ST_UINT8] = Type{
|
||||||
|
"uint8", ST_UINT8,
|
||||||
|
func(vals ...interface{}) interface{} { return new(uint8) },
|
||||||
|
baseTypeMarshaller,
|
||||||
|
func(r io.Reader) (interface{}, error) { return baseTypeUnmarshaller(ST_UINT8, r) },
|
||||||
|
}
|
||||||
|
cacheTypes.names["uint8"] = ST_UINT8
|
||||||
|
|
||||||
|
cacheTypes.types[ST_UINT16] = Type{
|
||||||
|
"uint16", ST_UINT16,
|
||||||
|
func(vals ...interface{}) interface{} { return new(uint16) },
|
||||||
|
baseTypeMarshaller,
|
||||||
|
func(r io.Reader) (interface{}, error) { return baseTypeUnmarshaller(ST_UINT16, r) },
|
||||||
|
}
|
||||||
|
cacheTypes.names["uint16"] = ST_UINT16
|
||||||
|
|
||||||
|
cacheTypes.types[ST_UINT32] = Type{
|
||||||
|
"uint32", ST_UINT32,
|
||||||
|
func(vals ...interface{}) interface{} { return new(uint32) },
|
||||||
|
baseTypeMarshaller,
|
||||||
|
func(r io.Reader) (interface{}, error) { return baseTypeUnmarshaller(ST_UINT32, r) },
|
||||||
|
}
|
||||||
|
cacheTypes.names["uint32"] = ST_UINT32
|
||||||
|
|
||||||
|
cacheTypes.types[ST_UINT64] = Type{
|
||||||
|
"uint64", ST_UINT64,
|
||||||
|
func(vals ...interface{}) interface{} { return new(uint64) },
|
||||||
|
baseTypeMarshaller,
|
||||||
|
func(r io.Reader) (interface{}, error) { return baseTypeUnmarshaller(ST_UINT64, r) },
|
||||||
|
}
|
||||||
|
cacheTypes.names["uint64"] = ST_UINT64
|
||||||
|
|
||||||
|
cacheTypes.types[ST_INT8] = Type{
|
||||||
|
"int8", ST_INT8,
|
||||||
|
func(vals ...interface{}) interface{} { return new(int8) },
|
||||||
|
baseTypeMarshaller,
|
||||||
|
func(r io.Reader) (interface{}, error) { return baseTypeUnmarshaller(ST_INT8, r) },
|
||||||
|
}
|
||||||
|
cacheTypes.names["int8"] = ST_UINT8
|
||||||
|
|
||||||
|
cacheTypes.types[ST_INT16] = Type{
|
||||||
|
"int16", ST_INT16,
|
||||||
|
func(vals ...interface{}) interface{} { return new(int16) },
|
||||||
|
baseTypeMarshaller,
|
||||||
|
func(r io.Reader) (interface{}, error) { return baseTypeUnmarshaller(ST_INT16, r) },
|
||||||
|
}
|
||||||
|
cacheTypes.names["int16"] = ST_INT16
|
||||||
|
|
||||||
|
cacheTypes.types[ST_INT32] = Type{
|
||||||
|
"int32", ST_INT32,
|
||||||
|
func(vals ...interface{}) interface{} { return new(int32) },
|
||||||
|
baseTypeMarshaller,
|
||||||
|
func(r io.Reader) (interface{}, error) { return baseTypeUnmarshaller(ST_INT32, r) },
|
||||||
|
}
|
||||||
|
cacheTypes.names["int32"] = ST_INT32
|
||||||
|
|
||||||
|
cacheTypes.types[ST_INT64] = Type{
|
||||||
|
"int64", ST_INT64,
|
||||||
|
func(vals ...interface{}) interface{} { return new(int64) },
|
||||||
|
baseTypeMarshaller,
|
||||||
|
func(r io.Reader) (interface{}, error) { return baseTypeUnmarshaller(ST_INT64, r) },
|
||||||
|
}
|
||||||
|
cacheTypes.names["int64"] = ST_INT64
|
||||||
|
|
||||||
|
cacheTypes.types[ST_FLOAT32] = Type{
|
||||||
|
"float32", ST_FLOAT32,
|
||||||
|
func(vals ...interface{}) interface{} { return new(float32) },
|
||||||
|
baseTypeMarshaller,
|
||||||
|
func(r io.Reader) (interface{}, error) { return baseTypeUnmarshaller(ST_FLOAT32, r) },
|
||||||
|
}
|
||||||
|
cacheTypes.names["float32"] = ST_FLOAT32
|
||||||
|
|
||||||
|
cacheTypes.types[ST_FLOAT64] = Type{
|
||||||
|
"float64", ST_FLOAT64,
|
||||||
|
func(vals ...interface{}) interface{} { return new(float64) },
|
||||||
|
baseTypeMarshaller,
|
||||||
|
func(r io.Reader) (interface{}, error) { return baseTypeUnmarshaller(ST_FLOAT64, r) },
|
||||||
|
}
|
||||||
|
cacheTypes.names["float64"] = ST_FLOAT64
|
||||||
|
|
||||||
|
cacheTypes.types[ST_STRING] = Type{
|
||||||
|
"string", ST_STRING,
|
||||||
|
func(vals ...interface{}) interface{} { return new(string) },
|
||||||
|
baseTypeMarshaller,
|
||||||
|
func(r io.Reader) (interface{}, error) { return baseTypeUnmarshaller(ST_STRING, r) },
|
||||||
|
}
|
||||||
|
cacheTypes.names["string"] = ST_STRING
|
||||||
|
}
|
||||||
|
|
||||||
|
func getTypeId(e interface{}, indirectLevel int) (id uint32, level int) {
|
||||||
|
level = indirectLevel
|
||||||
|
t := reflect.TypeOf(e)
|
||||||
|
|
||||||
|
if t.Kind() == reflect.Invalid {
|
||||||
|
return ST_INVALID, level
|
||||||
|
}
|
||||||
|
|
||||||
|
v := reflect.ValueOf(e)
|
||||||
|
switch t.Kind() {
|
||||||
|
case reflect.Ptr:
|
||||||
|
if v.IsNil() {
|
||||||
|
return ST_INVALID, level
|
||||||
|
}
|
||||||
|
p := reflect.Indirect(v)
|
||||||
|
level += 1
|
||||||
|
return getTypeId(p.Interface(), level)
|
||||||
|
}
|
||||||
|
|
||||||
|
if id, ok := cacheTypes.names[t.Kind().String()]; ok {
|
||||||
|
return id, level
|
||||||
|
}
|
||||||
|
|
||||||
|
return ST_INVALID, level
|
||||||
|
}
|
||||||
|
|
||||||
|
func getIndirection(e interface{}, level int) (indirection int, maintype uint32, typ reflect.Type) {
|
||||||
|
indirection = level
|
||||||
|
maintype = ST_COMMON
|
||||||
|
|
||||||
|
t := reflect.TypeOf(e)
|
||||||
|
v := reflect.ValueOf(e)
|
||||||
|
|
||||||
|
switch t.Kind() {
|
||||||
|
case reflect.Ptr:
|
||||||
|
if v.IsNil() {
|
||||||
|
return indirection, maintype, t
|
||||||
|
}
|
||||||
|
p := reflect.Indirect(v)
|
||||||
|
indirection += 1
|
||||||
|
return getIndirection(p.Interface(), indirection)
|
||||||
|
case reflect.Slice:
|
||||||
|
maintype = ST_SLICE
|
||||||
|
case reflect.Array:
|
||||||
|
maintype = ST_ARRAY
|
||||||
|
case reflect.Struct:
|
||||||
|
maintype = ST_STRUCT
|
||||||
|
}
|
||||||
|
|
||||||
|
return indirection, maintype, t
|
||||||
|
}
|
||||||
|
|
||||||
|
func getTypeById(id uint32) (ret *NType) {
|
||||||
|
if ret, ok := cacheTypes.ntypes[id]; !ok {
|
||||||
|
return nil
|
||||||
|
} else {
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getTypeByName(name string) (ret *NType) {
|
||||||
|
if ret, ok := cacheTypes.nnames[name]; !ok {
|
||||||
|
return nil
|
||||||
|
} else {
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseType(t reflect.Type) (ret nallocFunc, mainTypeId uint32, indirection int, valTypes []uint32, base bool, sfields []*StructField, err error) {
|
||||||
|
indirection = 0
|
||||||
|
ret = func() interface{} {
|
||||||
|
vret := reflect.New(t)
|
||||||
|
val := vret.Elem()
|
||||||
|
|
||||||
|
for {
|
||||||
|
if val.Kind() == reflect.Ptr {
|
||||||
|
val.Set(reflect.New(val.Type().Elem()))
|
||||||
|
val = val.Elem()
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return vret.Interface()
|
||||||
|
}
|
||||||
|
|
||||||
|
valTypes = []uint32{}
|
||||||
|
sfields = []*StructField{}
|
||||||
|
vret := reflect.New(t)
|
||||||
|
val := vret.Elem()
|
||||||
|
nval := vret
|
||||||
|
|
||||||
|
base = true
|
||||||
|
|
||||||
|
for {
|
||||||
|
if val.Kind() == reflect.Ptr {
|
||||||
|
nval = nval.Elem()
|
||||||
|
val.Set(reflect.New(val.Type().Elem()))
|
||||||
|
val = val.Elem()
|
||||||
|
indirection += 1
|
||||||
|
base = false
|
||||||
|
slog.LOG_DEBUGFLN("Indirection: %d", indirection)
|
||||||
|
} else {
|
||||||
|
slog.LOG_DEBUGFLN("ELSE: %v", t)
|
||||||
|
|
||||||
|
switch val.Kind() {
|
||||||
|
case reflect.Slice:
|
||||||
|
typ := reflect.TypeOf(val.Interface())
|
||||||
|
slog.LOG_DEBUGFLN("typ.Kind(): %s", typ.Kind())
|
||||||
|
slog.LOG_DEBUGFLN("val.Type(): %s", typ.Elem())
|
||||||
|
vt, err := getTypeByNameRegister(typ.Elem().String(), typ.Elem())
|
||||||
|
slog.LOG_DEBUGFLN("vt: %v", vt)
|
||||||
|
if err != nil {
|
||||||
|
return ret, mainTypeId, indirection, valTypes, base, sfields, fmt.Errorf("ssob: Failed receiving type '%s': %w", typ.Elem(), err)
|
||||||
|
}
|
||||||
|
valTypes = append(valTypes, vt.Id)
|
||||||
|
base = false
|
||||||
|
mainTypeId = ST_SLICE
|
||||||
|
case reflect.Array:
|
||||||
|
typ := reflect.TypeOf(val.Interface())
|
||||||
|
slog.LOG_DEBUGFLN("typ.Kind(): %s", typ.Kind())
|
||||||
|
slog.LOG_DEBUGFLN("val.Type(): %s", typ.Elem())
|
||||||
|
vt, err := getTypeByNameRegister(typ.Elem().String(), typ.Elem())
|
||||||
|
slog.LOG_DEBUGFLN("vt: %v", vt)
|
||||||
|
if err != nil {
|
||||||
|
return ret, mainTypeId, indirection, valTypes, base, sfields, fmt.Errorf("ssob: Failed receiving type '%s': %w", typ.Elem(), err)
|
||||||
|
}
|
||||||
|
valTypes = append(valTypes, uint32(val.Len()))
|
||||||
|
valTypes = append(valTypes, vt.Id)
|
||||||
|
base = false
|
||||||
|
mainTypeId = ST_ARRAY
|
||||||
|
case reflect.Interface:
|
||||||
|
typ := reflect.TypeOf(nval.Interface())
|
||||||
|
slog.LOG_DEBUGFLN("val.Type(): %s", typ.Elem())
|
||||||
|
slog.LOG_DEBUGFLN("INTERFACE")
|
||||||
|
if !base {
|
||||||
|
vt, err := getTypeByNameRegister(typ.Elem().String(), typ.Elem())
|
||||||
|
slog.LOG_DEBUGFLN("vt: %v", vt)
|
||||||
|
if err != nil {
|
||||||
|
return ret, mainTypeId, indirection, valTypes, base, sfields, fmt.Errorf("ssob: Failed receiving type '%s': %w", typ.Elem(), err)
|
||||||
|
}
|
||||||
|
valTypes = append(valTypes, vt.Id)
|
||||||
|
}
|
||||||
|
mainTypeId = ST_INTERFACE
|
||||||
|
case reflect.Struct:
|
||||||
|
typ := reflect.TypeOf(val.Interface())
|
||||||
|
slog.LOG_DEBUGFLN("typ.Kind(): %s", typ.String())
|
||||||
|
slog.LOG_DEBUGFLN("STRUCT")
|
||||||
|
if !base {
|
||||||
|
vt, err := getTypeByNameRegister(typ.String(), typ)
|
||||||
|
slog.LOG_DEBUGFLN("vt: %v", vt)
|
||||||
|
if err != nil {
|
||||||
|
return ret, mainTypeId, indirection, valTypes, base, sfields, fmt.Errorf("ssob: Failed receiving type '%s': %w", typ.Elem(), err)
|
||||||
|
}
|
||||||
|
valTypes = append(valTypes, vt.Id)
|
||||||
|
} else {
|
||||||
|
sl := val.NumField()
|
||||||
|
for i := 0; i < sl; i++ {
|
||||||
|
if val.Field(i).CanSet() {
|
||||||
|
slog.LOG_DEBUGFLN("Struct '%s': Field '%d' '%s' -> '%v'", typ.String(), i, val.Type().Field(i).Name, val.Field(i).Type())
|
||||||
|
sfield := new(StructField)
|
||||||
|
sfield.Name = val.Type().Field(i).Name
|
||||||
|
sfield.Tag = string(val.Type().Field(i).Tag)
|
||||||
|
sfields = append(sfields, sfield)
|
||||||
|
vt, err := getTypeByNameRegister(val.Field(i).Type().String(), val.Field(i).Type())
|
||||||
|
if err != nil {
|
||||||
|
return ret, mainTypeId, indirection, valTypes, base, sfields, fmt.Errorf("ssob: Failed receiving type '%s': %w", typ.Elem(), err)
|
||||||
|
}
|
||||||
|
valTypes = append(valTypes, vt.Id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
base = false
|
||||||
|
}
|
||||||
|
mainTypeId = ST_STRUCT
|
||||||
|
case reflect.Map:
|
||||||
|
typ := reflect.TypeOf(val.Interface())
|
||||||
|
slog.LOG_DEBUGFLN("typ.Kind(): %s", typ.String())
|
||||||
|
slog.LOG_DEBUGFLN("MAP")
|
||||||
|
slog.LOG_DEBUGFLN("key: %s", typ.Key())
|
||||||
|
slog.LOG_DEBUGFLN("val: %s", typ.Elem())
|
||||||
|
if !base {
|
||||||
|
vt, err := getTypeByNameRegister(typ.String(), typ)
|
||||||
|
slog.LOG_DEBUGFLN("vt: %v", vt)
|
||||||
|
if err != nil {
|
||||||
|
return ret, mainTypeId, indirection, valTypes, base, sfields, fmt.Errorf("ssob: Failed receiving type '%s': %w", typ.Elem(), err)
|
||||||
|
}
|
||||||
|
valTypes = append(valTypes, vt.Id)
|
||||||
|
} else {
|
||||||
|
// Key
|
||||||
|
vt, err := getTypeByNameRegister(typ.Key().String(), typ.Key())
|
||||||
|
slog.LOG_DEBUGFLN("vt: %v", vt)
|
||||||
|
if err != nil {
|
||||||
|
return ret, mainTypeId, indirection, valTypes, base, sfields, fmt.Errorf("ssob: Failed receiving type '%s': %w", typ.Elem(), err)
|
||||||
|
}
|
||||||
|
valTypes = append(valTypes, vt.Id)
|
||||||
|
|
||||||
|
// Val
|
||||||
|
vt, err = getTypeByNameRegister(typ.Elem().String(), typ.Elem())
|
||||||
|
slog.LOG_DEBUGFLN("vt: %v", vt)
|
||||||
|
if err != nil {
|
||||||
|
return ret, mainTypeId, indirection, valTypes, base, sfields, fmt.Errorf("ssob: Failed receiving type '%s': %w", typ.Elem(), err)
|
||||||
|
}
|
||||||
|
valTypes = append(valTypes, vt.Id)
|
||||||
|
base = false
|
||||||
|
}
|
||||||
|
mainTypeId = ST_MAP
|
||||||
|
default:
|
||||||
|
typ := reflect.TypeOf(val.Interface())
|
||||||
|
slog.LOG_DEBUGFLN("typ.Kind(): %s", typ.Kind())
|
||||||
|
slog.LOG_DEBUGFLN("COMMON")
|
||||||
|
if !base {
|
||||||
|
vt, err := getTypeByNameRegister(typ.Kind().String(), typ)
|
||||||
|
slog.LOG_DEBUGFLN("vt: %v", vt)
|
||||||
|
if err != nil {
|
||||||
|
return ret, mainTypeId, indirection, valTypes, base, sfields, fmt.Errorf("ssob: Failed receiving type '%s': %w", typ.Elem(), err)
|
||||||
|
}
|
||||||
|
valTypes = append(valTypes, vt.Id)
|
||||||
|
}
|
||||||
|
mainTypeId = ST_COMMON
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret, mainTypeId, indirection, valTypes, base, sfields, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func getTypeByNameRegister(name string, t reflect.Type) (ret *NType, err error) {
|
||||||
|
if ret = getTypeByName(name); ret != nil {
|
||||||
|
return ret, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = registerType(t); err != nil {
|
||||||
|
return ret, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if ret = getTypeByName(name); ret == nil {
|
||||||
|
return ret, fmt.Errorf("ssob: Failed registering type '%s'", name)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func createType(t reflect.Type) (ret *NType, base bool, err error) {
|
||||||
|
if t == nil {
|
||||||
|
return ret, base, fmt.Errorf("ssob: Cannot create Type from nil: %w", ErrTypeInvalid)
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = new(NType)
|
||||||
|
ret.Name = t.String()
|
||||||
|
slog.LOG_DEBUGFLN("t.Name(): %s", t)
|
||||||
|
ret.alloc, ret.MainTypeId, ret.Indirection, ret.ValTypes, base, ret.structFields, err = parseType(t)
|
||||||
|
|
||||||
|
return ret, base, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func registerType(t reflect.Type) (err error) {
|
||||||
|
if t == nil || t.Kind() == reflect.Invalid {
|
||||||
|
return fmt.Errorf("ssob: Cannot register nil: %w", ErrTypeInvalid)
|
||||||
|
}
|
||||||
|
|
||||||
|
if getTypeByName(t.String()) != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var base bool
|
||||||
|
ntype, base, err := createType(t)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("ssob: Cannot register type '%s': %w", t, err)
|
||||||
|
}
|
||||||
|
ntype.Id = cacheTypes.NextId
|
||||||
|
if base {
|
||||||
|
ntype.ValTypes = []uint32{ntype.Id}
|
||||||
|
}
|
||||||
|
cacheTypes.ntypes[ntype.Id] = ntype
|
||||||
|
cacheTypes.nnames[ntype.Name] = ntype
|
||||||
|
cacheTypes.NextId += 1
|
||||||
|
|
||||||
|
slog.LOG_DEBUGFLN("Registered type: %v", ntype)
|
||||||
|
if ntype.MainTypeId == ST_STRUCT {
|
||||||
|
for _, f := range ntype.structFields {
|
||||||
|
slog.LOG_DEBUGFLN(" Field: %v", f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func RegisterType(e interface{}) (err error) {
|
||||||
|
t := reflect.TypeOf(e)
|
||||||
|
return registerType(t)
|
||||||
|
}
|
104
unmarshal.go
104
unmarshal.go
|
@ -3,6 +3,7 @@ package ssob
|
||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"math"
|
"math"
|
||||||
"reflect"
|
"reflect"
|
||||||
)
|
)
|
||||||
|
@ -592,3 +593,106 @@ func unmarshal(e interface{}, in []byte) (n int, err error) {
|
||||||
func RegisterDecoder(name string, f func(e interface{}, in []byte) (n int, err error)) {
|
func RegisterDecoder(name string, f func(e interface{}, in []byte) (n int, err error)) {
|
||||||
decoderCache[name] = f
|
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
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue