Added serialization for Tree and SerializedType. Changed policies to an array instead of a map

gql_cataclysm
noah metz 2023-09-20 19:14:28 -06:00
parent 0fc6215448
commit d4e0d855c7
9 changed files with 303 additions and 255 deletions

@ -942,6 +942,100 @@ func NewContext(db * badger.DB, log Logger) (*Context, error) {
}
*/
err = ctx.RegisterType(reflect.TypeOf(Tree{}), TreeType, func(ctx *Context, ctx_type SerializedType, reflect_type reflect.Type, value *reflect.Value)(SerializedValue,error){
var data []byte
type_stack := []SerializedType{ctx_type}
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 {
data = make([]byte, 8)
map_size := 0
map_iter := value.MapRange()
for map_iter.Next() {
map_size += 1
key_reflect := map_iter.Key()
elem_reflect := map_iter.Value()
key_value, err := SerializeValue(ctx, key_reflect.Type(), &key_reflect)
if err != nil {
return SerializedValue{}, err
}
elem_value, err := SerializeValue(ctx, elem_reflect.Type(), &elem_reflect)
if err != nil {
return SerializedValue{}, err
}
data = append(data, key_value.Data...)
data = append(data, elem_value.Data...)
}
binary.BigEndian.PutUint64(data[0:8], uint64(map_size))
}
return SerializedValue{
type_stack,
data,
}, nil
},func(ctx *Context, value SerializedValue)(reflect.Type,*reflect.Value,SerializedValue,error){
if value.Data == nil {
return reflect.TypeOf(Tree{}), nil, value, nil
} else if len(value.Data) < 8 {
return nil, nil, value, fmt.Errorf("Not enough data to deserialize Tree")
} else {
var map_size_bytes []byte
var err error
map_size_bytes, value, err = value.PopData(8)
if err != nil {
return nil, nil, value, err
}
map_size := binary.BigEndian.Uint64(map_size_bytes)
ctx.Log.Logf("serialize", "Deserializing %d elements in Tree", map_size)
if map_size == 0xFFFFFFFFFFFFFFFF {
reflect_type := reflect.TypeOf(Tree{})
reflect_value := reflect.New(reflect_type).Elem()
return reflect_type, &reflect_value, value, nil
} else if map_size == 0x00 {
reflect_type := reflect.TypeOf(Tree{})
reflect_value := reflect.MakeMap(reflect_type)
return reflect_type, &reflect_value, value, nil
} else {
reflect_type := reflect.TypeOf(Tree{})
reflect_value := reflect.MakeMap(reflect_type)
tmp_value := value
for i := 0; i < int(map_size); i += 1 {
tmp_value.TypeStack = append([]SerializedType{SerializedTypeSerialized, TreeType}, value.TypeStack...)
var key_value, elem_value *reflect.Value
var err error
_, key_value, tmp_value, err = DeserializeValue(ctx, tmp_value)
if err != nil {
return nil, nil, value, err
}
_, elem_value, tmp_value, err = DeserializeValue(ctx, tmp_value)
if err != nil {
return nil, nil, value, err
}
reflect_value.SetMapIndex(*key_value, *elem_value)
}
return reflect_type, &reflect_value, tmp_value, nil
}
}
})
err = ctx.RegisterType(reflect.TypeOf(SerializedType(0)), SerializedTypeSerialized, SerializeUintN(8), DeserializeUintN[SerializedType](8))
if err != nil {
return nil, err
}
err = ctx.RegisterType(reflect.TypeOf(ExtType(0)), ExtTypeSerialized, SerializeUintN(8), DeserializeUintN[ExtType](8))
if err != nil {
return nil, err
@ -1136,6 +1230,11 @@ func NewContext(db * badger.DB, log Logger) (*Context, error) {
return nil, err
}
err = ctx.RegisterSignal(reflect.TypeOf(SuccessSignal{}), SuccessSignalType)
if err != nil {
return nil, err
}
err = ctx.RegisterSignal(reflect.TypeOf(ReadResultSignal{}), ReadResultSignalType)
if err != nil {
return nil, err

@ -65,16 +65,11 @@ func TestGQLServer(t *testing.T) {
fatalErr(t, err)
listener_ext := NewListenerExt(10)
n1, err := NewNode(ctx, nil, TestNodeType, 10, map[PolicyType]Policy{
MemberOfPolicyType: &user_policy_2,
AllNodesPolicyType: &user_policy_1,
}, NewLockableExt(nil))
n1, err := NewNode(ctx, nil, TestNodeType, 10, []Policy{user_policy_2, user_policy_1}, NewLockableExt(nil))
fatalErr(t, err)
gql, err := NewNode(ctx, gql_key, GQLNodeType, 10, map[PolicyType]Policy{
MemberOfPolicyType: &group_policy_2,
AllNodesPolicyType: &group_policy_1,
}, NewLockableExt([]NodeID{n1.ID}), gql_ext, NewGroupExt(map[NodeID]string{
gql, err := NewNode(ctx, gql_key, GQLNodeType, 10, []Policy{group_policy_2, group_policy_1},
NewLockableExt([]NodeID{n1.ID}), gql_ext, NewGroupExt(map[NodeID]string{
n1.ID: "user",
gql_id: "self",
}), listener_ext)

@ -28,10 +28,7 @@ func TestLink(t *testing.T) {
})
l2_listener := NewListenerExt(10)
l2, err := NewNode(ctx, nil, TestLockableType, 10,
map[PolicyType]Policy{
PerNodePolicyType: &policy,
},
l2, err := NewNode(ctx, nil, TestLockableType, 10, []Policy{policy},
l2_listener,
NewLockableExt(nil),
)
@ -77,10 +74,7 @@ func Test10KLink(t *testing.T) {
},
})
NewLockable := func()(*Node) {
l, err := NewNode(ctx, nil, TestLockableType, 10,
map[PolicyType]Policy{
PerNodePolicyType: &child_policy,
},
l, err := NewNode(ctx, nil, TestLockableType, 10, []Policy{child_policy},
NewLockableExt(nil),
)
fatalErr(t, err)
@ -98,10 +92,7 @@ func Test10KLink(t *testing.T) {
SerializedType(LockSignalType): nil,
})
listener := NewListenerExt(100000)
node, err := NewNode(ctx, listener_key, TestLockableType, 10000,
map[PolicyType]Policy{
AllNodesPolicyType: &l_policy,
},
node, err := NewNode(ctx, listener_key, TestLockableType, 10000, []Policy{l_policy},
listener,
NewLockableExt(reqs),
)
@ -132,10 +123,7 @@ func TestLock(t *testing.T) {
NewLockable := func(reqs []NodeID)(*Node, *ListenerExt) {
listener := NewListenerExt(100)
l, err := NewNode(ctx, nil, TestLockableType, 10,
map[PolicyType]Policy{
AllNodesPolicyType: &policy,
},
l, err := NewNode(ctx, nil, TestLockableType, 10, []Policy{policy},
listener,
NewLockableExt(reqs),
)

@ -14,16 +14,6 @@ import (
"crypto/rand"
)
const (
// Magic first four bytes of serialized DB content, stored big endian
NODE_DB_MAGIC = 0x2491df14
// Total length of the node database header, has magic to verify and type_hash to map to load function
NODE_DB_HEADER_LEN = 32
EXTENSION_DB_HEADER_LEN = 16
QSIGNAL_DB_HEADER_LEN = 24
POLICY_DB_HEADER_LEN = 16
)
var (
// Base NodeID, used as a special value
ZeroUUID = uuid.UUID{}
@ -84,7 +74,7 @@ type PendingACL struct {
}
type PendingSignal struct {
Policy PolicyType
Policy uuid.UUID
Found bool
ID uuid.UUID
}
@ -96,7 +86,7 @@ type Node struct {
ID NodeID
Type NodeType `gv:"type"`
Extensions map[ExtType]Extension `gv:"extensions"`
Policies map[PolicyType]Policy `gv:"policies"`
Policies []Policy `gv:"policies"`
PendingACLs map[uuid.UUID]PendingACL `gv:"pending_acls"`
PendingSignals map[uuid.UUID]PendingSignal `gv:"pending_signal"`
@ -134,14 +124,14 @@ const (
Pending
)
func (node *Node) Allows(ctx *Context, principal_id NodeID, action Tree)(map[PolicyType]Messages, RuleResult) {
pends := map[PolicyType]Messages{}
for policy_type, policy := range(node.Policies) {
func (node *Node) Allows(ctx *Context, principal_id NodeID, action Tree)(map[uuid.UUID]Messages, RuleResult) {
pends := map[uuid.UUID]Messages{}
for _, policy := range(node.Policies) {
msgs, resp := policy.Allows(ctx, principal_id, action, node)
if resp == Allow {
return nil, Allow
} else if resp == Pending {
pends[policy_type] = msgs
pends[policy.ID()] = msgs
}
}
if len(pends) != 0 {
@ -370,7 +360,18 @@ func nodeLoop(ctx *Context, node *Node) error {
req_info.Counter -= 1
req_info.Responses = append(req_info.Responses, signal)
allowed := node.Policies[info.Policy].ContinueAllows(ctx, req_info, signal)
idx := -1
for i, p := range(node.Policies) {
if p.ID() == info.Policy {
idx = i
break
}
}
if idx == -1 {
ctx.Log.Logf("policy", "PENDING_FOR_NONEXISTENT_POLICY: %s - %s", node.ID, info.Policy)
delete(node.PendingACLs, info.ID)
} else {
allowed := node.Policies[idx].ContinueAllows(ctx, req_info, signal)
if allowed == Allow {
ctx.Log.Logf("policy", "DELAYED_POLICY_ALLOW: %s - %s", node.ID, req_info.Signal)
signal = req_info.Signal
@ -401,6 +402,7 @@ func nodeLoop(ctx *Context, node *Node) error {
}
}
}
}
switch sig := signal.(type) {
case *StopSignal:
@ -544,7 +546,7 @@ func KeyID(pub ed25519.PublicKey) NodeID {
}
// Create a new node in memory and start it's event loop
func NewNode(ctx *Context, key ed25519.PrivateKey, node_type NodeType, buffer_size uint32, policies map[PolicyType]Policy, extensions ...Extension) (*Node, error) {
func NewNode(ctx *Context, key ed25519.PrivateKey, node_type NodeType, buffer_size uint32, policies []Policy, extensions ...Extension) (*Node, error) {
var err error
var public ed25519.PublicKey
if key == nil {
@ -586,22 +588,7 @@ func NewNode(ctx *Context, key ed25519.PrivateKey, node_type NodeType, buffer_si
}
}
if policies == nil {
policies = map[PolicyType]Policy{}
}
default_policy := NewAllNodesPolicy(Tree{
SerializedType(ErrorSignalType): nil,
SerializedType(ReadResultSignalType): nil,
SerializedType(StatusSignalType): nil,
})
all_nodes_policy, exists := policies[AllNodesPolicyType]
if exists == true {
policies[AllNodesPolicyType] = all_nodes_policy.Merge(&default_policy)
} else {
policies[AllNodesPolicyType] = &default_policy
}
policies = append(policies, DefaultPolicy)
node := &Node{
Key: key,

@ -63,9 +63,7 @@ func TestNodeRead(t *testing.T) {
n2, err := NewNode(ctx, n2_key, node_type, 10, nil, NewGroupExt(nil), n2_listener)
fatalErr(t, err)
n1, err := NewNode(ctx, n1_key, node_type, 10, map[PolicyType]Policy{
PerNodePolicyType: &n1_policy,
}, NewGroupExt(nil))
n1, err := NewNode(ctx, n1_key, node_type, 10, []Policy{n1_policy}, NewGroupExt(nil))
fatalErr(t, err)
read_sig := NewReadSignal(map[ExtType][]string{

@ -1,15 +1,21 @@
package graphvent
import (
"github.com/google/uuid"
)
type Policy interface {
Allows(ctx *Context, principal_id NodeID, action Tree, node *Node)(Messages, RuleResult)
ContinueAllows(ctx *Context, current PendingACL, signal Signal)RuleResult
// Merge with another policy of the same underlying type
Merge(Policy) Policy
// Make a copy of this policy
Copy() Policy
ID() uuid.UUID
}
type PolicyHeader struct {
UUID uuid.UUID `gv:"uuid"`
}
func (header PolicyHeader) ID() uuid.UUID {
return header.UUID
}
func (policy AllNodesPolicy) Allows(ctx *Context, principal_id NodeID, action Tree, node *Node)(Messages, RuleResult) {
@ -38,10 +44,6 @@ type RequirementOfPolicy struct {
PerNodePolicy
}
func (policy RequirementOfPolicy) Type() PolicyType {
return RequirementOfPolicyType
}
func NewRequirementOfPolicy(dep_rules map[NodeID]Tree) RequirementOfPolicy {
return RequirementOfPolicy {
PerNodePolicy: NewPerNodePolicy(dep_rules),
@ -87,10 +89,6 @@ type MemberOfPolicy struct {
PerNodePolicy
}
func (policy MemberOfPolicy) Type() PolicyType {
return MemberOfPolicyType
}
func NewMemberOfPolicy(group_rules map[NodeID]Tree) MemberOfPolicy {
return MemberOfPolicy{
PerNodePolicy: NewPerNodePolicy(group_rules),
@ -156,19 +154,6 @@ func (policy MemberOfPolicy) Allows(ctx *Context, principal_id NodeID, action Tr
return msgs, Pending
}
func (policy MemberOfPolicy) Merge(p Policy) Policy {
other := p.(*MemberOfPolicy)
policy.NodeRules = MergeNodeRules(policy.NodeRules, other.NodeRules)
return policy
}
func (policy MemberOfPolicy) Copy() Policy {
new_rules := CopyNodeRules(policy.NodeRules)
return &MemberOfPolicy{
PerNodePolicy: NewPerNodePolicy(new_rules),
}
}
func CopyTree(tree Tree) Tree {
if tree == nil {
return nil
@ -199,56 +184,6 @@ func MergeTrees(first Tree, second Tree) Tree {
return ret
}
func CopyNodeRules(rules map[NodeID]Tree) map[NodeID]Tree {
ret := map[NodeID]Tree{}
for id, r := range(rules) {
ret[id] = r
}
return ret
}
func MergeNodeRules(first map[NodeID]Tree, second map[NodeID]Tree) map[NodeID]Tree {
merged := map[NodeID]Tree{}
for id, actions := range(first) {
merged[id] = actions
}
for id, actions := range(second) {
existing, exists := merged[id]
if exists {
merged[id] = MergeTrees(existing, actions)
} else {
merged[id] = actions
}
}
return merged
}
func (policy PerNodePolicy) Merge(p Policy) Policy {
other := p.(*PerNodePolicy)
policy.NodeRules = MergeNodeRules(policy.NodeRules, other.NodeRules)
return policy
}
func (policy PerNodePolicy) Copy() Policy {
new_rules := CopyNodeRules(policy.NodeRules)
return &PerNodePolicy{
NodeRules: new_rules,
}
}
func (policy AllNodesPolicy) Merge(p Policy) Policy {
other := p.(*AllNodesPolicy)
policy.Rules = MergeTrees(policy.Rules, other.Rules)
return policy
}
func (policy AllNodesPolicy) Copy() Policy {
new_rules := policy.Rules
return &AllNodesPolicy {
Rules: new_rules,
}
}
type Tree map[SerializedType]Tree
func (rule Tree) Allows(action Tree) RuleResult {
@ -278,39 +213,40 @@ func (rule Tree) Allows(action Tree) RuleResult {
}
}
func NewPolicyHeader() PolicyHeader {
return PolicyHeader{
UUID: uuid.New(),
}
}
func NewPerNodePolicy(node_actions map[NodeID]Tree) PerNodePolicy {
if node_actions == nil {
node_actions = map[NodeID]Tree{}
}
return PerNodePolicy{
PolicyHeader: NewPolicyHeader(),
NodeRules: node_actions,
}
}
type PerNodePolicy struct {
NodeRules map[NodeID]Tree `json:"node_actions"`
}
func (policy PerNodePolicy) Type() PolicyType {
return PerNodePolicyType
PolicyHeader
NodeRules map[NodeID]Tree `gv:"node_rules"`
}
func NewAllNodesPolicy(rules Tree) AllNodesPolicy {
return AllNodesPolicy{
PolicyHeader: NewPolicyHeader(),
Rules: rules,
}
}
type AllNodesPolicy struct {
Rules Tree
}
func (policy AllNodesPolicy) Type() PolicyType {
return AllNodesPolicyType
PolicyHeader
Rules Tree `gv:"rules"`
}
var DefaultPolicy = NewAllNodesPolicy(Tree{
SerializedType(ErrorSignalType): nil,
SerializedType(ReadResultSignalType): nil,
ResultType: nil,
})

@ -26,26 +26,31 @@ func Hash(base string, name string) SerializedType {
}
type SerializedType uint64
func (t SerializedType) String() string {
return fmt.Sprintf("0x%x", uint64(t))
}
type ExtType SerializedType
func (t ExtType) String() string {
return fmt.Sprintf("0x%x", uint64(t))
}
type NodeType SerializedType
func (t NodeType) String() string {
return fmt.Sprintf("0x%x", uint64(t))
}
type SignalType SerializedType
func (t SignalType) String() string {
return fmt.Sprintf("0x%x", uint64(t))
}
type PolicyType SerializedType
func (t PolicyType) String() string {
return fmt.Sprintf("0x%x", uint64(t))
}
@ -84,13 +89,14 @@ var (
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")
ErrorSignalType = NewSignalType("ERROR")
SuccessSignalType = NewSignalType("SUCCESS")
ReadResultSignalType = NewSignalType("READ_RESULT")
MemberOfPolicyType = NewPolicyType("USER_OF")
RequirementOfPolicyType = NewPolicyType("REQUIEMENT_OF")
@ -134,6 +140,9 @@ var (
PendingACLType = NewSerializedType("PENDING_ACL")
PendingSignalType = NewSerializedType("PENDING_SIGNAL")
TimeType = NewSerializedType("TIME")
ResultType = NewSerializedType("RESULT")
TreeType = NewSerializedType("TREE")
SerializedTypeSerialized = NewSerializedType("SERIALIZED_TYPE")
)
func SerializeArray(ctx *Context, ctx_type SerializedType, reflect_type reflect.Type, value *reflect.Value) (SerializedValue, error) {
@ -164,7 +173,7 @@ func SerializeArray(ctx *Context, ctx_type SerializedType, reflect_type reflect.
}
}
func DeserializeArray[T any](ctx *Context)(func(ctx *Context, value SerializedValue)(reflect.Type,*reflect.Value,SerializedValue,error)){
func DeserializeArray[T any](ctx *Context) func(ctx *Context, value SerializedValue) (reflect.Type, *reflect.Value, SerializedValue, error) {
var zero T
array_type := reflect.TypeOf(zero)
array_size := array_type.Len()
@ -198,7 +207,7 @@ func DeserializeArray[T any](ctx *Context)(func(ctx *Context, value SerializedVa
}
}
func SerializeUintN(size int)(func(*Context,SerializedType,reflect.Type,*reflect.Value)(SerializedValue,error)){
func SerializeUintN(size int) func(*Context, SerializedType, reflect.Type, *reflect.Value) (SerializedValue, error) {
var fill_data func([]byte, uint64) = nil
switch size {
case 1:
@ -233,7 +242,9 @@ func SerializeUintN(size int)(func(*Context,SerializedType,reflect.Type,*reflect
}
}
func DeserializeUintN[T interface{~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64}](size int)(func(ctx *Context, value SerializedValue)(reflect.Type,*reflect.Value,SerializedValue,error)){
func DeserializeUintN[T interface {
~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64
}](size int) func(ctx *Context, value SerializedValue) (reflect.Type, *reflect.Value, SerializedValue, error) {
var get_uint func([]byte) uint64
switch size {
case 1:
@ -274,7 +285,7 @@ func DeserializeUintN[T interface{~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64}]
}
}
func SerializeIntN(size int)(func(ctx *Context, ctx_type SerializedType, reflect_type reflect.Type, value *reflect.Value)(SerializedValue,error)){
func SerializeIntN(size int) func(ctx *Context, ctx_type SerializedType, reflect_type reflect.Type, value *reflect.Value) (SerializedValue, error) {
var fill_data func([]byte, int64) = nil
switch size {
case 1:
@ -309,7 +320,9 @@ func SerializeIntN(size int)(func(ctx *Context, ctx_type SerializedType, reflect
}
}
func DeserializeIntN[T interface{~int | ~int8 | ~int16 | ~int32 | ~int64}](size int)(func(ctx *Context, value SerializedValue)(reflect.Type,*reflect.Value,SerializedValue,error)){
func DeserializeIntN[T interface {
~int | ~int8 | ~int16 | ~int32 | ~int64
}](size int) func(ctx *Context, value SerializedValue) (reflect.Type, *reflect.Value, SerializedValue, error) {
var get_int func([]byte) int64
switch size {
case 1:
@ -373,7 +386,7 @@ var DeserializableType = reflect.TypeOf(&deserializable_zero).Elem()
func structInfo(ctx *Context, struct_type reflect.Type) StructInfo {
field_order := []SerializedType{}
field_map := map[SerializedType]FieldInfo{}
for _, field := range(reflect.VisibleFields(struct_type)) {
for _, field := range reflect.VisibleFields(struct_type) {
gv_tag, tagged_gv := field.Tag.Lookup("gv")
if tagged_gv == false {
continue
@ -423,7 +436,7 @@ func structInfo(ctx *Context, struct_type reflect.Type)StructInfo{
}
}
func SerializeStruct(ctx *Context, struct_type reflect.Type)(func(*Context,SerializedType,reflect.Type,*reflect.Value)(SerializedValue,error)){
func SerializeStruct(ctx *Context, struct_type reflect.Type) func(*Context, SerializedType, reflect.Type, *reflect.Value) (SerializedValue, error) {
struct_info := structInfo(ctx, struct_type)
return func(ctx *Context, ctx_type SerializedType, reflect_type reflect.Type, value *reflect.Value) (SerializedValue, error) {
type_stack := []SerializedType{ctx_type}
@ -432,7 +445,7 @@ func SerializeStruct(ctx *Context, struct_type reflect.Type)(func(*Context,Seria
data = nil
} else {
data = make([]byte, 8)
for _, field_hash := range(struct_info.FieldOrder) {
for _, field_hash := range struct_info.FieldOrder {
field_hash_bytes := make([]byte, 8)
binary.BigEndian.PutUint64(field_hash_bytes, uint64(field_hash))
field_info := struct_info.FieldMap[field_hash]
@ -453,7 +466,7 @@ func SerializeStruct(ctx *Context, struct_type reflect.Type)(func(*Context,Seria
}
}
func DeserializeStruct(ctx *Context, struct_type reflect.Type)(func(*Context,SerializedValue)(reflect.Type,*reflect.Value,SerializedValue,error)){
func DeserializeStruct(ctx *Context, struct_type reflect.Type) func(*Context, SerializedValue) (reflect.Type, *reflect.Value, SerializedValue, error) {
struct_info := structInfo(ctx, struct_type)
return func(ctx *Context, value SerializedValue) (reflect.Type, *reflect.Value, SerializedValue, error) {
if value.Data == nil {
@ -537,7 +550,7 @@ func SerializeInterface(ctx *Context, ctx_type SerializedType, reflect_type refl
}, nil
}
func DeserializeInterface[T any]()(func(*Context,SerializedValue)(reflect.Type,*reflect.Value,SerializedValue,error)){
func DeserializeInterface[T any]() func(*Context, SerializedValue) (reflect.Type, *reflect.Value, SerializedValue, error) {
return func(ctx *Context, value SerializedValue) (reflect.Type, *reflect.Value, SerializedValue, error) {
var interface_zero T
var interface_type = reflect.ValueOf(&interface_zero).Type().Elem()
@ -641,7 +654,7 @@ func ExtField(ctx *Context, ext Extension, field_name string) (reflect.Value, er
}
ext_value := reflect.ValueOf(ext).Elem()
for _, field := range(reflect.VisibleFields(ext_value.Type())) {
for _, field := range reflect.VisibleFields(ext_value.Type()) {
gv_tag, tagged := field.Tag.Lookup("gv")
if tagged == true && gv_tag == field_name {
return ext_value.FieldByIndex(field.Index), nil
@ -665,7 +678,7 @@ func (value SerializedValue) MarshalBinary() ([]byte, error) {
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) {
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))

@ -7,7 +7,7 @@ import (
)
func TestSerializeBasic(t *testing.T) {
ctx := logTestContext(t, []string{"test"})
ctx := logTestContext(t, []string{"test", "serialize"})
testSerializeComparable[string](t, ctx, "test")
testSerializeComparable[bool](t, ctx, true)
testSerializeComparable[float32](t, ctx, 0.05)
@ -59,6 +59,18 @@ func TestSerializeBasic(t *testing.T) {
12345,
"test_string",
})
testSerialize(t, ctx, Tree{
TreeType: nil,
})
testSerialize(t, ctx, Tree{
TreeType: {
ErrorType: Tree{},
MapType: nil,
},
StringType: nil,
})
}
type test struct {

@ -144,13 +144,31 @@ func NewStopSignal() *StopSignal {
}
}
type SuccessSignal struct {
SignalHeader
}
func (signal SuccessSignal) Permission() Tree {
return Tree{
ResultType: {
SerializedType(SuccessSignalType): nil,
},
}
}
func NewSuccessSignal(req_id uuid.UUID) Signal {
return &SuccessSignal{
NewRespHeader(req_id, Direct),
}
}
type ErrorSignal struct {
SignalHeader
Error string
}
func (signal ErrorSignal) Permission() Tree {
return Tree{
ResultType: {
SerializedType(ErrorSignalType): nil,
},
}
}
func NewErrorSignal(req_id uuid.UUID, fmt_string string, args ...interface{}) Signal {
@ -275,7 +293,9 @@ type ReadResultSignal struct {
}
func (signal ReadResultSignal) Permission() Tree {
return Tree{
ResultType: {
SerializedType(ReadResultSignalType): nil,
},
}
}
func NewReadResultSignal(req_id uuid.UUID, node_id NodeID, node_type NodeType, exts map[ExtType]map[string]SerializedValue) *ReadResultSignal {