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)) err = ctx.RegisterType(reflect.TypeOf(ExtType(0)), ExtTypeSerialized, SerializeUintN(8), DeserializeUintN[ExtType](8))
if err != nil { if err != nil {
return nil, err return nil, err
@ -1136,6 +1230,11 @@ func NewContext(db * badger.DB, log Logger) (*Context, error) {
return nil, err return nil, err
} }
err = ctx.RegisterSignal(reflect.TypeOf(SuccessSignal{}), SuccessSignalType)
if err != nil {
return nil, err
}
err = ctx.RegisterSignal(reflect.TypeOf(ReadResultSignal{}), ReadResultSignalType) err = ctx.RegisterSignal(reflect.TypeOf(ReadResultSignal{}), ReadResultSignalType)
if err != nil { if err != nil {
return nil, err return nil, err

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

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

@ -14,16 +14,6 @@ import (
"crypto/rand" "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 ( var (
// Base NodeID, used as a special value // Base NodeID, used as a special value
ZeroUUID = uuid.UUID{} ZeroUUID = uuid.UUID{}
@ -84,7 +74,7 @@ type PendingACL struct {
} }
type PendingSignal struct { type PendingSignal struct {
Policy PolicyType Policy uuid.UUID
Found bool Found bool
ID uuid.UUID ID uuid.UUID
} }
@ -96,7 +86,7 @@ type Node struct {
ID NodeID ID NodeID
Type NodeType `gv:"type"` Type NodeType `gv:"type"`
Extensions map[ExtType]Extension `gv:"extensions"` Extensions map[ExtType]Extension `gv:"extensions"`
Policies map[PolicyType]Policy `gv:"policies"` Policies []Policy `gv:"policies"`
PendingACLs map[uuid.UUID]PendingACL `gv:"pending_acls"` PendingACLs map[uuid.UUID]PendingACL `gv:"pending_acls"`
PendingSignals map[uuid.UUID]PendingSignal `gv:"pending_signal"` PendingSignals map[uuid.UUID]PendingSignal `gv:"pending_signal"`
@ -134,14 +124,14 @@ const (
Pending Pending
) )
func (node *Node) Allows(ctx *Context, principal_id NodeID, action Tree)(map[PolicyType]Messages, RuleResult) { func (node *Node) Allows(ctx *Context, principal_id NodeID, action Tree)(map[uuid.UUID]Messages, RuleResult) {
pends := map[PolicyType]Messages{} pends := map[uuid.UUID]Messages{}
for policy_type, policy := range(node.Policies) { for _, policy := range(node.Policies) {
msgs, resp := policy.Allows(ctx, principal_id, action, node) msgs, resp := policy.Allows(ctx, principal_id, action, node)
if resp == Allow { if resp == Allow {
return nil, Allow return nil, Allow
} else if resp == Pending { } else if resp == Pending {
pends[policy_type] = msgs pends[policy.ID()] = msgs
} }
} }
if len(pends) != 0 { if len(pends) != 0 {
@ -370,7 +360,18 @@ func nodeLoop(ctx *Context, node *Node) error {
req_info.Counter -= 1 req_info.Counter -= 1
req_info.Responses = append(req_info.Responses, signal) 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 { if allowed == Allow {
ctx.Log.Logf("policy", "DELAYED_POLICY_ALLOW: %s - %s", node.ID, req_info.Signal) ctx.Log.Logf("policy", "DELAYED_POLICY_ALLOW: %s - %s", node.ID, req_info.Signal)
signal = req_info.Signal signal = req_info.Signal
@ -401,6 +402,7 @@ func nodeLoop(ctx *Context, node *Node) error {
} }
} }
} }
}
switch sig := signal.(type) { switch sig := signal.(type) {
case *StopSignal: case *StopSignal:
@ -544,7 +546,7 @@ func KeyID(pub ed25519.PublicKey) NodeID {
} }
// Create a new node in memory and start it's event loop // 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 err error
var public ed25519.PublicKey var public ed25519.PublicKey
if key == nil { if key == nil {
@ -586,22 +588,7 @@ func NewNode(ctx *Context, key ed25519.PrivateKey, node_type NodeType, buffer_si
} }
} }
if policies == nil { policies = append(policies, DefaultPolicy)
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
}
node := &Node{ node := &Node{
Key: key, 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) n2, err := NewNode(ctx, n2_key, node_type, 10, nil, NewGroupExt(nil), n2_listener)
fatalErr(t, err) fatalErr(t, err)
n1, err := NewNode(ctx, n1_key, node_type, 10, map[PolicyType]Policy{ n1, err := NewNode(ctx, n1_key, node_type, 10, []Policy{n1_policy}, NewGroupExt(nil))
PerNodePolicyType: &n1_policy,
}, NewGroupExt(nil))
fatalErr(t, err) fatalErr(t, err)
read_sig := NewReadSignal(map[ExtType][]string{ read_sig := NewReadSignal(map[ExtType][]string{

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

@ -26,26 +26,31 @@ func Hash(base string, name string) SerializedType {
} }
type SerializedType uint64 type SerializedType uint64
func (t SerializedType) String() string { func (t SerializedType) String() string {
return fmt.Sprintf("0x%x", uint64(t)) return fmt.Sprintf("0x%x", uint64(t))
} }
type ExtType SerializedType type ExtType SerializedType
func (t ExtType) String() string { func (t ExtType) String() string {
return fmt.Sprintf("0x%x", uint64(t)) return fmt.Sprintf("0x%x", uint64(t))
} }
type NodeType SerializedType type NodeType SerializedType
func (t NodeType) String() string { func (t NodeType) String() string {
return fmt.Sprintf("0x%x", uint64(t)) return fmt.Sprintf("0x%x", uint64(t))
} }
type SignalType SerializedType type SignalType SerializedType
func (t SignalType) String() string { func (t SignalType) String() string {
return fmt.Sprintf("0x%x", uint64(t)) return fmt.Sprintf("0x%x", uint64(t))
} }
type PolicyType SerializedType type PolicyType SerializedType
func (t PolicyType) String() string { func (t PolicyType) String() string {
return fmt.Sprintf("0x%x", uint64(t)) return fmt.Sprintf("0x%x", uint64(t))
} }
@ -84,13 +89,14 @@ var (
StopSignalType = NewSignalType("STOP") StopSignalType = NewSignalType("STOP")
CreateSignalType = NewSignalType("CREATE") CreateSignalType = NewSignalType("CREATE")
StartSignalType = NewSignalType("START") StartSignalType = NewSignalType("START")
ErrorSignalType = NewSignalType("ERROR")
StatusSignalType = NewSignalType("STATUS") StatusSignalType = NewSignalType("STATUS")
LinkSignalType = NewSignalType("LINK") LinkSignalType = NewSignalType("LINK")
LockSignalType = NewSignalType("LOCK") LockSignalType = NewSignalType("LOCK")
ReadSignalType = NewSignalType("READ") ReadSignalType = NewSignalType("READ")
ReadResultSignalType = NewSignalType("READ_RESULT")
ACLTimeoutSignalType = NewSignalType("ACL_TIMEOUT") ACLTimeoutSignalType = NewSignalType("ACL_TIMEOUT")
ErrorSignalType = NewSignalType("ERROR")
SuccessSignalType = NewSignalType("SUCCESS")
ReadResultSignalType = NewSignalType("READ_RESULT")
MemberOfPolicyType = NewPolicyType("USER_OF") MemberOfPolicyType = NewPolicyType("USER_OF")
RequirementOfPolicyType = NewPolicyType("REQUIEMENT_OF") RequirementOfPolicyType = NewPolicyType("REQUIEMENT_OF")
@ -134,6 +140,9 @@ var (
PendingACLType = NewSerializedType("PENDING_ACL") PendingACLType = NewSerializedType("PENDING_ACL")
PendingSignalType = NewSerializedType("PENDING_SIGNAL") PendingSignalType = NewSerializedType("PENDING_SIGNAL")
TimeType = NewSerializedType("TIME") 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) { 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 var zero T
array_type := reflect.TypeOf(zero) array_type := reflect.TypeOf(zero)
array_size := array_type.Len() 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 var fill_data func([]byte, uint64) = nil
switch size { switch size {
case 1: 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 var get_uint func([]byte) uint64
switch size { switch size {
case 1: 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 var fill_data func([]byte, int64) = nil
switch size { switch size {
case 1: 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 var get_int func([]byte) int64
switch size { switch size {
case 1: case 1:
@ -373,7 +386,7 @@ var DeserializableType = reflect.TypeOf(&deserializable_zero).Elem()
func structInfo(ctx *Context, struct_type reflect.Type) StructInfo { func structInfo(ctx *Context, struct_type reflect.Type) StructInfo {
field_order := []SerializedType{} field_order := []SerializedType{}
field_map := map[SerializedType]FieldInfo{} 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") gv_tag, tagged_gv := field.Tag.Lookup("gv")
if tagged_gv == false { if tagged_gv == false {
continue 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) struct_info := structInfo(ctx, struct_type)
return func(ctx *Context, ctx_type SerializedType, reflect_type reflect.Type, value *reflect.Value) (SerializedValue, error) { return func(ctx *Context, ctx_type SerializedType, reflect_type reflect.Type, value *reflect.Value) (SerializedValue, error) {
type_stack := []SerializedType{ctx_type} type_stack := []SerializedType{ctx_type}
@ -432,7 +445,7 @@ func SerializeStruct(ctx *Context, struct_type reflect.Type)(func(*Context,Seria
data = nil data = nil
} else { } else {
data = make([]byte, 8) data = make([]byte, 8)
for _, field_hash := range(struct_info.FieldOrder) { for _, field_hash := range struct_info.FieldOrder {
field_hash_bytes := make([]byte, 8) field_hash_bytes := make([]byte, 8)
binary.BigEndian.PutUint64(field_hash_bytes, uint64(field_hash)) binary.BigEndian.PutUint64(field_hash_bytes, uint64(field_hash))
field_info := struct_info.FieldMap[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) struct_info := structInfo(ctx, struct_type)
return func(ctx *Context, value SerializedValue) (reflect.Type, *reflect.Value, SerializedValue, error) { return func(ctx *Context, value SerializedValue) (reflect.Type, *reflect.Value, SerializedValue, error) {
if value.Data == nil { if value.Data == nil {
@ -537,7 +550,7 @@ func SerializeInterface(ctx *Context, ctx_type SerializedType, reflect_type refl
}, nil }, 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) { return func(ctx *Context, value SerializedValue) (reflect.Type, *reflect.Value, SerializedValue, error) {
var interface_zero T var interface_zero T
var interface_type = reflect.ValueOf(&interface_zero).Type().Elem() 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() 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") gv_tag, tagged := field.Tag.Lookup("gv")
if tagged == true && gv_tag == field_name { if tagged == true && gv_tag == field_name {
return ext_value.FieldByIndex(field.Index), nil 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[0:8], uint64(len(value.TypeStack)))
binary.BigEndian.PutUint64(data[8:16], uint64(len(value.Data))) 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_start := (i + 2) * 8
type_end := (i + 3) * 8 type_end := (i + 3) * 8
binary.BigEndian.PutUint64(data[type_start:type_end], uint64(t)) binary.BigEndian.PutUint64(data[type_start:type_end], uint64(t))

@ -7,7 +7,7 @@ import (
) )
func TestSerializeBasic(t *testing.T) { func TestSerializeBasic(t *testing.T) {
ctx := logTestContext(t, []string{"test"}) ctx := logTestContext(t, []string{"test", "serialize"})
testSerializeComparable[string](t, ctx, "test") testSerializeComparable[string](t, ctx, "test")
testSerializeComparable[bool](t, ctx, true) testSerializeComparable[bool](t, ctx, true)
testSerializeComparable[float32](t, ctx, 0.05) testSerializeComparable[float32](t, ctx, 0.05)
@ -59,6 +59,18 @@ func TestSerializeBasic(t *testing.T) {
12345, 12345,
"test_string", "test_string",
}) })
testSerialize(t, ctx, Tree{
TreeType: nil,
})
testSerialize(t, ctx, Tree{
TreeType: {
ErrorType: Tree{},
MapType: nil,
},
StringType: nil,
})
} }
type test struct { 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 { type ErrorSignal struct {
SignalHeader SignalHeader
Error string Error string
} }
func (signal ErrorSignal) Permission() Tree { func (signal ErrorSignal) Permission() Tree {
return Tree{ return Tree{
ResultType: {
SerializedType(ErrorSignalType): nil, SerializedType(ErrorSignalType): nil,
},
} }
} }
func NewErrorSignal(req_id uuid.UUID, fmt_string string, args ...interface{}) Signal { func NewErrorSignal(req_id uuid.UUID, fmt_string string, args ...interface{}) Signal {
@ -275,7 +293,9 @@ type ReadResultSignal struct {
} }
func (signal ReadResultSignal) Permission() Tree { func (signal ReadResultSignal) Permission() Tree {
return Tree{ return Tree{
ResultType: {
SerializedType(ReadResultSignalType): nil, SerializedType(ReadResultSignalType): nil,
},
} }
} }
func NewReadResultSignal(req_id uuid.UUID, node_id NodeID, node_type NodeType, exts map[ExtType]map[string]SerializedValue) *ReadResultSignal { func NewReadResultSignal(req_id uuid.UUID, node_id NodeID, node_type NodeType, exts map[ExtType]map[string]SerializedValue) *ReadResultSignal {