|
|
|
@ -1,16 +1,17 @@
|
|
|
|
|
package graphvent
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"crypto/ecdh"
|
|
|
|
|
"crypto/sha512"
|
|
|
|
|
"encoding/binary"
|
|
|
|
|
"errors"
|
|
|
|
|
"fmt"
|
|
|
|
|
"reflect"
|
|
|
|
|
"runtime"
|
|
|
|
|
"sync"
|
|
|
|
|
|
|
|
|
|
badger "github.com/dgraph-io/badger/v3"
|
|
|
|
|
"crypto/ecdh"
|
|
|
|
|
"crypto/sha512"
|
|
|
|
|
"encoding/binary"
|
|
|
|
|
"errors"
|
|
|
|
|
"fmt"
|
|
|
|
|
"reflect"
|
|
|
|
|
"runtime"
|
|
|
|
|
"sync"
|
|
|
|
|
"strconv"
|
|
|
|
|
|
|
|
|
|
badger "github.com/dgraph-io/badger/v3"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
func Hash(base string, name string) uint64 {
|
|
|
|
@ -49,6 +50,7 @@ func NewSerializedType(name string) SerializedType {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const (
|
|
|
|
|
TagBase = "GraphventTag"
|
|
|
|
|
ExtTypeBase = "ExtType"
|
|
|
|
|
NodeTypeBase = "NodeType"
|
|
|
|
|
SignalTypeBase = "SignalType"
|
|
|
|
@ -91,7 +93,10 @@ var (
|
|
|
|
|
ExtensionType = NewSerializedType("extension")
|
|
|
|
|
|
|
|
|
|
StringType = NewSerializedType("string")
|
|
|
|
|
IntType = NewSerializedType("int")
|
|
|
|
|
Uint8Type = NewSerializedType("uint8")
|
|
|
|
|
Uint32Type = NewSerializedType("uint32")
|
|
|
|
|
Uint64Type = NewSerializedType("uint64")
|
|
|
|
|
NodeKeyType = NewSerializedType("node_key")
|
|
|
|
|
|
|
|
|
|
NodeNotFoundError = errors.New("Node not found in DB")
|
|
|
|
@ -107,8 +112,8 @@ type NodeInfo struct {
|
|
|
|
|
Extensions []ExtType
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type TypeSerialize func(*Context,interface{}) ([]byte, error)
|
|
|
|
|
type TypeDeserialize func(*Context,[]byte) (interface{}, error)
|
|
|
|
|
type TypeSerialize func(*Context,uint64,reflect.Type,*reflect.Value) (SerializedValue, error)
|
|
|
|
|
type TypeDeserialize func(*Context,SerializedValue) (interface{}, []byte, error)
|
|
|
|
|
type TypeInfo struct {
|
|
|
|
|
Type reflect.Type
|
|
|
|
|
Serialize TypeSerialize
|
|
|
|
@ -136,6 +141,9 @@ type Context struct {
|
|
|
|
|
Types map[SerializedType]TypeInfo
|
|
|
|
|
TypeReflects map[reflect.Type]SerializedType
|
|
|
|
|
|
|
|
|
|
Kinds map[reflect.Kind]KindInfo
|
|
|
|
|
KindTypes map[SerializedType]reflect.Kind
|
|
|
|
|
|
|
|
|
|
// Routing map to all the nodes local to this context
|
|
|
|
|
nodeMapLock sync.RWMutex
|
|
|
|
|
nodeMap map[NodeID]*Node
|
|
|
|
@ -207,6 +215,32 @@ func (ctx *Context)RegisterExtension(reflect_type reflect.Type, ext_type ExtType
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (ctx *Context)RegisterKind(kind reflect.Kind, ctx_type SerializedType, serialize TypeSerialize, deserialize TypeDeserialize) error {
|
|
|
|
|
_, exists := ctx.Kinds[kind]
|
|
|
|
|
if exists == true {
|
|
|
|
|
return fmt.Errorf("Cannot register kind %+v, kind already exists in context", kind)
|
|
|
|
|
}
|
|
|
|
|
_, exists = ctx.KindTypes[ctx_type]
|
|
|
|
|
if exists == true {
|
|
|
|
|
return fmt.Errorf("0x%x is already registered, cannot use for %+v", ctx_type, kind)
|
|
|
|
|
}
|
|
|
|
|
if deserialize == nil {
|
|
|
|
|
return fmt.Errorf("Cannot register field without deserialize function")
|
|
|
|
|
}
|
|
|
|
|
if serialize == nil {
|
|
|
|
|
return fmt.Errorf("Cannot register field without serialize function")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ctx.Kinds[kind] = KindInfo{
|
|
|
|
|
ctx_type,
|
|
|
|
|
serialize,
|
|
|
|
|
deserialize,
|
|
|
|
|
}
|
|
|
|
|
ctx.KindTypes[ctx_type] = kind
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (ctx *Context)RegisterType(reflect_type reflect.Type, ctx_type SerializedType, serialize TypeSerialize, deserialize TypeDeserialize) error {
|
|
|
|
|
_, exists := ctx.Types[ctx_type]
|
|
|
|
|
if exists == true {
|
|
|
|
@ -287,31 +321,10 @@ func (ctx *Context) Send(messages Messages) error {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type defaultKind struct {
|
|
|
|
|
type KindInfo struct {
|
|
|
|
|
Type SerializedType
|
|
|
|
|
Serialize func(interface{})([]byte, error)
|
|
|
|
|
Deserialize func([]byte)(interface{}, error)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var defaultKinds = map[reflect.Kind]defaultKind{
|
|
|
|
|
reflect.Int: {
|
|
|
|
|
Deserialize: func(data []byte)(interface{}, error){
|
|
|
|
|
if len(data) != 8 {
|
|
|
|
|
return nil, fmt.Errorf("invalid length: %d/8", len(data))
|
|
|
|
|
}
|
|
|
|
|
return int(binary.BigEndian.Uint64(data)), nil
|
|
|
|
|
},
|
|
|
|
|
Serialize: func(val interface{})([]byte, error){
|
|
|
|
|
i, ok := val.(int)
|
|
|
|
|
if ok == false {
|
|
|
|
|
return nil, fmt.Errorf("invalid type %+v", reflect.TypeOf(val))
|
|
|
|
|
} else {
|
|
|
|
|
bytes := make([]byte, 8)
|
|
|
|
|
binary.BigEndian.PutUint64(bytes, uint64(i))
|
|
|
|
|
return bytes, nil
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
Serialize TypeSerialize
|
|
|
|
|
Deserialize TypeDeserialize
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type SerializedValue struct {
|
|
|
|
@ -321,33 +334,364 @@ type SerializedValue struct {
|
|
|
|
|
|
|
|
|
|
func SerializeValue(ctx *Context, value reflect.Value) (SerializedValue, error) {
|
|
|
|
|
val, err := serializeValue(ctx, value.Type(), &value)
|
|
|
|
|
ctx.Log.Logf("serialize", "SERIALIZED_VALUE(%+v): %+v - %s", value, val, err)
|
|
|
|
|
ctx.Log.Logf("serialize", "SERIALIZED_VALUE(%+v): %+v - %+v", value.Type(), val.TypeStack, val.Data)
|
|
|
|
|
return val, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func serializeValue(ctx *Context, t reflect.Type, value *reflect.Value) (SerializedValue, error) {
|
|
|
|
|
var ctx_type uint64 = 0x00
|
|
|
|
|
ctype, exists := ctx.TypeReflects[t]
|
|
|
|
|
ctx.Log.Logf("serialize", "TYPE_REFLECTS: %+v", ctx.TypeReflects)
|
|
|
|
|
if exists == true {
|
|
|
|
|
type_info := ctx.Types[ctype]
|
|
|
|
|
ctx_type = uint64(ctype)
|
|
|
|
|
val_ser, err := type_info.Serialize(ctx, value.Interface())
|
|
|
|
|
if type_info.Serialize != nil {
|
|
|
|
|
return type_info.Serialize(ctx, ctx_type, t, value)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
kind := t.Kind()
|
|
|
|
|
kind_info, handled := ctx.Kinds[kind]
|
|
|
|
|
if handled == false {
|
|
|
|
|
return SerializedValue{}, fmt.Errorf("Don't know how to serialize kind %+v", kind)
|
|
|
|
|
} else if ctx_type == 0x00 {
|
|
|
|
|
ctx_type = uint64(kind_info.Type)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return kind_info.Serialize(ctx, ctx_type, t, value)
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func SerializeField(ctx *Context, ext Extension, field_name string) (SerializedValue, error) {
|
|
|
|
|
if ext == nil {
|
|
|
|
|
return SerializedValue{}, fmt.Errorf("Cannot get fields on nil Extension")
|
|
|
|
|
}
|
|
|
|
|
ext_value := reflect.ValueOf(ext).Elem()
|
|
|
|
|
field := ext_value.FieldByName(field_name)
|
|
|
|
|
if field.IsValid() == false {
|
|
|
|
|
return SerializedValue{}, fmt.Errorf("%s is not a field in %+v", field_name, ext)
|
|
|
|
|
} else {
|
|
|
|
|
return SerializeValue(ctx, field)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (value SerializedValue) MarshalBinary() ([]byte, error) {
|
|
|
|
|
data := make([]byte, value.SerializedSize())
|
|
|
|
|
binary.BigEndian.PutUint64(data[0:8], uint64(len(value.TypeStack)))
|
|
|
|
|
binary.BigEndian.PutUint64(data[8:16], uint64(len(value.Data)))
|
|
|
|
|
|
|
|
|
|
for i, t := range(value.TypeStack) {
|
|
|
|
|
type_start := (i+2)*8
|
|
|
|
|
type_end := (i+3)*8
|
|
|
|
|
binary.BigEndian.PutUint64(data[type_start:type_end], t)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return append(data, value.Data...), nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (value SerializedValue) SerializedSize() uint64 {
|
|
|
|
|
return uint64((len(value.TypeStack) + 2) * 8)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func ParseSerializedValue(ctx *Context, data []byte) (SerializedValue, error) {
|
|
|
|
|
if len(data) < 8 {
|
|
|
|
|
return SerializedValue{}, fmt.Errorf("SerializedValue required to have at least 8 bytes when serialized")
|
|
|
|
|
}
|
|
|
|
|
num_types := int(binary.BigEndian.Uint64(data[0:8]))
|
|
|
|
|
data_size := int(binary.BigEndian.Uint64(data[8:16]))
|
|
|
|
|
type_stack := make([]uint64, num_types)
|
|
|
|
|
for i := 0; i < num_types; i += 1 {
|
|
|
|
|
type_start := (i+2) * 8
|
|
|
|
|
type_end := (i+3) * 8
|
|
|
|
|
type_stack[i] = binary.BigEndian.Uint64(data[type_start:type_end])
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
types_end := 8*(num_types + 1)
|
|
|
|
|
return SerializedValue{
|
|
|
|
|
type_stack,
|
|
|
|
|
data[types_end:(types_end+data_size)],
|
|
|
|
|
}, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func DeserializeValue(ctx *Context, value SerializedValue, n int) ([]interface{}, []byte, error) {
|
|
|
|
|
ret := make([]interface{}, n)
|
|
|
|
|
|
|
|
|
|
var deserialize TypeDeserialize = nil
|
|
|
|
|
|
|
|
|
|
ctx_type := value.TypeStack[0]
|
|
|
|
|
type_info, exists := ctx.Types[SerializedType(ctx_type)]
|
|
|
|
|
if exists == true {
|
|
|
|
|
deserialize = type_info.Deserialize
|
|
|
|
|
} else {
|
|
|
|
|
kind, exists := ctx.KindTypes[SerializedType(ctx_type)]
|
|
|
|
|
if exists == false {
|
|
|
|
|
return nil, nil, fmt.Errorf("Cannot deserialize 0x%x: unknown type/kind", ctx_type)
|
|
|
|
|
}
|
|
|
|
|
kind_info := ctx.Kinds[kind]
|
|
|
|
|
deserialize = kind_info.Deserialize
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
remaining_data := value.Data
|
|
|
|
|
for i := 0; i < n; i += 1 {
|
|
|
|
|
var elem interface{} = nil
|
|
|
|
|
var err error = nil
|
|
|
|
|
elem, remaining_data, err = deserialize(ctx, value)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, nil, err
|
|
|
|
|
}
|
|
|
|
|
if len(remaining_data) == 0 {
|
|
|
|
|
remaining_data = nil
|
|
|
|
|
}
|
|
|
|
|
ret[i] = elem
|
|
|
|
|
}
|
|
|
|
|
return ret, remaining_data, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Create a new Context with the base library content added
|
|
|
|
|
func NewContext(db * badger.DB, log Logger) (*Context, error) {
|
|
|
|
|
ctx := &Context{
|
|
|
|
|
DB: db,
|
|
|
|
|
Log: log,
|
|
|
|
|
Policies: map[PolicyType]reflect.Type{},
|
|
|
|
|
PolicyTypes: map[reflect.Type]PolicyType{},
|
|
|
|
|
Extensions: map[ExtType]ExtensionInfo{},
|
|
|
|
|
ExtensionTypes: map[reflect.Type]ExtType{},
|
|
|
|
|
Signals: map[SignalType]reflect.Type{},
|
|
|
|
|
SignalTypes: map[reflect.Type]SignalType{},
|
|
|
|
|
Nodes: map[NodeType]NodeInfo{},
|
|
|
|
|
nodeMap: map[NodeID]*Node{},
|
|
|
|
|
Types: map[SerializedType]TypeInfo{},
|
|
|
|
|
TypeReflects: map[reflect.Type]SerializedType{},
|
|
|
|
|
Kinds: map[reflect.Kind]KindInfo{},
|
|
|
|
|
KindTypes: map[SerializedType]reflect.Kind{},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var err error
|
|
|
|
|
err = ctx.RegisterKind(reflect.Pointer, NewSerializedType("pointer"),
|
|
|
|
|
func(ctx *Context, ctx_type uint64, reflect_type reflect.Type, value *reflect.Value) (SerializedValue, error) {
|
|
|
|
|
var data []byte
|
|
|
|
|
var elem_value *reflect.Value = nil
|
|
|
|
|
if value == nil {
|
|
|
|
|
data = nil
|
|
|
|
|
} else if value.IsZero() {
|
|
|
|
|
data = []byte{0x01}
|
|
|
|
|
} else {
|
|
|
|
|
data = []byte{0x00}
|
|
|
|
|
ev := value.Elem()
|
|
|
|
|
elem_value = &ev
|
|
|
|
|
}
|
|
|
|
|
elem, err := serializeValue(ctx, reflect_type.Elem(), elem_value)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return SerializedValue{}, err
|
|
|
|
|
}
|
|
|
|
|
if elem.Data != nil {
|
|
|
|
|
data = append(data, elem.Data...)
|
|
|
|
|
}
|
|
|
|
|
return SerializedValue{
|
|
|
|
|
append([]uint64{ctx_type}, elem.TypeStack...),
|
|
|
|
|
data,
|
|
|
|
|
}, nil
|
|
|
|
|
}, func(ctx *Context, value SerializedValue) (interface{}, []byte, error) {
|
|
|
|
|
return nil, nil, fmt.Errorf("deserialize pointer unimplemented")
|
|
|
|
|
})
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
err = ctx.RegisterKind(reflect.Struct, NewSerializedType("struct"),
|
|
|
|
|
func(ctx *Context, ctx_type uint64, reflect_type reflect.Type, value *reflect.Value)(SerializedValue, error){
|
|
|
|
|
var m map[int][]byte = nil
|
|
|
|
|
if value != nil {
|
|
|
|
|
m = map[int][]byte{}
|
|
|
|
|
}
|
|
|
|
|
num_fields := 0
|
|
|
|
|
for _, field := range(reflect.VisibleFields(reflect_type)) {
|
|
|
|
|
gv_tag, tagged_gv := field.Tag.Lookup("gv")
|
|
|
|
|
if tagged_gv == false {
|
|
|
|
|
continue
|
|
|
|
|
} else if gv_tag == "" {
|
|
|
|
|
continue
|
|
|
|
|
} else if m != nil {
|
|
|
|
|
field_index, err := strconv.Atoi(gv_tag)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return SerializedValue{}, err
|
|
|
|
|
}
|
|
|
|
|
num_fields += 1
|
|
|
|
|
|
|
|
|
|
field_value := value.FieldByIndex(field.Index)
|
|
|
|
|
field_ser, err := serializeValue(ctx, field.Type, &field_value)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return SerializedValue{}, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m[field_index], err = field_ser.MarshalBinary()
|
|
|
|
|
if err != nil {
|
|
|
|
|
return SerializedValue{}, nil
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
field_list := make([][]byte, num_fields)
|
|
|
|
|
for i := range(field_list) {
|
|
|
|
|
var exists bool = false
|
|
|
|
|
field_list[i], exists = m[i]
|
|
|
|
|
if exists == false {
|
|
|
|
|
return SerializedValue{}, fmt.Errorf("%+v missing gv:%d", reflect_type, i)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
list_value := reflect.ValueOf(field_list)
|
|
|
|
|
list_serial, err := serializeValue(ctx, list_value.Type(), &list_value)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return SerializedValue{}, err
|
|
|
|
|
}
|
|
|
|
|
return SerializedValue{
|
|
|
|
|
[]uint64{ctx_type},
|
|
|
|
|
val_ser,
|
|
|
|
|
list_serial.Data,
|
|
|
|
|
}, nil
|
|
|
|
|
}, func(ctx *Context, value SerializedValue)(interface{}, []byte, error){
|
|
|
|
|
return nil, nil, fmt.Errorf("deserialize struct not implemented")
|
|
|
|
|
})
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
kind := t.Kind()
|
|
|
|
|
switch kind {
|
|
|
|
|
case reflect.Map:
|
|
|
|
|
if ctx_type == 0x00 {
|
|
|
|
|
ctx_type = uint64(MapType)
|
|
|
|
|
err = ctx.RegisterKind(reflect.Int, NewSerializedType("int"),
|
|
|
|
|
func(ctx *Context, ctx_type uint64, reflect_type reflect.Type, value *reflect.Value)(SerializedValue, error){
|
|
|
|
|
var data []byte = nil
|
|
|
|
|
if value != nil {
|
|
|
|
|
data = make([]byte, 8)
|
|
|
|
|
binary.BigEndian.PutUint64(data, value.Uint())
|
|
|
|
|
}
|
|
|
|
|
return SerializedValue{
|
|
|
|
|
[]uint64{ctx_type},
|
|
|
|
|
data,
|
|
|
|
|
}, nil
|
|
|
|
|
}, func(ctx *Context, value SerializedValue)(interface{}, []byte, error){
|
|
|
|
|
if len(value.Data) < 8 {
|
|
|
|
|
return reflect.Value{}, nil, fmt.Errorf("invalid length: %d/8", len(value.Data))
|
|
|
|
|
}
|
|
|
|
|
remaining_data := value.Data[8:]
|
|
|
|
|
if len(remaining_data) == 0 {
|
|
|
|
|
remaining_data = nil
|
|
|
|
|
}
|
|
|
|
|
return int(binary.BigEndian.Uint64(value.Data[0:8])), remaining_data, nil
|
|
|
|
|
})
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
err = ctx.RegisterKind(reflect.Uint32, NewSerializedType("uint32"),
|
|
|
|
|
func(ctx *Context, ctx_type uint64, reflect_type reflect.Type, value *reflect.Value)(SerializedValue, error){
|
|
|
|
|
data := make([]byte, 4)
|
|
|
|
|
if value != nil {
|
|
|
|
|
binary.BigEndian.PutUint32(data, uint32(value.Uint()))
|
|
|
|
|
}
|
|
|
|
|
return SerializedValue{
|
|
|
|
|
[]uint64{ctx_type},
|
|
|
|
|
data,
|
|
|
|
|
}, nil
|
|
|
|
|
}, func(ctx *Context, value SerializedValue)(interface{}, []byte, error){
|
|
|
|
|
return nil, nil, fmt.Errorf("deserialize uint32 unimplemented")
|
|
|
|
|
})
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
err = ctx.RegisterKind(reflect.String, NewSerializedType("string"),
|
|
|
|
|
func(ctx *Context, ctx_type uint64, reflect_type reflect.Type, value *reflect.Value)(SerializedValue, error){
|
|
|
|
|
if value == nil {
|
|
|
|
|
return SerializedValue{
|
|
|
|
|
[]uint64{ctx_type},
|
|
|
|
|
nil,
|
|
|
|
|
}, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
data := make([]byte, 8)
|
|
|
|
|
str := value.String()
|
|
|
|
|
binary.BigEndian.PutUint64(data, uint64(len(str)))
|
|
|
|
|
return SerializedValue{
|
|
|
|
|
[]uint64{uint64(ctx_type)},
|
|
|
|
|
append(data, []byte(str)...),
|
|
|
|
|
}, nil
|
|
|
|
|
}, func(ctx *Context, value SerializedValue)(interface{}, []byte, error){
|
|
|
|
|
return nil, nil, fmt.Errorf("deserialize string unimplemented")
|
|
|
|
|
})
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
err = ctx.RegisterKind(reflect.Array, NewSerializedType("array"),
|
|
|
|
|
func(ctx *Context, ctx_type uint64, reflect_type reflect.Type, value *reflect.Value)(SerializedValue, error){
|
|
|
|
|
var data []byte
|
|
|
|
|
if value == nil {
|
|
|
|
|
data = nil
|
|
|
|
|
} else if value.Len() == 0 {
|
|
|
|
|
data = []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
|
|
|
|
|
} else {
|
|
|
|
|
data := make([]byte, 8)
|
|
|
|
|
binary.BigEndian.PutUint64(data, uint64(value.Len()))
|
|
|
|
|
|
|
|
|
|
var type_stack []uint64 = nil
|
|
|
|
|
for i := 0; i < value.Len(); i += 1 {
|
|
|
|
|
val := value.Index(i)
|
|
|
|
|
element, err := serializeValue(ctx, reflect_type.Elem(), &val)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return SerializedValue{}, err
|
|
|
|
|
}
|
|
|
|
|
if type_stack == nil {
|
|
|
|
|
type_stack = append([]uint64{ctx_type}, element.TypeStack...)
|
|
|
|
|
}
|
|
|
|
|
data = append(data, element.Data...)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
elem, err := serializeValue(ctx, reflect_type.Elem(), nil)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return SerializedValue{}, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return SerializedValue{
|
|
|
|
|
append([]uint64{ctx_type}, elem.TypeStack...),
|
|
|
|
|
data,
|
|
|
|
|
}, nil
|
|
|
|
|
}, func(ctx *Context, value SerializedValue)(interface{}, []byte, error){
|
|
|
|
|
return nil, nil, fmt.Errorf("deserialize array unimplemented")
|
|
|
|
|
})
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
err = ctx.RegisterKind(reflect.Interface, NewSerializedType("interface"),
|
|
|
|
|
func(ctx *Context, ctx_type uint64, reflect_type reflect.Type, value *reflect.Value)(SerializedValue, error){
|
|
|
|
|
var data []byte
|
|
|
|
|
type_stack := []uint64{}
|
|
|
|
|
if value == nil {
|
|
|
|
|
data = nil
|
|
|
|
|
} else if value.IsZero() {
|
|
|
|
|
return SerializedValue{}, fmt.Errorf("Cannot serialize nil interfaces")
|
|
|
|
|
} else {
|
|
|
|
|
elem_value := value.Elem()
|
|
|
|
|
elem, err := serializeValue(ctx, value.Elem().Type(), &elem_value)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return SerializedValue{}, err
|
|
|
|
|
}
|
|
|
|
|
data = elem.Data
|
|
|
|
|
type_stack = elem.TypeStack
|
|
|
|
|
}
|
|
|
|
|
return SerializedValue{
|
|
|
|
|
append([]uint64{ctx_type}, type_stack...),
|
|
|
|
|
data,
|
|
|
|
|
}, nil
|
|
|
|
|
}, func(ctx *Context, value SerializedValue)(interface{}, []byte, error){
|
|
|
|
|
return nil, nil, fmt.Errorf("deserialize interface unimplemented")
|
|
|
|
|
})
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
err = ctx.RegisterKind(reflect.Map, NewSerializedType("map"),
|
|
|
|
|
func(ctx *Context, ctx_type uint64, reflect_type reflect.Type, value *reflect.Value)(SerializedValue, error){
|
|
|
|
|
var data []byte
|
|
|
|
|
if value == nil {
|
|
|
|
|
data = nil
|
|
|
|
@ -367,11 +711,11 @@ func serializeValue(ctx *Context, t reflect.Type, value *reflect.Value) (Seriali
|
|
|
|
|
key_value := map_iter.Key()
|
|
|
|
|
val_value := map_iter.Value()
|
|
|
|
|
|
|
|
|
|
key, err := serializeValue(ctx, t.Key(), &key_value)
|
|
|
|
|
key, err := serializeValue(ctx, reflect_type.Key(), &key_value)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return SerializedValue{}, err
|
|
|
|
|
}
|
|
|
|
|
val, err := serializeValue(ctx, t.Elem(), &val_value)
|
|
|
|
|
val, err := serializeValue(ctx, reflect_type.Elem(), &val_value)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return SerializedValue{}, err
|
|
|
|
|
}
|
|
|
|
@ -398,11 +742,11 @@ func serializeValue(ctx *Context, t reflect.Type, value *reflect.Value) (Seriali
|
|
|
|
|
data,
|
|
|
|
|
}, nil
|
|
|
|
|
}
|
|
|
|
|
key, err := serializeValue(ctx, t.Key(), nil)
|
|
|
|
|
key, err := serializeValue(ctx, reflect_type.Key(), nil)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return SerializedValue{}, err
|
|
|
|
|
}
|
|
|
|
|
elem, err := serializeValue(ctx, t.Elem(), nil)
|
|
|
|
|
elem, err := serializeValue(ctx, reflect_type.Elem(), nil)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return SerializedValue{}, err
|
|
|
|
|
}
|
|
|
|
@ -413,10 +757,51 @@ func serializeValue(ctx *Context, t reflect.Type, value *reflect.Value) (Seriali
|
|
|
|
|
type_stack,
|
|
|
|
|
data,
|
|
|
|
|
}, nil
|
|
|
|
|
case reflect.Slice:
|
|
|
|
|
if ctx_type == 0x00 {
|
|
|
|
|
ctx_type = uint64(SliceType)
|
|
|
|
|
}, func(ctx *Context, value SerializedValue)(interface{}, []byte, error){
|
|
|
|
|
return nil, nil, fmt.Errorf("deserialize map unimplemented")
|
|
|
|
|
})
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
err = ctx.RegisterKind(reflect.Uint8, NewSerializedType("uint8"),
|
|
|
|
|
func(ctx *Context, ctx_type uint64, reflect_type reflect.Type, value *reflect.Value)(SerializedValue, error){
|
|
|
|
|
var data []byte = nil
|
|
|
|
|
if value != nil {
|
|
|
|
|
data = []byte{uint8(value.Uint())}
|
|
|
|
|
}
|
|
|
|
|
return SerializedValue{
|
|
|
|
|
[]uint64{ctx_type},
|
|
|
|
|
data,
|
|
|
|
|
}, nil
|
|
|
|
|
}, func(ctx *Context, value SerializedValue)(interface{}, []byte, error){
|
|
|
|
|
return nil, nil, fmt.Errorf("deserialize uint8 unimplemented")
|
|
|
|
|
})
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
err = ctx.RegisterKind(reflect.Uint64, NewSerializedType("uint64"),
|
|
|
|
|
func(ctx *Context, ctx_type uint64, reflect_type reflect.Type, value *reflect.Value)(SerializedValue, error){
|
|
|
|
|
var data []byte = nil
|
|
|
|
|
if value != nil {
|
|
|
|
|
data = make([]byte, 8)
|
|
|
|
|
binary.BigEndian.PutUint64(data, value.Uint())
|
|
|
|
|
}
|
|
|
|
|
return SerializedValue{
|
|
|
|
|
[]uint64{ctx_type},
|
|
|
|
|
data,
|
|
|
|
|
}, nil
|
|
|
|
|
}, func(ctx *Context, value SerializedValue)(interface{}, []byte, error){
|
|
|
|
|
return nil, nil, fmt.Errorf("deserialize uint64 unimplemented")
|
|
|
|
|
})
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
err = ctx.RegisterKind(reflect.Slice, NewSerializedType("slice"),
|
|
|
|
|
func(ctx *Context, ctx_type uint64, reflect_type reflect.Type, value *reflect.Value)(SerializedValue, error){
|
|
|
|
|
var data []byte
|
|
|
|
|
if value == nil {
|
|
|
|
|
data = nil
|
|
|
|
@ -427,217 +812,74 @@ func serializeValue(ctx *Context, t reflect.Type, value *reflect.Value) (Seriali
|
|
|
|
|
} else {
|
|
|
|
|
data := make([]byte, 8)
|
|
|
|
|
binary.BigEndian.PutUint64(data, uint64(value.Len()))
|
|
|
|
|
var elem SerializedValue
|
|
|
|
|
var type_stack []uint64
|
|
|
|
|
for i := 0; i < value.Len(); i += 1 {
|
|
|
|
|
val := value.Index(i)
|
|
|
|
|
element, err := serializeValue(ctx, t.Elem(), &val)
|
|
|
|
|
element, err := serializeValue(ctx, reflect_type.Elem(), &val)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return SerializedValue{}, err
|
|
|
|
|
}
|
|
|
|
|
if i == 0 {
|
|
|
|
|
elem = element
|
|
|
|
|
if type_stack == nil {
|
|
|
|
|
type_stack = append([]uint64{ctx_type}, element.TypeStack...)
|
|
|
|
|
}
|
|
|
|
|
data = append(data, elem.Data...)
|
|
|
|
|
data = append(data, element.Data...)
|
|
|
|
|
}
|
|
|
|
|
return SerializedValue{
|
|
|
|
|
append([]uint64{ctx_type}, elem.TypeStack...),
|
|
|
|
|
append([]uint64{ctx_type}, type_stack...),
|
|
|
|
|
data,
|
|
|
|
|
}, nil
|
|
|
|
|
}
|
|
|
|
|
elem, err := serializeValue(ctx, t.Elem(), nil)
|
|
|
|
|
elem, err := serializeValue(ctx, reflect_type.Elem(), nil)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return SerializedValue{}, err
|
|
|
|
|
}
|
|
|
|
|
return SerializedValue{
|
|
|
|
|
append([]uint64{ctx_type}, elem.TypeStack...),
|
|
|
|
|
elem.TypeStack,
|
|
|
|
|
data,
|
|
|
|
|
}, nil
|
|
|
|
|
case reflect.Pointer:
|
|
|
|
|
if ctx_type == 0x00 {
|
|
|
|
|
ctx_type = uint64(PointerType)
|
|
|
|
|
}
|
|
|
|
|
var data []byte
|
|
|
|
|
var elem_value *reflect.Value = nil
|
|
|
|
|
if value == nil {
|
|
|
|
|
data = nil
|
|
|
|
|
} else if value.IsZero() {
|
|
|
|
|
data = []byte{0x01}
|
|
|
|
|
} else {
|
|
|
|
|
data = []byte{0x00}
|
|
|
|
|
ev := value.Elem()
|
|
|
|
|
elem_value = &ev
|
|
|
|
|
}
|
|
|
|
|
elem, err := serializeValue(ctx, t.Elem(), elem_value)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return SerializedValue{}, err
|
|
|
|
|
}
|
|
|
|
|
if elem.Data != nil {
|
|
|
|
|
data = append(data, elem.Data...)
|
|
|
|
|
}, func(ctx *Context, value SerializedValue)(interface{}, []byte, error){
|
|
|
|
|
return nil, nil, fmt.Errorf("not implemented")
|
|
|
|
|
})
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
err = ctx.RegisterType(reflect.TypeOf(Up), NewSerializedType("SignalDirection"),
|
|
|
|
|
func(ctx *Context, ctx_type uint64, t reflect.Type, value *reflect.Value) (SerializedValue, error) {
|
|
|
|
|
var data []byte = nil
|
|
|
|
|
if value != nil {
|
|
|
|
|
val := value.Interface().(SignalDirection)
|
|
|
|
|
data = []byte{byte(val)}
|
|
|
|
|
}
|
|
|
|
|
return SerializedValue{
|
|
|
|
|
append([]uint64{uint64(ctx_type)}, elem.TypeStack...),
|
|
|
|
|
[]uint64{ctx_type},
|
|
|
|
|
data,
|
|
|
|
|
}, nil
|
|
|
|
|
case reflect.String:
|
|
|
|
|
if ctx_type == 0x00 {
|
|
|
|
|
ctx_type = uint64(StringType)
|
|
|
|
|
}
|
|
|
|
|
if value == nil {
|
|
|
|
|
return SerializedValue{
|
|
|
|
|
[]uint64{ctx_type},
|
|
|
|
|
nil,
|
|
|
|
|
}, nil
|
|
|
|
|
}
|
|
|
|
|
}, func(ctx *Context, value SerializedValue) (interface{}, []byte, error) {
|
|
|
|
|
return nil, nil, fmt.Errorf("unimplemented")
|
|
|
|
|
})
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
data := make([]byte, 8)
|
|
|
|
|
str := value.String()
|
|
|
|
|
binary.BigEndian.PutUint64(data, uint64(len(str)))
|
|
|
|
|
return SerializedValue{
|
|
|
|
|
[]uint64{uint64(ctx_type)},
|
|
|
|
|
append(data, []byte(str)...),
|
|
|
|
|
}, nil
|
|
|
|
|
case reflect.Uint8:
|
|
|
|
|
if ctx_type == 0x00 {
|
|
|
|
|
ctx_type = uint64(Uint8Type)
|
|
|
|
|
err = ctx.RegisterType(reflect.TypeOf(ReqState(0)), NewSerializedType("ReqState"),
|
|
|
|
|
func(ctx *Context, ctx_type uint64, t reflect.Type, value *reflect.Value) (SerializedValue, error) {
|
|
|
|
|
var data []byte = nil
|
|
|
|
|
if value != nil {
|
|
|
|
|
val := value.Interface().(ReqState)
|
|
|
|
|
data = []byte{byte(val)}
|
|
|
|
|
}
|
|
|
|
|
return SerializedValue{
|
|
|
|
|
[]uint64{uint64(ctx_type)},
|
|
|
|
|
[]byte{uint8(value.Uint())},
|
|
|
|
|
[]uint64{ctx_type},
|
|
|
|
|
data,
|
|
|
|
|
}, nil
|
|
|
|
|
default:
|
|
|
|
|
return SerializedValue{}, fmt.Errorf("unhandled kind: %+v - %+v", kind, t)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
default:
|
|
|
|
|
kind_def, handled := defaultKinds[kind]
|
|
|
|
|
if handled == false {
|
|
|
|
|
ctx_type, handled := ctx.TypeReflects[value.Type()]
|
|
|
|
|
if handled == false {
|
|
|
|
|
err = fmt.Errorf("%+v is not a handled reflect type", value.Type())
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
type_info, handled := ctx.Types[ctx_type]
|
|
|
|
|
if handled == false {
|
|
|
|
|
err = fmt.Errorf("%+v is not a handled reflect type(INTERNAL_ERROR)", value.Type())
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
field_ser, err := type_info.Serialize(ctx, value.Interface())
|
|
|
|
|
if err != nil {
|
|
|
|
|
err = fmt.Errorf(err.Error())
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
ret = SerializedValue{
|
|
|
|
|
[]uint64{uint64(ctx_type)},
|
|
|
|
|
field_ser,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
field_ser, err := kind_def.Serialize(value.Interface())
|
|
|
|
|
if err != nil {
|
|
|
|
|
err = fmt.Errorf(err.Error())
|
|
|
|
|
} else {
|
|
|
|
|
ret = SerializedValue{
|
|
|
|
|
[]uint64{uint64(kind_def.Type)},
|
|
|
|
|
field_ser,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
func SerializeField(ctx *Context, ext Extension, field_name string) (SerializedValue, error) {
|
|
|
|
|
if ext == nil {
|
|
|
|
|
return SerializedValue{}, fmt.Errorf("Cannot get fields on nil Extension")
|
|
|
|
|
}
|
|
|
|
|
ext_value := reflect.ValueOf(ext).Elem()
|
|
|
|
|
field := ext_value.FieldByName(field_name)
|
|
|
|
|
if field.IsValid() == false {
|
|
|
|
|
return SerializedValue{}, fmt.Errorf("%s is not a field in %+v", field_name, ext)
|
|
|
|
|
} else {
|
|
|
|
|
return SerializeValue(ctx, field)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func SerializeSignal(ctx *Context, signal Signal, ctx_type SignalType) (SerializedValue, error) {
|
|
|
|
|
return SerializedValue{}, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func SerializeExtension(ctx *Context, ext Extension, ctx_type ExtType) (SerializedValue, error) {
|
|
|
|
|
if ext == nil {
|
|
|
|
|
return SerializedValue{}, fmt.Errorf("Cannot serialize nil Extension ")
|
|
|
|
|
}
|
|
|
|
|
ext_type := reflect.TypeOf(ext).Elem()
|
|
|
|
|
ext_value := reflect.ValueOf(ext).Elem()
|
|
|
|
|
|
|
|
|
|
m := map[string]SerializedValue{}
|
|
|
|
|
for _, field := range(reflect.VisibleFields(ext_type)) {
|
|
|
|
|
ext_tag, tagged_ext := field.Tag.Lookup("ext")
|
|
|
|
|
if tagged_ext == false {
|
|
|
|
|
continue
|
|
|
|
|
} else {
|
|
|
|
|
field_value := ext_value.FieldByIndex(field.Index)
|
|
|
|
|
var err error
|
|
|
|
|
m[ext_tag], err = SerializeValue(ctx, field_value)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return SerializedValue{}, err
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
map_value := reflect.ValueOf(m)
|
|
|
|
|
map_ser, err := SerializeValue(ctx, map_value)
|
|
|
|
|
}, func(ctx *Context, value SerializedValue) (interface{}, []byte, error) {
|
|
|
|
|
return nil, nil, fmt.Errorf("unimplemented")
|
|
|
|
|
})
|
|
|
|
|
if err != nil {
|
|
|
|
|
return SerializedValue{}, err
|
|
|
|
|
}
|
|
|
|
|
return SerializedValue{
|
|
|
|
|
append([]uint64{uint64(ctx_type)}, map_ser.TypeStack...),
|
|
|
|
|
map_ser.Data,
|
|
|
|
|
}, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (value SerializedValue) MarshalBinary() ([]byte, error) {
|
|
|
|
|
return nil, fmt.Errorf("SerializedValue.MarshalBinary Undefined")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func ParseSerializedValue(ctx *Context, data []byte) (SerializedValue, []byte, error) {
|
|
|
|
|
return SerializedValue{}, nil, fmt.Errorf("ParseSerializedValue Undefined")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func DeserializeValue(ctx *Context, value SerializedValue) (interface{}, error) {
|
|
|
|
|
return nil, fmt.Errorf("DeserializeValue Undefined")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Create a new Context with the base library content added
|
|
|
|
|
func NewContext(db * badger.DB, log Logger) (*Context, error) {
|
|
|
|
|
ctx := &Context{
|
|
|
|
|
DB: db,
|
|
|
|
|
Log: log,
|
|
|
|
|
Policies: map[PolicyType]reflect.Type{},
|
|
|
|
|
PolicyTypes: map[reflect.Type]PolicyType{},
|
|
|
|
|
Extensions: map[ExtType]ExtensionInfo{},
|
|
|
|
|
ExtensionTypes: map[reflect.Type]ExtType{},
|
|
|
|
|
Signals: map[SignalType]reflect.Type{},
|
|
|
|
|
SignalTypes: map[reflect.Type]SignalType{},
|
|
|
|
|
Nodes: map[NodeType]NodeInfo{},
|
|
|
|
|
nodeMap: map[NodeID]*Node{},
|
|
|
|
|
Types: map[SerializedType]TypeInfo{},
|
|
|
|
|
TypeReflects: map[reflect.Type]SerializedType{},
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var err error
|
|
|
|
|
err = ctx.RegisterType(reflect.TypeOf(SerializedValue{}), NewSerializedType("SerializedValue"),
|
|
|
|
|
func(ctx *Context, val interface{}) ([]byte, error) {
|
|
|
|
|
value := val.(SerializedValue)
|
|
|
|
|
return value.MarshalBinary()
|
|
|
|
|
}, func(ctx *Context, data []byte) (interface{}, error) {
|
|
|
|
|
value, data, err := ParseSerializedValue(ctx, data)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
if data != nil {
|
|
|
|
|
return nil, fmt.Errorf("%+v remaining after parse", data)
|
|
|
|
|
}
|
|
|
|
|
return value, nil
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
err = ctx.RegisterExtension(reflect.TypeOf((*LockableExt)(nil)), LockableExtType, nil)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|