Moved serialization to serialize.go and removed n parameter from DeserializeValue

gql_cataclysm
noah metz 2023-09-05 00:08:09 -06:00
parent 06513a5ad6
commit e2f34150ef
10 changed files with 405 additions and 551 deletions

@ -2,7 +2,6 @@ package graphvent
import (
"crypto/ecdh"
"crypto/sha512"
"encoding/binary"
"errors"
"fmt"
@ -10,83 +9,11 @@ import (
"reflect"
"runtime"
"sync"
"strconv"
badger "github.com/dgraph-io/badger/v3"
)
func Hash(base string, name string) uint64 {
digest := append([]byte(base), 0x00)
digest = append(digest, []byte(name)...)
hash := sha512.Sum512(digest)
return binary.BigEndian.Uint64(hash[0:8])
}
type ExtType uint64
type NodeType uint64
type SignalType uint64
type PolicyType uint64
type SerializedType uint64
func NewExtType(name string) ExtType {
return ExtType(Hash(ExtTypeBase, name))
}
func NewNodeType(name string) NodeType {
return NodeType(Hash(NodeTypeBase, name))
}
func NewSignalType(name string) SignalType {
return SignalType(Hash(SignalTypeBase, name))
}
func NewPolicyType(name string) PolicyType {
return PolicyType(Hash(PolicyTypeBase, name))
}
func NewSerializedType(name string) SerializedType {
val := SerializedType(Hash(SerializedTypeBase, name))
println(fmt.Sprintf("TYPE: %s: %d", name, val))
return val
}
const (
TagBase = "GraphventTag"
ExtTypeBase = "ExtType"
NodeTypeBase = "NodeType"
SignalTypeBase = "SignalType"
PolicyTypeBase = "PolicyType"
SerializedTypeBase = "SerializedType"
FieldNameBase = "FieldName"
)
var (
ListenerExtType = NewExtType("LISTENER")
LockableExtType = NewExtType("LOCKABLE")
GQLExtType = NewExtType("GQL")
GroupExtType = NewExtType("GROUP")
ECDHExtType = NewExtType("ECDH")
GQLNodeType = NewNodeType("GQL")
StopSignalType = NewSignalType("STOP")
CreateSignalType = NewSignalType("CREATE")
StartSignalType = NewSignalType("START")
ErrorSignalType = NewSignalType("ERROR")
StatusSignalType = NewSignalType("STATUS")
LinkSignalType = NewSignalType("LINK")
LockSignalType = NewSignalType("LOCK")
ReadSignalType = NewSignalType("READ")
ReadResultSignalType = NewSignalType("READ_RESULT")
ACLTimeoutSignalType = NewSignalType("ACL_TIMEOUT")
MemberOfPolicyType = NewPolicyType("USER_OF")
RequirementOfPolicyType = NewPolicyType("REQUIEMENT_OF")
PerNodePolicyType = NewPolicyType("PER_NODE")
AllNodesPolicyType = NewPolicyType("ALL_NODES")
ErrorType = NewSerializedType("ERROR")
NodeNotFoundError = errors.New("Node not found in DB")
ECDH = ecdh.X25519()
)
@ -100,14 +27,18 @@ type NodeInfo struct {
Extensions []ExtType
}
type TypeSerialize func(*Context,uint64,reflect.Type,*reflect.Value) (SerializedValue, error)
type TypeDeserialize func(*Context,SerializedValue) (reflect.Type, *reflect.Value, SerializedValue, error)
type TypeInfo struct {
Type reflect.Type
Serialize TypeSerialize
Deserialize TypeDeserialize
}
type KindInfo struct {
Type SerializedType
Serialize TypeSerialize
Deserialize TypeDeserialize
}
// A Context stores all the data to run a graphvent process
type Context struct {
// DB is the database connection used to load and write nodes
@ -309,149 +240,6 @@ func (ctx *Context) Send(messages Messages) error {
return nil
}
type KindInfo struct {
Type SerializedType
Serialize TypeSerialize
Deserialize TypeDeserialize
}
type SerializedValue struct {
TypeStack []uint64
Data []byte
}
func SerializeValue(ctx *Context, value reflect.Value) (SerializedValue, error) {
val, err := serializeValue(ctx, value.Type(), &value)
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]
if exists == true {
type_info := ctx.Types[ctype]
ctx_type = uint64(ctype)
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(data []byte) (SerializedValue, []byte, error) {
if len(data) < 8 {
return SerializedValue{}, nil, 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 + 2)
data_end := types_end + data_size
return SerializedValue{
type_stack,
data[types_end:data_end],
}, data[data_end:], nil
}
func DeserializeValue(ctx *Context, value SerializedValue, n int) (reflect.Type, []reflect.Value, SerializedValue, error) {
ctx.Log.Logf("serialize", "DeserializeValue: %+v - %d", value, n)
ret := make([]reflect.Value, n)
var deserialize TypeDeserialize = nil
var reflect_type reflect.Type = nil
ctx_type := value.TypeStack[0]
value.TypeStack = value.TypeStack[1:]
type_info, exists := ctx.Types[SerializedType(ctx_type)]
if exists == true {
deserialize = type_info.Deserialize
reflect_type = type_info.Type
} else {
kind, exists := ctx.KindTypes[SerializedType(ctx_type)]
if exists == false {
return nil, nil, SerializedValue{}, fmt.Errorf("Cannot deserialize 0x%x: unknown type/kind", ctx_type)
}
kind_info := ctx.Kinds[kind]
deserialize = kind_info.Deserialize
}
ctx.Log.Logf("serialize", "Deserializing: %d x %d", ctx_type, n)
if value.Data == nil {
reflect_type, _, val, err := deserialize(ctx, value)
if err != nil {
return nil, nil, SerializedValue{}, err
}
return reflect_type, nil, val, nil
}
val := SerializedValue{
value.TypeStack,
value.Data,
}
for i := 0; i < n; i += 1 {
val.TypeStack = value.TypeStack
var elem *reflect.Value
var err error
reflect_type, elem, val, err = deserialize(ctx, val)
if err != nil {
return nil, nil, SerializedValue{}, err
}
ret[i] = *elem
}
ctx.Log.Logf("serialize", "DeserializeValue: DONE %+v - %+v", val, ret)
return reflect_type, ret, val, nil
}
// Create a new Context with the base library content added
func NewContext(db * badger.DB, log Logger) (*Context, error) {
ctx := &Context{
@ -473,7 +261,7 @@ func NewContext(db * badger.DB, log Logger) (*Context, error) {
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) {
func(ctx *Context, ctx_type SerializedType, reflect_type reflect.Type, value *reflect.Value) (SerializedValue, error) {
var data []byte
var elem_value *reflect.Value = nil
if value == nil {
@ -493,12 +281,12 @@ func NewContext(db * badger.DB, log Logger) (*Context, error) {
data = append(data, elem.Data...)
}
return SerializedValue{
append([]uint64{ctx_type}, elem.TypeStack...),
append([]SerializedType{ctx_type}, elem.TypeStack...),
data,
}, nil
}, func(ctx *Context, value SerializedValue) (reflect.Type, *reflect.Value, SerializedValue, error) {
if value.Data == nil {
elem_type, _, _, err := DeserializeValue(ctx, value, 1)
elem_type, _, _, err := DeserializeValue(ctx, value)
if err != nil {
return nil, nil, SerializedValue{}, err
}
@ -509,14 +297,14 @@ func NewContext(db * badger.DB, log Logger) (*Context, error) {
pointer_flags := value.Data[0]
value.Data = value.Data[1:]
if pointer_flags == 0x00 {
_, elem_value, remaining_data, err := DeserializeValue(ctx, value, 1)
_, elem_value, remaining_data, err := DeserializeValue(ctx, value)
if err != nil {
return nil, nil, SerializedValue{}, err
}
pointer_value := elem_value[0].Addr()
pointer_value := elem_value.Addr()
return pointer_value.Type(), &pointer_value, remaining_data, nil
} else if pointer_flags == 0x01 {
elem_type, _, remaining_data, err := DeserializeValue(ctx, value, 1)
elem_type, _, remaining_data, err := DeserializeValue(ctx, value)
if err != nil {
return nil, nil, SerializedValue{}, err
}
@ -534,14 +322,12 @@ func NewContext(db * badger.DB, log Logger) (*Context, error) {
}
err = ctx.RegisterKind(reflect.Struct, NewSerializedType("struct"),
func(ctx *Context, ctx_type uint64, reflect_type reflect.Type, value *reflect.Value)(SerializedValue, error){
// TODO: Switch from serializing each field as a []byte of a SerializedValue.MarshalBinary to just running serializeValue and adding the TypeStack and Data together
func(ctx *Context, ctx_type SerializedType, reflect_type reflect.Type, value *reflect.Value)(SerializedValue, error){
serialized_value := SerializedValue{
[]uint64{ctx_type},
[]SerializedType{ctx_type},
nil,
}
num_fields := 0
field_values := map[int]SerializedValue{}
field_values := map[SerializedType]SerializedValue{}
for _, field := range(reflect.VisibleFields(reflect_type)) {
gv_tag, tagged_gv := field.Tag.Lookup("gv")
if tagged_gv == false {
@ -550,37 +336,22 @@ func NewContext(db * badger.DB, log Logger) (*Context, error) {
continue
} else {
// Add to the type stack and data stack
field_index, err := strconv.Atoi(gv_tag)
if err != nil {
return SerializedValue{}, err
}
num_fields += 1
field_hash := Hash(FieldNameBase, gv_tag)
if value == nil {
field_ser, err := serializeValue(ctx, field.Type, nil)
if err != nil {
return SerializedValue{}, err
}
field_values[field_index] = field_ser
field_values[field_hash] = field_ser
} else {
field_value := value.FieldByIndex(field.Index)
field_ser, err := serializeValue(ctx, field.Type, &field_value)
if err != nil {
return SerializedValue{}, err
}
field_values[field_index] = field_ser
}
field_values[field_hash] = field_ser
}
}
for i := 0; i < num_fields; i += 1 {
field_value, exists := field_values[i]
if exists == false {
return SerializedValue{}, fmt.Errorf("%+v missing gv:%d", reflect_type, i)
}
serialized_value.TypeStack = append(serialized_value.TypeStack, field_value.TypeStack...)
if value != nil {
serialized_value.Data = append(serialized_value.Data, field_value.Data...)
}
}
return serialized_value, nil
@ -592,14 +363,14 @@ func NewContext(db * badger.DB, log Logger) (*Context, error) {
}
err = ctx.RegisterKind(reflect.Int, NewSerializedType("int"),
func(ctx *Context, ctx_type uint64, reflect_type reflect.Type, value *reflect.Value)(SerializedValue, error){
func(ctx *Context, ctx_type SerializedType, reflect_type reflect.Type, value *reflect.Value)(SerializedValue, error){
var data []byte = nil
if value != nil {
data = make([]byte, 8)
binary.BigEndian.PutUint64(data, uint64(value.Int()))
}
return SerializedValue{
[]uint64{ctx_type},
[]SerializedType{ctx_type},
data,
}, nil
}, func(ctx *Context, value SerializedValue)(reflect.Type, *reflect.Value, SerializedValue, error){
@ -618,7 +389,7 @@ func NewContext(db * badger.DB, log Logger) (*Context, error) {
}
err = ctx.RegisterKind(reflect.Bool, NewSerializedType("bool"),
func(ctx *Context, ctx_type uint64, reflect_type reflect.Type, value *reflect.Value)(SerializedValue, error){
func(ctx *Context, ctx_type SerializedType, reflect_type reflect.Type, value *reflect.Value)(SerializedValue, error){
var data []byte = nil
if value != nil {
b := value.Bool()
@ -629,7 +400,7 @@ func NewContext(db * badger.DB, log Logger) (*Context, error) {
}
}
return SerializedValue{
[]uint64{ctx_type},
[]SerializedType{ctx_type},
data,
}, nil
}, func(ctx *Context, value SerializedValue)(reflect.Type, *reflect.Value, SerializedValue, error){
@ -657,7 +428,7 @@ func NewContext(db * badger.DB, log Logger) (*Context, error) {
}
err = ctx.RegisterKind(reflect.Float64, NewSerializedType("float64"),
func(ctx *Context, ctx_type uint64, reflect_type reflect.Type, value *reflect.Value)(SerializedValue, error){
func(ctx *Context, ctx_type SerializedType, reflect_type reflect.Type, value *reflect.Value)(SerializedValue, error){
var data []byte = nil
if value != nil {
// TODO: fix if underlying memory layout of float32 changes(or if it's architecture-dependent)
@ -666,7 +437,7 @@ func NewContext(db * badger.DB, log Logger) (*Context, error) {
binary.BigEndian.PutUint64(data, val)
}
return SerializedValue{
[]uint64{ctx_type},
[]SerializedType{ctx_type},
data,
}, nil
}, func(ctx *Context, value SerializedValue)(reflect.Type, *reflect.Value, SerializedValue, error){
@ -690,7 +461,7 @@ func NewContext(db * badger.DB, log Logger) (*Context, error) {
}
err = ctx.RegisterKind(reflect.Float32, NewSerializedType("float32"),
func(ctx *Context, ctx_type uint64, reflect_type reflect.Type, value *reflect.Value)(SerializedValue, error){
func(ctx *Context, ctx_type SerializedType, reflect_type reflect.Type, value *reflect.Value)(SerializedValue, error){
var data []byte = nil
if value != nil {
// TODO: fix if underlying memory layout of float32 changes(or if it's architecture-dependent)
@ -699,7 +470,7 @@ func NewContext(db * badger.DB, log Logger) (*Context, error) {
binary.BigEndian.PutUint32(data, val)
}
return SerializedValue{
[]uint64{ctx_type},
[]SerializedType{ctx_type},
data,
}, nil
}, func(ctx *Context, value SerializedValue)(reflect.Type, *reflect.Value, SerializedValue, error){
@ -723,13 +494,13 @@ func NewContext(db * badger.DB, log Logger) (*Context, error) {
}
err = ctx.RegisterKind(reflect.Uint32, NewSerializedType("uint32"),
func(ctx *Context, ctx_type uint64, reflect_type reflect.Type, value *reflect.Value)(SerializedValue, error){
func(ctx *Context, ctx_type SerializedType, 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},
[]SerializedType{ctx_type},
data,
}, nil
}, func(ctx *Context, value SerializedValue)(reflect.Type, *reflect.Value, SerializedValue, error){
@ -751,10 +522,10 @@ func NewContext(db * badger.DB, log Logger) (*Context, error) {
}
err = ctx.RegisterKind(reflect.String, NewSerializedType("string"),
func(ctx *Context, ctx_type uint64, reflect_type reflect.Type, value *reflect.Value)(SerializedValue, error){
func(ctx *Context, ctx_type SerializedType, reflect_type reflect.Type, value *reflect.Value)(SerializedValue, error){
if value == nil {
return SerializedValue{
[]uint64{ctx_type},
[]SerializedType{ctx_type},
nil,
}, nil
}
@ -763,7 +534,7 @@ func NewContext(db * badger.DB, log Logger) (*Context, error) {
str := value.String()
binary.BigEndian.PutUint64(data, uint64(len(str)))
return SerializedValue{
[]uint64{uint64(ctx_type)},
[]SerializedType{SerializedType(ctx_type)},
append(data, []byte(str)...),
}, nil
}, func(ctx *Context, value SerializedValue)(reflect.Type, *reflect.Value, SerializedValue, error){
@ -789,7 +560,7 @@ func NewContext(db * badger.DB, log Logger) (*Context, error) {
err = ctx.RegisterKind(reflect.Array, NewSerializedType("array"),
func(ctx *Context, ctx_type uint64, reflect_type reflect.Type, value *reflect.Value)(SerializedValue, error){
func(ctx *Context, ctx_type SerializedType, reflect_type reflect.Type, value *reflect.Value)(SerializedValue, error){
var data []byte
if value == nil {
data = nil
@ -799,7 +570,7 @@ func NewContext(db * badger.DB, log Logger) (*Context, error) {
data := make([]byte, 8)
binary.BigEndian.PutUint64(data, uint64(value.Len()))
var type_stack []uint64 = nil
var type_stack []SerializedType = nil
for i := 0; i < value.Len(); i += 1 {
val := value.Index(i)
element, err := serializeValue(ctx, reflect_type.Elem(), &val)
@ -807,7 +578,7 @@ func NewContext(db * badger.DB, log Logger) (*Context, error) {
return SerializedValue{}, err
}
if type_stack == nil {
type_stack = append([]uint64{ctx_type}, element.TypeStack...)
type_stack = append([]SerializedType{ctx_type}, element.TypeStack...)
}
data = append(data, element.Data...)
}
@ -819,7 +590,7 @@ func NewContext(db * badger.DB, log Logger) (*Context, error) {
}
return SerializedValue{
append([]uint64{ctx_type}, elem.TypeStack...),
append([]SerializedType{ctx_type}, elem.TypeStack...),
data,
}, nil
}, func(ctx *Context, value SerializedValue)(reflect.Type, *reflect.Value, SerializedValue, error){
@ -830,9 +601,9 @@ func NewContext(db * badger.DB, log Logger) (*Context, error) {
}
err = ctx.RegisterKind(reflect.Interface, NewSerializedType("interface"),
func(ctx *Context, ctx_type uint64, reflect_type reflect.Type, value *reflect.Value)(SerializedValue, error){
func(ctx *Context, ctx_type SerializedType, reflect_type reflect.Type, value *reflect.Value)(SerializedValue, error){
var data []byte
type_stack := []uint64{}
type_stack := []SerializedType{}
if value == nil {
data = nil
} else if value.IsZero() {
@ -847,7 +618,7 @@ func NewContext(db * badger.DB, log Logger) (*Context, error) {
type_stack = elem.TypeStack
}
return SerializedValue{
append([]uint64{ctx_type}, type_stack...),
append([]SerializedType{ctx_type}, type_stack...),
data,
}, nil
}, func(ctx *Context, value SerializedValue)(reflect.Type, *reflect.Value, SerializedValue, error){
@ -859,170 +630,23 @@ func NewContext(db * badger.DB, log Logger) (*Context, error) {
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
} else if value.IsZero() {
data = []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}
} else if value.Len() == 0 {
data = []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
} else {
map_iter := value.MapRange()
key_data := []byte{}
val_data := []byte{}
var key_types []uint64 = nil
var val_types []uint64 = nil
map_len := 0
for map_iter.Next() {
map_len += 1
key_value := map_iter.Key()
val_value := map_iter.Value()
key, err := serializeValue(ctx, reflect_type.Key(), &key_value)
if err != nil {
return SerializedValue{}, err
}
val, err := serializeValue(ctx, reflect_type.Elem(), &val_value)
if err != nil {
return SerializedValue{}, err
}
if key_types == nil {
key_types = key.TypeStack
val_types = val.TypeStack
}
key_data = append(key_data, key.Data...)
val_data = append(val_data, val.Data...)
}
type_stack := []uint64{ctx_type}
type_stack = append(type_stack, key_types...)
type_stack = append(type_stack, val_types...)
data := make([]byte, 8)
binary.BigEndian.PutUint64(data, uint64(map_len))
data = append(data, key_data...)
data = append(data, val_data...)
return SerializedValue{
type_stack,
data,
}, nil
}
key, err := serializeValue(ctx, reflect_type.Key(), nil)
if err != nil {
return SerializedValue{}, err
}
elem, err := serializeValue(ctx, reflect_type.Elem(), nil)
if err != nil {
return SerializedValue{}, err
}
type_stack := []uint64{ctx_type}
type_stack = append(type_stack, key.TypeStack...)
type_stack = append(type_stack, elem.TypeStack...)
return SerializedValue{
type_stack,
data,
}, nil
func(ctx *Context, ctx_type SerializedType, reflect_type reflect.Type, value *reflect.Value)(SerializedValue, error){
return SerializedValue{}, fmt.Errorf("serialize map unimplemented")
}, func(ctx *Context, value SerializedValue)(reflect.Type, *reflect.Value, SerializedValue, error){
if value.Data == nil {
var key_type, elem_type reflect.Type
key_type, _, value, err = DeserializeValue(ctx, value, 1)
if err != nil {
return nil, nil, SerializedValue{}, err
}
elem_type, _, value, err = DeserializeValue(ctx, value, 1)
if err != nil {
return nil, nil, SerializedValue{}, err
}
return reflect.MapOf(key_type, elem_type), nil, value, nil
} else if len(value.Data) < 8 {
return nil, nil, SerializedValue{}, fmt.Errorf("Not enough data to deserialize map")
} else {
map_len := binary.BigEndian.Uint64(value.Data[0:8])
value.Data = value.Data[8:]
if map_len == 0xFFFFFFFFFFFFFFFF {
temp_value := SerializedValue{
value.TypeStack,
nil,
}
var key_type, elem_type reflect.Type
key_type, _, temp_value, err = DeserializeValue(ctx, temp_value, 1)
if err != nil {
return nil, nil, SerializedValue{}, err
}
elem_type, _, temp_value, err = DeserializeValue(ctx, temp_value, 1)
if err != nil {
return nil, nil, SerializedValue{}, err
}
map_type := reflect.MapOf(key_type, elem_type)
map_value := reflect.New(map_type).Elem()
return map_type, &map_value, SerializedValue{
temp_value.TypeStack,
value.Data,
}, nil
} else if map_len == 0x00 {
temp_value := SerializedValue{
value.TypeStack,
nil,
}
var key_type, elem_type reflect.Type
key_type, _, temp_value, err = DeserializeValue(ctx, temp_value, 1)
if err != nil {
return nil, nil, SerializedValue{}, err
}
elem_type, _, temp_value, err = DeserializeValue(ctx, temp_value, 1)
if err != nil {
return nil, nil, SerializedValue{}, err
}
map_type := reflect.MapOf(key_type, elem_type)
map_value := reflect.MakeMap(map_type)
return map_type, &map_value, SerializedValue{
temp_value.TypeStack,
value.Data,
}, nil
} else {
var key_type, elem_type reflect.Type
var key_values, elem_values []reflect.Value
key_type, key_values, value, err = DeserializeValue(ctx, value, int(map_len))
if err != nil {
return nil, nil, SerializedValue{}, err
}
elem_type, elem_values, value, err = DeserializeValue(ctx, value, int(map_len))
if err != nil {
return nil, nil, SerializedValue{}, err
}
map_type := reflect.MapOf(key_type, elem_type)
map_value := reflect.MakeMap(map_type)
for i := 0; i < int(map_len); i += 1 {
map_value.SetMapIndex(key_values[i], elem_values[i])
}
return map_type, &map_value, value, nil
}
}
return nil, nil, value, fmt.Errorf("deserialize map unimplemented")
})
if err != nil {
return nil, err
}
err = ctx.RegisterKind(reflect.Int8, NewSerializedType("int8"),
func(ctx *Context, ctx_type uint64, reflect_type reflect.Type, value *reflect.Value)(SerializedValue, error){
func(ctx *Context, ctx_type SerializedType, reflect_type reflect.Type, value *reflect.Value)(SerializedValue, error){
var data []byte = nil
if value != nil {
data = []byte{byte(value.Int())}
}
return SerializedValue{
[]uint64{ctx_type},
[]SerializedType{ctx_type},
data,
}, nil
}, func(ctx *Context, value SerializedValue)(reflect.Type, *reflect.Value, SerializedValue, error){
@ -1043,13 +667,13 @@ func NewContext(db * badger.DB, log Logger) (*Context, error) {
}
err = ctx.RegisterKind(reflect.Uint8, NewSerializedType("uint8"),
func(ctx *Context, ctx_type uint64, reflect_type reflect.Type, value *reflect.Value)(SerializedValue, error){
func(ctx *Context, ctx_type SerializedType, 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},
[]SerializedType{ctx_type},
data,
}, nil
}, func(ctx *Context, value SerializedValue)(reflect.Type, *reflect.Value, SerializedValue, error){
@ -1070,14 +694,14 @@ func NewContext(db * badger.DB, log Logger) (*Context, error) {
}
err = ctx.RegisterKind(reflect.Uint16, NewSerializedType("uint16"),
func(ctx *Context, ctx_type uint64, reflect_type reflect.Type, value *reflect.Value)(SerializedValue, error){
func(ctx *Context, ctx_type SerializedType, reflect_type reflect.Type, value *reflect.Value)(SerializedValue, error){
var data []byte = nil
if value != nil {
data = make([]byte, 2)
binary.BigEndian.PutUint16(data, uint16(value.Uint()))
}
return SerializedValue{
[]uint64{ctx_type},
[]SerializedType{ctx_type},
data,
}, nil
}, func(ctx *Context, value SerializedValue)(reflect.Type, *reflect.Value, SerializedValue, error){
@ -1099,14 +723,14 @@ func NewContext(db * badger.DB, log Logger) (*Context, error) {
}
err = ctx.RegisterKind(reflect.Int16, NewSerializedType("int16"),
func(ctx *Context, ctx_type uint64, reflect_type reflect.Type, value *reflect.Value)(SerializedValue, error){
func(ctx *Context, ctx_type SerializedType, reflect_type reflect.Type, value *reflect.Value)(SerializedValue, error){
var data []byte = nil
if value != nil {
data = make([]byte, 2)
binary.BigEndian.PutUint16(data, uint16(value.Int()))
}
return SerializedValue{
[]uint64{ctx_type},
[]SerializedType{ctx_type},
data,
}, nil
}, func(ctx *Context, value SerializedValue)(reflect.Type, *reflect.Value, SerializedValue, error){
@ -1128,14 +752,14 @@ func NewContext(db * badger.DB, log Logger) (*Context, error) {
}
err = ctx.RegisterKind(reflect.Int32, NewSerializedType("int32"),
func(ctx *Context, ctx_type uint64, reflect_type reflect.Type, value *reflect.Value)(SerializedValue, error){
func(ctx *Context, ctx_type SerializedType, reflect_type reflect.Type, value *reflect.Value)(SerializedValue, error){
var data []byte = nil
if value != nil {
data = make([]byte, 4)
binary.BigEndian.PutUint32(data, uint32(value.Int()))
}
return SerializedValue{
[]uint64{ctx_type},
[]SerializedType{ctx_type},
data,
}, nil
}, func(ctx *Context, value SerializedValue)(reflect.Type, *reflect.Value, SerializedValue, error){
@ -1157,14 +781,14 @@ func NewContext(db * badger.DB, log Logger) (*Context, error) {
}
err = ctx.RegisterKind(reflect.Uint, NewSerializedType("uint"),
func(ctx *Context, ctx_type uint64, reflect_type reflect.Type, value *reflect.Value)(SerializedValue, error){
func(ctx *Context, ctx_type SerializedType, 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},
[]SerializedType{ctx_type},
data,
}, nil
}, func(ctx *Context, value SerializedValue)(reflect.Type, *reflect.Value, SerializedValue, error){
@ -1172,7 +796,7 @@ func NewContext(db * badger.DB, log Logger) (*Context, error) {
return reflect.TypeOf(uint(0)), nil, value, nil
} else {
if len(value.Data) < 8 {
return nil, nil, SerializedValue{}, fmt.Errorf("Not enough data to deserialize uint64")
return nil, nil, SerializedValue{}, fmt.Errorf("Not enough data to deserialize SerializedType")
}
val := uint(binary.BigEndian.Uint64(value.Data[0:8]))
value.Data = value.Data[8:]
@ -1185,23 +809,23 @@ func NewContext(db * badger.DB, log Logger) (*Context, error) {
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){
err = ctx.RegisterKind(reflect.Uint64, NewSerializedType("SerializedType"),
func(ctx *Context, ctx_type SerializedType, 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},
[]SerializedType{ctx_type},
data,
}, nil
}, func(ctx *Context, value SerializedValue)(reflect.Type, *reflect.Value, SerializedValue, error){
if value.Data == nil {
return reflect.TypeOf(uint64(0)), nil, value, nil
return reflect.TypeOf(SerializedType(0)), nil, value, nil
} else {
if len(value.Data) < 8 {
return nil, nil, SerializedValue{}, fmt.Errorf("Not enough data to deserialize uint64")
return nil, nil, SerializedValue{}, fmt.Errorf("Not enough data to deserialize SerializedType")
}
val := binary.BigEndian.Uint64(value.Data[0:8])
value.Data = value.Data[8:]
@ -1215,14 +839,14 @@ func NewContext(db * badger.DB, log Logger) (*Context, error) {
}
err = ctx.RegisterKind(reflect.Int64, NewSerializedType("int64"),
func(ctx *Context, ctx_type uint64, reflect_type reflect.Type, value *reflect.Value)(SerializedValue, error){
func(ctx *Context, ctx_type SerializedType, reflect_type reflect.Type, value *reflect.Value)(SerializedValue, error){
var data []byte = nil
if value != nil {
data = make([]byte, 8)
binary.BigEndian.PutUint64(data, uint64(value.Int()))
}
return SerializedValue{
[]uint64{ctx_type},
[]SerializedType{ctx_type},
data,
}, nil
}, func(ctx *Context, value SerializedValue)(reflect.Type, *reflect.Value, SerializedValue, error){
@ -1230,7 +854,7 @@ func NewContext(db * badger.DB, log Logger) (*Context, error) {
return reflect.TypeOf(int64(0)), nil, value, nil
} else {
if len(value.Data) < 8 {
return nil, nil, SerializedValue{}, fmt.Errorf("Not enough data to deserialize uint64")
return nil, nil, SerializedValue{}, fmt.Errorf("Not enough data to deserialize SerializedType")
}
val := int64(binary.BigEndian.Uint64(value.Data[0:8]))
value.Data = value.Data[8:]
@ -1243,10 +867,10 @@ func NewContext(db * badger.DB, log Logger) (*Context, error) {
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){
err = ctx.RegisterKind(reflect.Slice, SliceType,
func(ctx *Context, ctx_type SerializedType, reflect_type reflect.Type, value *reflect.Value)(SerializedValue, error){
var data []byte
var type_stack []uint64 = nil
type_stack := []SerializedType{ctx_type}
if value == nil {
data = nil
} else if value.IsZero() {
@ -1256,19 +880,18 @@ func NewContext(db * badger.DB, log Logger) (*Context, error) {
} else {
data := make([]byte, 8)
binary.BigEndian.PutUint64(data, uint64(value.Len()))
var element SerializedValue
var err error
for i := 0; i < value.Len(); i += 1 {
val := value.Index(i)
element, err := serializeValue(ctx, reflect_type.Elem(), &val)
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...)
}
return SerializedValue{
type_stack,
append(type_stack, element.TypeStack...),
data,
}, nil
}
@ -1277,12 +900,12 @@ func NewContext(db * badger.DB, log Logger) (*Context, error) {
return SerializedValue{}, err
}
return SerializedValue{
append([]uint64{ctx_type}, element.TypeStack...),
append(type_stack, element.TypeStack...),
data,
}, nil
}, func(ctx *Context, value SerializedValue)(reflect.Type, *reflect.Value, SerializedValue, error){
if value.Data == nil {
elem_type, _, _, err := DeserializeValue(ctx, value, 1)
elem_type, _, _, err := DeserializeValue(ctx, value)
if err != nil {
return nil, nil, SerializedValue{}, err
}
@ -1296,7 +919,7 @@ func NewContext(db * badger.DB, log Logger) (*Context, error) {
elem_type, _, remaining, err := DeserializeValue(ctx, SerializedValue{
value.TypeStack,
nil,
}, 1)
})
if err != nil {
return nil, nil, SerializedValue{}, err
}
@ -1307,7 +930,7 @@ func NewContext(db * badger.DB, log Logger) (*Context, error) {
value.Data,
}, nil
} else if slice_length == 0x00 {
elem_type, _, remaining, err := DeserializeValue(ctx, value, 1)
elem_type, _, remaining, err := DeserializeValue(ctx, value)
if err != nil {
return nil, nil, SerializedValue{}, err
}
@ -1317,15 +940,28 @@ func NewContext(db * badger.DB, log Logger) (*Context, error) {
value.Data,
}, nil
} else {
elem_type, elements, remaining_data, err := DeserializeValue(ctx, value, int(slice_length))
var reflect_value *reflect.Value = nil
var reflect_type reflect.Type = nil
saved_type_stack := value.TypeStack
for i := 0; i < int(slice_length); i += 1 {
var element_type reflect.Type
var element_value *reflect.Value
element_type, element_value, value, err = DeserializeValue(ctx, value)
if err != nil {
return nil, nil, SerializedValue{}, err
return nil, nil, value, err
}
reflect_value := reflect.MakeSlice(reflect.SliceOf(elem_type), 0, int(slice_length))
for i := 0; i < int(slice_length); i += 1 {
reflect_value = reflect.Append(reflect_value, elements[i])
if reflect_value == nil {
reflect_type = reflect.SliceOf(element_type)
real_value := reflect.MakeSlice(reflect_type, int(slice_length), int(slice_length))
reflect_value = &real_value
}
if i != (int(slice_length) - 1) {
value.TypeStack = saved_type_stack
}
slice_index_ptr := reflect_value.Index(i)
slice_index_ptr.Set(*element_value)
}
return reflect_value.Type(), &reflect_value, remaining_data, nil
return reflect_type, reflect_value, value, nil
}
}
})
@ -1334,10 +970,10 @@ func NewContext(db * badger.DB, log Logger) (*Context, error) {
}
err = ctx.RegisterType(reflect.TypeOf(StringError("")), ErrorType,
func(ctx *Context, ctx_type uint64, t reflect.Type, value *reflect.Value) (SerializedValue, error) {
func(ctx *Context, ctx_type SerializedType, t reflect.Type, value *reflect.Value) (SerializedValue, error) {
if value == nil {
return SerializedValue{
[]uint64{ctx_type},
[]SerializedType{ctx_type},
nil,
}, nil
}
@ -1347,7 +983,7 @@ func NewContext(db * badger.DB, log Logger) (*Context, error) {
str := string(err)
binary.BigEndian.PutUint64(data, uint64(len(str)))
return SerializedValue{
[]uint64{uint64(ctx_type)},
[]SerializedType{SerializedType(ctx_type)},
append(data, []byte(str)...),
}, nil
}, func(ctx *Context, value SerializedValue)(reflect.Type, *reflect.Value, SerializedValue, error){
@ -1355,7 +991,7 @@ func NewContext(db * badger.DB, log Logger) (*Context, error) {
})
err = ctx.RegisterType(reflect.TypeOf(RandID()), NewSerializedType("NodeID"),
func(ctx *Context, ctx_type uint64, t reflect.Type, value *reflect.Value) (SerializedValue, error) {
func(ctx *Context, ctx_type SerializedType, t reflect.Type, value *reflect.Value) (SerializedValue, error) {
var id_ser []byte = nil
if value != nil {
var err error = nil
@ -1365,7 +1001,7 @@ func NewContext(db * badger.DB, log Logger) (*Context, error) {
}
}
return SerializedValue{
[]uint64{ctx_type},
[]SerializedType{ctx_type},
id_ser,
}, nil
}, func(ctx *Context, value SerializedValue)(reflect.Type, *reflect.Value, SerializedValue, error){
@ -1376,14 +1012,14 @@ func NewContext(db * badger.DB, log Logger) (*Context, error) {
}
err = ctx.RegisterType(reflect.TypeOf(Up), NewSerializedType("SignalDirection"),
func(ctx *Context, ctx_type uint64, t reflect.Type, value *reflect.Value) (SerializedValue, error) {
func(ctx *Context, ctx_type SerializedType, 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{
[]uint64{ctx_type},
[]SerializedType{ctx_type},
data,
}, nil
}, func(ctx *Context, value SerializedValue)(reflect.Type, *reflect.Value, SerializedValue, error){
@ -1394,14 +1030,14 @@ func NewContext(db * badger.DB, log Logger) (*Context, error) {
}
err = ctx.RegisterType(reflect.TypeOf(ReqState(0)), NewSerializedType("ReqState"),
func(ctx *Context, ctx_type uint64, t reflect.Type, value *reflect.Value) (SerializedValue, error) {
func(ctx *Context, ctx_type SerializedType, 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{ctx_type},
[]SerializedType{ctx_type},
data,
}, nil
}, func(ctx *Context, value SerializedValue)(reflect.Type, *reflect.Value, SerializedValue, error){

@ -569,7 +569,7 @@ func (ctx *GQLExtContext) RegisterField(gql_type graphql.Type, gql_name string,
return nil, fmt.Errorf("%s is not in the fields of %+v in the result", acl_name, ext_type)
}
if val_ser.TypeStack[0] == uint64(ErrorType) {
if val_ser.TypeStack[0] == ErrorType {
return nil, fmt.Errorf(string(val_ser.Data))
}

@ -31,33 +31,33 @@ func TestGQLServer(t *testing.T) {
gql_id := KeyID(pub)
group_policy_1 := NewAllNodesPolicy(Tree{
uint64(ReadSignalType): Tree{
uint64(GroupExtType): Tree{
SerializedType(ReadSignalType): Tree{
SerializedType(GroupExtType): Tree{
Hash(FieldNameBase, "members"): Tree{},
},
},
uint64(ReadResultSignalType): nil,
uint64(ErrorSignalType): nil,
SerializedType(ReadResultSignalType): nil,
SerializedType(ErrorSignalType): nil,
})
group_policy_2 := NewMemberOfPolicy(map[NodeID]Tree{
gql_id: Tree{
uint64(LinkSignalType): nil,
uint64(LockSignalType): nil,
uint64(StatusSignalType): nil,
uint64(ReadSignalType): nil,
SerializedType(LinkSignalType): nil,
SerializedType(LockSignalType): nil,
SerializedType(StatusSignalType): nil,
SerializedType(ReadSignalType): nil,
},
})
user_policy_1 := NewAllNodesPolicy(Tree{
uint64(ReadResultSignalType): nil,
uint64(ErrorSignalType): nil,
SerializedType(ReadResultSignalType): nil,
SerializedType(ErrorSignalType): nil,
})
user_policy_2 := NewMemberOfPolicy(map[NodeID]Tree{
gql_id: Tree{
uint64(LinkSignalType): nil,
uint64(ReadSignalType): nil,
SerializedType(LinkSignalType): nil,
SerializedType(ReadSignalType): nil,
},
})

@ -73,7 +73,7 @@ func Test10KLink(t *testing.T) {
listener_id := KeyID(l_pub)
child_policy := NewPerNodePolicy(map[NodeID]Tree{
listener_id: Tree{
uint64(LockSignalType): nil,
SerializedType(LockSignalType): nil,
},
})
NewLockable := func()(*Node) {
@ -95,7 +95,7 @@ func Test10KLink(t *testing.T) {
ctx.Log.Logf("test", "CREATED_10K")
l_policy := NewAllNodesPolicy(Tree{
uint64(LockSignalType): nil,
SerializedType(LockSignalType): nil,
})
listener := NewListenerExt(100000)
node, err := NewNode(ctx, listener_key, TestLockableType, 10000,

@ -206,7 +206,7 @@ func NewErrorField(fstring string, args ...interface{}) SerializedValue {
panic(err)
}
return SerializedValue{
TypeStack: []uint64{uint64(ErrorType)},
TypeStack: []SerializedType{ErrorType},
Data: str_ser,
}
}
@ -570,9 +570,9 @@ func NewNode(ctx *Context, key ed25519.PrivateKey, node_type NodeType, buffer_si
}
default_policy := NewAllNodesPolicy(Tree{
uint64(ErrorSignalType): nil,
uint64(ReadResultSignalType): nil,
uint64(StatusSignalType): nil,
SerializedType(ErrorSignalType): nil,
SerializedType(ReadResultSignalType): nil,
SerializedType(StatusSignalType): nil,
})
all_nodes_policy, exists := policies[AllNodesPolicyType]
@ -665,7 +665,7 @@ func LoadNode(ctx * Context, id NodeID) (*Node, error) {
} else if len(remaining) != 0 {
return nil, fmt.Errorf("%d bytes left after parsing node from DB", len(remaining))
}
_, node_val, remaining_data, err := DeserializeValue(ctx, value, 1)
_, node_val, remaining_data, err := DeserializeValue(ctx, value)
if err != nil {
return nil, err
}
@ -677,7 +677,7 @@ func LoadNode(ctx * Context, id NodeID) (*Node, error) {
return nil, fmt.Errorf("%d bytes left after desrializing *Node", len(remaining_data.Data))
}
node, ok := node_val[0].Interface().(*Node)
node, ok := node_val.Interface().(*Node)
if ok == false {
return nil, fmt.Errorf("Deserialized %+v when expecting *Node", reflect.TypeOf(node_val).Elem())
}

@ -55,7 +55,7 @@ func TestNodeRead(t *testing.T) {
n1_policy := NewPerNodePolicy(map[NodeID]Tree{
n2_id: {
uint64(ReadSignalType): nil,
SerializedType(ReadSignalType): nil,
},
})

@ -64,12 +64,12 @@ func (policy *RequirementOfPolicy) ContinueAllows(ctx *Context, current PendingA
return Deny
}
_, reqs_if, _, err := DeserializeValue(ctx, reqs_ser, 1)
_, reqs_if, _, err := DeserializeValue(ctx, reqs_ser)
if err != nil {
return Deny
}
requirements, ok := reqs_if[0].Interface().(map[NodeID]ReqState)
requirements, ok := reqs_if.Interface().(map[NodeID]ReqState)
if ok == false {
return Deny
}
@ -113,12 +113,12 @@ func (policy *MemberOfPolicy) ContinueAllows(ctx *Context, current PendingACL, s
return Deny
}
_, members_if, _, err := DeserializeValue(ctx, members_ser, 1)
_, members_if, _, err := DeserializeValue(ctx, members_ser)
if err != nil {
return Deny
}
members, ok := members_if[0].Interface().(map[NodeID]string)
members, ok := members_if.Interface().(map[NodeID]string)
if ok == false {
return Deny
}
@ -249,7 +249,7 @@ func (policy *AllNodesPolicy) Copy() Policy {
}
}
type Tree map[uint64]Tree
type Tree map[SerializedType]Tree
func (rule Tree) Allows(action Tree) RuleResult {
// If the current rule is nil, it's a wildcard and any action being processed is allowed
@ -311,6 +311,6 @@ func (policy *AllNodesPolicy) Type() PolicyType {
}
var DefaultPolicy = NewAllNodesPolicy(Tree{
uint64(ErrorSignalType): nil,
uint64(ReadResultSignalType): nil,
SerializedType(ErrorSignalType): nil,
SerializedType(ReadResultSignalType): nil,
})

@ -0,0 +1,227 @@
package graphvent
import (
"crypto/sha512"
"encoding/binary"
"fmt"
"reflect"
)
const (
TagBase = "GraphventTag"
ExtTypeBase = "ExtType"
NodeTypeBase = "NodeType"
SignalTypeBase = "SignalType"
PolicyTypeBase = "PolicyType"
SerializedTypeBase = "SerializedType"
FieldNameBase = "FieldName"
)
func Hash(base string, name string) SerializedType {
digest := append([]byte(base), 0x00)
digest = append(digest, []byte(name)...)
hash := sha512.Sum512(digest)
return SerializedType(binary.BigEndian.Uint64(hash[0:8]))
}
type SerializedType uint64
type ExtType SerializedType
type NodeType SerializedType
type SignalType SerializedType
type PolicyType SerializedType
type TypeSerialize func(*Context,SerializedType,reflect.Type,*reflect.Value) (SerializedValue, error)
type TypeDeserialize func(*Context,SerializedValue) (reflect.Type, *reflect.Value, SerializedValue, error)
func NewExtType(name string) ExtType {
return ExtType(Hash(ExtTypeBase, name))
}
func NewNodeType(name string) NodeType {
return NodeType(Hash(NodeTypeBase, name))
}
func NewSignalType(name string) SignalType {
return SignalType(Hash(SignalTypeBase, name))
}
func NewPolicyType(name string) PolicyType {
return PolicyType(Hash(PolicyTypeBase, name))
}
func NewSerializedType(name string) SerializedType {
return Hash(SerializedTypeBase, name)
}
var (
ListenerExtType = NewExtType("LISTENER")
LockableExtType = NewExtType("LOCKABLE")
GQLExtType = NewExtType("GQL")
GroupExtType = NewExtType("GROUP")
ECDHExtType = NewExtType("ECDH")
GQLNodeType = NewNodeType("GQL")
StopSignalType = NewSignalType("STOP")
CreateSignalType = NewSignalType("CREATE")
StartSignalType = NewSignalType("START")
ErrorSignalType = NewSignalType("ERROR")
StatusSignalType = NewSignalType("STATUS")
LinkSignalType = NewSignalType("LINK")
LockSignalType = NewSignalType("LOCK")
ReadSignalType = NewSignalType("READ")
ReadResultSignalType = NewSignalType("READ_RESULT")
ACLTimeoutSignalType = NewSignalType("ACL_TIMEOUT")
MemberOfPolicyType = NewPolicyType("USER_OF")
RequirementOfPolicyType = NewPolicyType("REQUIEMENT_OF")
PerNodePolicyType = NewPolicyType("PER_NODE")
AllNodesPolicyType = NewPolicyType("ALL_NODES")
ErrorType = NewSerializedType("ERROR")
PointerType = NewSerializedType("POINTER")
SliceType = NewSerializedType("SLICE")
)
type SerializedValue struct {
TypeStack []SerializedType
Data []byte
}
func (value SerializedValue) PopType() (SerializedType, SerializedValue, error) {
if len(value.TypeStack) == 0 {
return SerializedType(0), value, fmt.Errorf("No elements in TypeStack")
}
ctx_type := value.TypeStack[0]
value.TypeStack = value.TypeStack[1:]
return ctx_type, value, nil
}
func (value SerializedValue) PopData(n int) ([]byte, SerializedValue, error) {
if len(value.Data) < n {
return nil, value, fmt.Errorf("Not enough data %d/%d", len(value.Data), n)
}
data := value.Data[0:n]
value.Data = value.Data[n:]
return data, value, nil
}
func SerializeValue(ctx *Context, value reflect.Value) (SerializedValue, error) {
val, err := serializeValue(ctx, value.Type(), &value)
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) {
ctx_type, type_exists := ctx.TypeReflects[t]
if type_exists == true {
type_info := ctx.Types[ctx_type]
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 type_exists == false {
ctx_type = 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], uint64(t))
}
return append(data, value.Data...), nil
}
func (value SerializedValue) SerializedSize() uint64 {
return uint64((len(value.TypeStack) + 2) * 8)
}
func ParseSerializedValue(data []byte) (SerializedValue, []byte, error) {
if len(data) < 8 {
return SerializedValue{}, nil, 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([]SerializedType, num_types)
for i := 0; i < num_types; i += 1 {
type_start := (i+2) * 8
type_end := (i+3) * 8
type_stack[i] = SerializedType(binary.BigEndian.Uint64(data[type_start:type_end]))
}
types_end := 8*(num_types + 2)
data_end := types_end + data_size
return SerializedValue{
type_stack,
data[types_end:data_end],
}, data[data_end:], nil
}
func DeserializeValue(ctx *Context, value SerializedValue) (reflect.Type, *reflect.Value, SerializedValue, error) {
ctx.Log.Logf("serialize", "DeserializeValue: %+v", value)
var deserialize TypeDeserialize = nil
var reflect_type reflect.Type = nil
var reflect_value *reflect.Value = nil
ctx_type, value, err := value.PopType()
if err != nil {
return nil, nil, value, err
}
type_info, exists := ctx.Types[SerializedType(ctx_type)]
if exists == true {
deserialize = type_info.Deserialize
reflect_type = type_info.Type
} else {
kind, exists := ctx.KindTypes[SerializedType(ctx_type)]
if exists == false {
return nil, nil, value, fmt.Errorf("Cannot deserialize 0x%x: unknown type/kind", ctx_type)
}
kind_info := ctx.Kinds[kind]
deserialize = kind_info.Deserialize
}
ctx.Log.Logf("serialize", "Deserializing: %d", ctx_type)
if value.Data == nil {
reflect_type, _, value, err = deserialize(ctx, value)
} else {
reflect_type, reflect_value, value, err = deserialize(ctx, value)
}
if err != nil {
return nil, nil, value, err
}
ctx.Log.Logf("serialize", "DeserializeValue: DONE %+v - %+v - %+v", value, reflect_type, reflect_value)
return reflect_type, reflect_value, value, nil
}

@ -27,13 +27,6 @@ func TestSerializeBasic(t *testing.T) {
testSerializeSliceSlice[[][]int](t, ctx, [][]int{{123, 456, 789, 101112}, {3253, 2341, 735, 212}, {123, 51}, nil})
testSerializeSliceSlice[[][]string](t, ctx, [][]string{{"123", "456", "789", "101112"}, {"3253", "2341", "735", "212"}, {"123", "51"}, nil})
testSerializeMap(t, ctx, map[int]int{
1: 2,
3: 4,
5: 6,
7: 8,
})
testSerialize(t, ctx, struct{
int `gv:"0"`
string `gv:"1"`
@ -105,7 +98,7 @@ func testSerialize[T any](t *testing.T, ctx *Context, val T) T {
t.Fatal("Data remaining after deserializing value")
}
val_type, deserialized_values, remaining_deserialize, err := DeserializeValue(ctx, val_parsed, 1)
val_type, deserialized_values, remaining_deserialize, err := DeserializeValue(ctx, val_parsed)
fatalErr(t, err)
if len(remaining_deserialize.Data) != 0 {
@ -116,12 +109,10 @@ func testSerialize[T any](t *testing.T, ctx *Context, val T) T {
t.Fatal(fmt.Sprintf("DeserializeValue returned wrong reflect.Type %+v - %+v", val_type, reflect.TypeOf(val)))
} else if deserialized_values == nil {
t.Fatal("DeserializeValue returned no []reflect.Value")
} else if len(deserialized_values) == 0 {
t.Fatal("DeserializeValue returned empty []reflect.Value")
} else if len(deserialized_values) > 1 {
t.Fatal("DeserializeValue returned wrong length []reflect.Value")
} else if deserialized_values[0].CanConvert(val_type) == false {
} else if deserialized_values == nil {
t.Fatal("DeserializeValue returned nil *reflect.Value")
} else if deserialized_values.CanConvert(val_type) == false {
t.Fatal("DeserializeValue returned value that can't convert to original value")
}
return deserialized_values[0].Interface().(T)
return deserialized_values.Interface().(T)
}

@ -144,7 +144,7 @@ func (signal *CreateSignal) Header() *SignalHeader {
}
func (signal *CreateSignal) Permission() Tree {
return Tree{
uint64(CreateSignalType): nil,
SerializedType(CreateSignalType): nil,
}
}
@ -162,7 +162,7 @@ func (signal *StartSignal) Header() *SignalHeader {
}
func (signal *StartSignal) Permission() Tree {
return Tree{
uint64(StartSignalType): nil,
SerializedType(StartSignalType): nil,
}
}
func NewStartSignal() *StartSignal {
@ -179,7 +179,7 @@ func (signal *StopSignal) Header() *SignalHeader {
}
func (signal *StopSignal) Permission() Tree {
return Tree{
uint64(StopSignalType): nil,
SerializedType(StopSignalType): nil,
}
}
func NewStopSignal() *StopSignal {
@ -250,7 +250,7 @@ func (signal *ErrorSignal) Deserialize(ctx *Context, data []byte) error {
}
func (signal *ErrorSignal) Permission() Tree {
return Tree{
uint64(ErrorSignalType): nil,
SerializedType(ErrorSignalType): nil,
}
}
func NewErrorSignal(req_id uuid.UUID, fmt_string string, args ...interface{}) Signal {
@ -268,7 +268,7 @@ func (signal *ACLTimeoutSignal) Header() *SignalHeader {
}
func (signal *ACLTimeoutSignal) Permission() Tree {
return Tree{
uint64(ACLTimeoutSignalType): nil,
SerializedType(ACLTimeoutSignalType): nil,
}
}
func NewACLTimeoutSignal(req_id uuid.UUID) *ACLTimeoutSignal {
@ -288,7 +288,7 @@ func (signal *StatusSignal) Header() *SignalHeader {
}
func (signal *StatusSignal) Permission() Tree {
return Tree{
uint64(StatusSignalType): nil,
SerializedType(StatusSignalType): nil,
}
}
func NewStatusSignal(source NodeID, status string) *StatusSignal {
@ -315,7 +315,7 @@ const (
func (signal *LinkSignal) Permission() Tree {
return Tree{
uint64(LinkSignalType): Tree{
SerializedType(LinkSignalType): Tree{
Hash(LinkActionBase, signal.Action): nil,
},
}
@ -342,7 +342,7 @@ const (
func (signal *LockSignal) Permission() Tree {
return Tree{
uint64(LockSignalType): Tree{
SerializedType(LockSignalType): Tree{
Hash(LockStateBase, signal.State): nil,
},
}
@ -418,9 +418,9 @@ func (signal *ReadSignal) Permission() Tree {
for _, field := range(fields) {
field_tree[Hash(FieldNameBase, field)] = nil
}
ret[uint64(ext)] = field_tree
ret[SerializedType(ext)] = field_tree
}
return Tree{uint64(ReadSignalType): ret}
return Tree{SerializedType(ReadSignalType): ret}
}
func NewReadSignal(exts map[ExtType][]string) *ReadSignal {
return &ReadSignal{
@ -440,7 +440,7 @@ func (signal *ReadResultSignal) Header() *SignalHeader {
}
func (signal *ReadResultSignal) Permission() Tree {
return Tree{
uint64(ReadResultSignalType): nil,
SerializedType(ReadResultSignalType): nil,
}
}
func NewReadResultSignal(req_id uuid.UUID, node_id NodeID, node_type NodeType, exts map[ExtType]map[string]SerializedValue) *ReadResultSignal {