ssob/types.go

568 lines
13 KiB
Go
Raw Permalink Normal View History

2021-09-02 00:08:59 +02:00
package ssob
import (
"fmt"
"io"
"reflect"
2021-09-08 13:27:39 +02:00
"gitea.olznet.de/OlzNet/slog"
2021-09-02 00:08:59 +02:00
)
type allocatorFunc func(vals ...interface{}) interface{}
type marshallerFunc func(interface{}, io.Writer) error
type unmarshallerFunc func(io.Reader) (interface{}, error)
2021-09-02 15:25:39 +02:00
type marshalFunc func(interface{}) ([]byte, error)
2021-09-02 00:08:59 +02:00
type nallocFunc func() interface{}
type RegisteredTypes struct {
NextId uint32
ntypes map[uint32]*NType
nnames map[string]*NType
}
const (
2021-10-21 11:46:02 +02:00
ST_COMMON = 0
ST_SLICE = 1
ST_ARRAY = 2
ST_STRUCT = 3
ST_MAP = 4
//ST_MINTERFACE = 5
2021-09-02 00:08:59 +02:00
)
type StructField struct {
2021-09-02 15:25:39 +02:00
Id uint32
2021-09-02 00:08:59 +02:00
Name string
Tag string
2021-09-07 16:05:04 +02:00
SId int
2021-09-02 00:08:59 +02:00
}
type NType struct {
Name string
Id uint32
Indirection int
MainTypeId uint32
2021-09-02 15:25:39 +02:00
ValType uint32
2021-09-02 00:08:59 +02:00
structFields []*StructField
2021-09-02 15:25:39 +02:00
arrayLen int
2021-09-02 00:08:59 +02:00
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 (
2021-10-21 11:46:02 +02:00
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
ST_NIL = 14
ST_INTERFACE = 15
2021-09-02 00:08:59 +02:00
)
func init() {
cacheTypes.NextId = 128
cacheTypes.ntypes = make(map[uint32]*NType)
cacheTypes.nnames = make(map[string]*NType)
boolType := &NType{
2021-09-02 15:25:39 +02:00
"bool", ST_BOOL, 0, ST_COMMON, ST_BOOL, nil,
0, func() interface{} { return new(bool) },
2021-09-02 00:08:59 +02:00
}
cacheTypes.ntypes[ST_BOOL] = boolType
cacheTypes.nnames["bool"] = boolType
uint8Type := &NType{
2021-09-02 15:25:39 +02:00
"uint8", ST_UINT8, 0, ST_COMMON, ST_UINT8, nil,
0, func() interface{} { return new(uint8) },
2021-09-02 00:08:59 +02:00
}
cacheTypes.ntypes[ST_UINT8] = uint8Type
cacheTypes.nnames["uint8"] = uint8Type
uint16Type := &NType{
2021-09-02 15:25:39 +02:00
"uint16", ST_UINT16, 0, ST_COMMON, ST_UINT16, nil,
0, func() interface{} { return new(uint16) },
2021-09-02 00:08:59 +02:00
}
cacheTypes.ntypes[ST_UINT16] = uint16Type
cacheTypes.nnames["uint16"] = uint16Type
uint32Type := &NType{
2021-09-02 15:25:39 +02:00
"uint32", ST_UINT32, 0, ST_COMMON, ST_UINT32, nil,
0, func() interface{} { return new(uint32) },
2021-09-02 00:08:59 +02:00
}
cacheTypes.ntypes[ST_UINT32] = uint32Type
cacheTypes.nnames["uint32"] = uint32Type
uint64Type := &NType{
2021-09-02 15:25:39 +02:00
"uint64", ST_UINT64, 0, ST_COMMON, ST_UINT64, nil,
0, func() interface{} { return new(uint64) },
2021-09-02 00:08:59 +02:00
}
cacheTypes.ntypes[ST_UINT64] = uint64Type
cacheTypes.nnames["uint64"] = uint64Type
int8Type := &NType{
2021-09-02 15:25:39 +02:00
"int8", ST_INT8, 0, ST_COMMON, ST_INT8, nil,
0, func() interface{} { return new(int8) },
2021-09-02 00:08:59 +02:00
}
cacheTypes.ntypes[ST_INT8] = int8Type
cacheTypes.nnames["int8"] = int8Type
int16Type := &NType{
2021-09-02 15:25:39 +02:00
"int16", ST_INT16, 0, ST_COMMON, ST_INT16, nil,
0, func() interface{} { return new(int16) },
2021-09-02 00:08:59 +02:00
}
cacheTypes.ntypes[ST_INT16] = int16Type
cacheTypes.nnames["int16"] = int16Type
int32Type := &NType{
2021-09-02 15:25:39 +02:00
"int32", ST_INT32, 0, ST_COMMON, ST_INT32, nil,
0, func() interface{} { return new(int32) },
2021-09-02 00:08:59 +02:00
}
cacheTypes.ntypes[ST_INT32] = int32Type
cacheTypes.nnames["int32"] = int32Type
int64Type := &NType{
2021-09-02 15:25:39 +02:00
"int64", ST_INT64, 0, ST_COMMON, ST_INT64, nil,
0, func() interface{} { return new(int64) },
2021-09-02 00:08:59 +02:00
}
cacheTypes.ntypes[ST_INT64] = int64Type
cacheTypes.nnames["int64"] = int64Type
float32Type := &NType{
2021-09-02 15:25:39 +02:00
"float32", ST_FLOAT32, 0, ST_COMMON, ST_FLOAT32, nil,
0, func() interface{} { return new(float32) },
2021-09-02 00:08:59 +02:00
}
cacheTypes.ntypes[ST_FLOAT32] = float32Type
cacheTypes.nnames["float32"] = float32Type
float64Type := &NType{
2021-09-02 15:25:39 +02:00
"float64", ST_FLOAT64, 0, ST_COMMON, ST_FLOAT64, nil,
0, func() interface{} { return new(float64) },
2021-09-02 00:08:59 +02:00
}
cacheTypes.ntypes[ST_FLOAT64] = float64Type
cacheTypes.nnames["float64"] = float64Type
stringType := &NType{
2021-09-02 15:25:39 +02:00
"string", ST_STRING, 0, ST_COMMON, ST_STRING, nil,
0, func() interface{} { return new(string) },
2021-09-02 00:08:59 +02:00
}
cacheTypes.ntypes[ST_STRING] = stringType
cacheTypes.nnames["string"] = stringType
errorType := &NType{
2021-09-02 15:25:39 +02:00
"error", ST_ERROR, 0, ST_COMMON, ST_ERROR, nil,
0, func() interface{} { return new(error) },
2021-09-02 00:08:59 +02:00
}
cacheTypes.ntypes[ST_ERROR] = errorType
cacheTypes.nnames["error"] = errorType
2021-09-02 15:25:39 +02:00
nilType := &NType{
"nil", ST_NIL, 0, ST_NIL, ST_NIL, nil,
0, func() interface{} { return nil },
}
cacheTypes.ntypes[ST_NIL] = nilType
cacheTypes.nnames["nil"] = nilType
2021-10-21 11:46:02 +02:00
interfaceType := &NType{
"interface {}", ST_INTERFACE, 0, ST_INTERFACE, ST_INTERFACE, nil,
0, func() interface{} { return new(interface{}) },
}
cacheTypes.ntypes[ST_INTERFACE] = interfaceType
cacheTypes.nnames["interface {}"] = interfaceType
2021-09-02 00:08:59 +02:00
}
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
}
}
2021-09-02 15:25:39 +02:00
func parseType(t reflect.Type) (ret nallocFunc, mainTypeId uint32, indirection int, valType uint32, base bool, sfields []*StructField, arrayLen int, err error) {
2021-09-02 00:08:59 +02:00
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
}
}
2021-09-06 23:33:50 +02:00
//return vret
2021-09-02 00:08:59 +02:00
return vret.Interface()
}
sfields = []*StructField{}
2021-09-02 15:25:39 +02:00
arrayLen = 0
2021-09-02 00:08:59 +02:00
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
} else {
switch val.Kind() {
case reflect.Slice:
typ := reflect.TypeOf(val.Interface())
vt, err := getTypeByNameRegister(typ.Elem().String(), typ.Elem())
if err != nil {
2021-09-07 16:05:04 +02:00
return ret, mainTypeId, indirection, valType, base, sfields, arrayLen, err
2021-09-02 00:08:59 +02:00
}
2021-09-02 15:25:39 +02:00
valType = vt.Id
2021-09-02 00:08:59 +02:00
base = false
mainTypeId = ST_SLICE
case reflect.Array:
typ := reflect.TypeOf(val.Interface())
2021-09-02 15:25:39 +02:00
arrayLen = val.Len()
2021-09-02 00:08:59 +02:00
vt, err := getTypeByNameRegister(typ.Elem().String(), typ.Elem())
if err != nil {
2021-09-07 16:05:04 +02:00
return ret, mainTypeId, indirection, valType, base, sfields, arrayLen, err
2021-09-02 00:08:59 +02:00
}
2021-09-02 15:25:39 +02:00
valType = vt.Id
2021-09-02 00:08:59 +02:00
base = false
mainTypeId = ST_ARRAY
case reflect.Struct:
typ := reflect.TypeOf(val.Interface())
if !base {
vt, err := getTypeByNameRegister(typ.String(), typ)
if err != nil {
2021-09-07 16:05:04 +02:00
return ret, mainTypeId, indirection, valType, base, sfields, arrayLen, err
2021-09-02 00:08:59 +02:00
}
2021-09-02 15:25:39 +02:00
valType = vt.Id
2021-09-02 00:08:59 +02:00
} else {
sl := val.NumField()
for i := 0; i < sl; i++ {
if val.Field(i).CanSet() {
sfield := new(StructField)
sfield.Name = val.Type().Field(i).Name
sfield.Tag = string(val.Type().Field(i).Tag)
2021-10-21 11:46:02 +02:00
slog.LOG_DEBUGFLN("ts: %v", val.Field(i).Type().String())
slog.LOG_DEBUGFLN("tt: %v", val.Field(i).Type())
2021-09-02 00:08:59 +02:00
vt, err := getTypeByNameRegister(val.Field(i).Type().String(), val.Field(i).Type())
if err != nil {
2021-09-07 16:05:04 +02:00
return ret, mainTypeId, indirection, valType, base, sfields, arrayLen, err
2021-09-02 00:08:59 +02:00
}
2021-09-02 15:25:39 +02:00
sfield.Id = vt.Id
2021-09-07 16:05:04 +02:00
sfield.SId = i
2021-09-02 15:25:39 +02:00
sfields = append(sfields, sfield)
2021-09-02 00:08:59 +02:00
}
}
2021-09-06 23:33:50 +02:00
base = true
2021-09-02 00:08:59 +02:00
}
mainTypeId = ST_STRUCT
case reflect.Map:
typ := reflect.TypeOf(val.Interface())
if !base {
vt, err := getTypeByNameRegister(typ.String(), typ)
if err != nil {
2021-09-07 16:05:04 +02:00
return ret, mainTypeId, indirection, valType, base, sfields, arrayLen, err
2021-09-02 00:08:59 +02:00
}
2021-09-02 15:25:39 +02:00
valType = vt.Id
2021-09-02 00:08:59 +02:00
} else {
// Key
vt, err := getTypeByNameRegister(typ.Key().String(), typ.Key())
if err != nil {
2021-09-07 16:05:04 +02:00
return ret, mainTypeId, indirection, valType, base, sfields, arrayLen, err
2021-09-02 00:08:59 +02:00
}
2021-09-02 15:25:39 +02:00
valType = vt.Id
2021-09-02 00:08:59 +02:00
// Val
vt, err = getTypeByNameRegister(typ.Elem().String(), typ.Elem())
if err != nil {
2021-09-07 16:05:04 +02:00
return ret, mainTypeId, indirection, valType, base, sfields, arrayLen, err
2021-09-02 00:08:59 +02:00
}
2021-09-02 15:25:39 +02:00
valType = vt.Id
2021-09-02 00:08:59 +02:00
base = false
}
mainTypeId = ST_MAP
default:
typ := reflect.TypeOf(val.Interface())
if !base {
vt, err := getTypeByNameRegister(typ.Kind().String(), typ)
if err != nil {
2021-09-07 16:05:04 +02:00
return ret, mainTypeId, indirection, valType, base, sfields, arrayLen, err
2021-09-02 00:08:59 +02:00
}
2021-09-02 15:25:39 +02:00
valType = vt.Id
2021-09-02 00:08:59 +02:00
}
mainTypeId = ST_COMMON
}
break
}
}
2021-09-02 15:25:39 +02:00
return ret, mainTypeId, indirection, valType, base, sfields, arrayLen, err
2021-09-02 00:08:59 +02:00
}
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()
2021-09-02 15:25:39 +02:00
ret.alloc, ret.MainTypeId, ret.Indirection, ret.ValType, base, ret.structFields, ret.arrayLen, err = parseType(t)
2021-09-02 00:08:59 +02:00
return ret, base, err
}
func registerType(t reflect.Type) (err error) {
if t == nil || t.Kind() == reflect.Invalid {
2021-09-07 16:05:04 +02:00
return ErrTypeInvalid
2021-09-02 00:08:59 +02:00
}
if getTypeByName(t.String()) != nil {
return nil
}
var base bool
ntype, base, err := createType(t)
if err != nil {
2021-09-07 16:05:04 +02:00
return err
2021-09-02 00:08:59 +02:00
}
ntype.Id = cacheTypes.NextId
if base {
2021-09-02 15:25:39 +02:00
ntype.ValType = ntype.Id
2021-09-02 00:08:59 +02:00
}
cacheTypes.ntypes[ntype.Id] = ntype
cacheTypes.nnames[ntype.Name] = ntype
cacheTypes.NextId += 1
return err
}
2021-09-02 15:25:39 +02:00
func splitType(e interface{}) (t reflect.Type, v reflect.Value, err error) {
t = reflect.TypeOf(e)
if t == nil || t.Kind() != reflect.Ptr {
2021-09-07 16:05:04 +02:00
return t, v, ErrTypeInvalid
2021-09-02 15:25:39 +02:00
}
v = reflect.ValueOf(e)
if v.IsNil() {
2021-09-07 16:05:04 +02:00
return t, v, ErrValueInvalid
2021-09-02 15:25:39 +02:00
}
return t, v, err
}
func indirectType(e interface{}) (ret interface{}, ntype *NType, nilLevel uint16, err error) {
nilLevel = 0
t, v, err := splitType(e)
if err != nil {
return nil, nil, nilLevel, err
}
ntype, err = getTypeByNameRegister(t.Elem().String(), t.Elem())
if err != nil {
return nil, nil, nilLevel, err
}
for i := 0; i < ntype.Indirection; i++ {
2021-09-07 16:05:04 +02:00
if v, err = indirectValue(v); err != nil {
return nil, ntype, nilLevel, ErrValueInvalid
}
if v.IsValid() && v.IsNil() {
2021-09-02 15:25:39 +02:00
nilLevel += uint16(i)
return nil, ntype, nilLevel, err
}
}
2021-09-07 16:05:04 +02:00
if v, err = indirectValue(v); err != nil {
return nil, ntype, nilLevel, err
}
return v.Interface(), ntype, nilLevel, err
2021-09-02 15:25:39 +02:00
}
2021-09-06 23:33:50 +02:00
func setTypeNil(e interface{}, indirection int) (err error) {
2021-09-07 16:05:04 +02:00
var v reflect.Value
2021-09-06 23:33:50 +02:00
2021-09-07 16:05:04 +02:00
if v, err = getValPtr(e); err != nil {
return err
2021-09-06 23:33:50 +02:00
}
2021-09-07 16:05:04 +02:00
if v, err = indirectValue(v); err != nil {
if indirection > 0 {
return ErrValueInvalid
}
2021-09-06 23:33:50 +02:00
}
for i := 0; i < indirection; i++ {
2021-09-07 16:05:04 +02:00
if v, err = indirectValue(v); err != nil {
return err
2021-09-06 23:33:50 +02:00
}
}
2021-09-07 16:05:04 +02:00
if v.IsValid() && !v.IsNil() {
2021-09-06 23:33:50 +02:00
v.Set(reflect.Zero(reflect.TypeOf(v.Interface())))
}
return err
}
func setTypeVal(e interface{}, val interface{}, ntype *NType) (err error) {
2021-09-07 16:05:04 +02:00
var v reflect.Value
2021-09-06 23:33:50 +02:00
2021-09-07 16:05:04 +02:00
if v, err = getValPtr(e); err != nil {
return err
}
if v, err = indirectValue(v); err != nil {
return err
2021-09-06 23:33:50 +02:00
}
for i := 0; i < ntype.Indirection; i++ {
2021-09-07 16:05:04 +02:00
if v, err = indirectValue(v); err != nil {
return err
2021-09-06 23:33:50 +02:00
}
}
v.Set(reflect.ValueOf(val))
return err
}
2021-09-07 16:05:04 +02:00
func getValPtr(e interface{}) (ret reflect.Value, err error) {
v := reflect.ValueOf(e)
if !v.IsValid() || v.Kind() != reflect.Ptr || v.IsNil() {
err = ErrValueInvalid
}
return v, err
}
2021-09-06 23:33:50 +02:00
func getVal(e interface{}) (ret reflect.Value) {
v := reflect.ValueOf(e)
2021-09-07 16:05:04 +02:00
if !v.IsValid() || v.Kind() != reflect.Ptr || v.IsNil() {
2021-09-06 23:33:50 +02:00
return v
}
return reflect.Indirect(v)
}
2021-09-07 16:05:04 +02:00
func indirectValue(v reflect.Value) (ret reflect.Value, err error) {
if !v.IsValid() || v.Kind() != reflect.Ptr {
return v, ErrValueInvalid
}
ret = reflect.Indirect(v)
return ret, err
}
func valueIsNil(v reflect.Value) (ret bool) {
ret = false
if !v.IsValid() || v.Kind() == reflect.Invalid || (v.Kind() == reflect.Ptr && v.IsNil()) {
ret = true
}
return ret
}
2021-09-08 13:27:39 +02:00
func traverseValuePtr(v reflect.Value) (ret reflect.Value) {
ret = v
if !ret.IsValid() || ret.Kind() != reflect.Ptr {
return ret
} else {
ret = reflect.Indirect(ret)
return traverseValuePtr(ret)
}
}
func parseInterface(e interface{}) (rett reflect.Type, retv reflect.Value, err error) {
2021-09-02 00:08:59 +02:00
t := reflect.TypeOf(e)
2021-09-08 13:27:39 +02:00
if t == nil || t.Kind() != reflect.Ptr {
return nil, reflect.ValueOf(e), ErrTypeInvalid
}
if t.Elem().Kind() == reflect.Interface {
rett = reflect.TypeOf(reflect.Indirect(reflect.ValueOf(e)).Interface())
retv = reflect.New(rett)
retv.Elem().Set(reflect.ValueOf(reflect.Indirect(reflect.ValueOf(e)).Interface()))
2021-10-21 11:46:02 +02:00
slog.LOG_DEBUGFLN("rett: %v", rett)
slog.LOG_DEBUGFLN("retv: %v", retv)
2021-09-08 13:27:39 +02:00
return rett, retv, nil
}
2021-10-21 11:46:02 +02:00
slog.LOG_DEBUGFLN("t: %v", t)
slog.LOG_DEBUGFLN("v: %v", reflect.ValueOf(e))
2021-09-08 13:27:39 +02:00
return t, reflect.ValueOf(e), nil
}
func RegisterType(e interface{}) (err error) {
//t := reflect.TypeOf(e)
t, _, err := parseInterface(e)
if err != nil {
return err
}
2021-09-02 15:25:39 +02:00
if t == nil || t.Kind() != reflect.Ptr {
return fmt.Errorf("ssob: Interface is not a valid address: %w", ErrTypeInvalid)
}
if err = registerType(t.Elem()); err != nil {
return err
}
2021-09-06 23:33:50 +02:00
return nil
2021-09-02 00:08:59 +02:00
}