Moved serialization to serialize.go and removed n parameter from DeserializeValue
parent
06513a5ad6
commit
e2f34150ef
File diff suppressed because it is too large
Load Diff
@ -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
|
||||
}
|
Loading…
Reference in New Issue