2023-07-09 14:30:30 -06:00
package graphvent
import (
2023-09-02 17:30:52 -06:00
"crypto/ecdh"
"crypto/sha512"
"encoding/binary"
"errors"
"fmt"
"reflect"
"runtime"
"sync"
"strconv"
badger "github.com/dgraph-io/badger/v3"
2023-08-31 19:50:32 -06:00
)
2023-07-27 23:15:58 -06:00
2023-08-31 19:50:32 -06:00
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 ] )
2023-07-27 23:15:58 -06:00
}
2023-08-31 19:50:32 -06:00
type ExtType uint64
type NodeType uint64
type SignalType uint64
type PolicyType uint64
type SerializedType uint64
2023-07-27 23:26:58 -06:00
2023-08-31 19:50:32 -06:00
func NewExtType ( name string ) ExtType {
return ExtType ( Hash ( ExtTypeBase , name ) )
}
2023-08-01 20:55:15 -06:00
2023-08-31 19:50:32 -06:00
func NewNodeType ( name string ) NodeType {
return NodeType ( Hash ( NodeTypeBase , name ) )
2023-08-01 20:55:15 -06:00
}
2023-07-27 16:06:56 -06:00
2023-08-31 19:50:32 -06:00
func NewSignalType ( name string ) SignalType {
return SignalType ( Hash ( SignalTypeBase , name ) )
}
2023-08-07 20:26:02 -06:00
2023-08-31 19:50:32 -06:00
func NewPolicyType ( name string ) PolicyType {
return PolicyType ( Hash ( PolicyTypeBase , name ) )
2023-08-07 20:26:02 -06:00
}
2023-08-31 19:50:32 -06:00
func NewSerializedType ( name string ) SerializedType {
2023-08-31 22:31:29 -06:00
val := SerializedType ( Hash ( SerializedTypeBase , name ) )
println ( fmt . Sprintf ( "TYPE: %s: %d" , name , val ) )
return val
2023-08-07 20:26:02 -06:00
}
2023-07-27 23:15:58 -06:00
const (
2023-09-02 17:30:52 -06:00
TagBase = "GraphventTag"
2023-08-31 19:50:32 -06:00
ExtTypeBase = "ExtType"
NodeTypeBase = "NodeType"
SignalTypeBase = "SignalType"
PolicyTypeBase = "PolicyType"
SerializedTypeBase = "SerializedType"
FieldNameBase = "FieldName"
2023-07-27 23:15:58 -06:00
)
2023-07-28 00:04:18 -06:00
var (
2023-08-31 19:50:32 -06:00
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" )
2023-09-02 18:49:37 -06:00
ErrorType = NewSerializedType ( "ERROR" )
2023-08-31 19:50:32 -06:00
2023-07-28 00:04:18 -06:00
NodeNotFoundError = errors . New ( "Node not found in DB" )
2023-08-07 20:26:02 -06:00
ECDH = ecdh . X25519 ( )
2023-07-28 00:04:18 -06:00
)
2023-08-31 19:50:32 -06:00
type ExtensionInfo struct {
Type reflect . Type
Data interface { }
}
2023-08-01 20:55:15 -06:00
2023-08-31 19:50:32 -06:00
type NodeInfo struct {
Extensions [ ] ExtType
2023-08-01 20:55:15 -06:00
}
2023-07-29 00:28:44 -06:00
2023-09-02 17:30:52 -06:00
type TypeSerialize func ( * Context , uint64 , reflect . Type , * reflect . Value ) ( SerializedValue , error )
2023-09-02 18:49:37 -06:00
type TypeDeserialize func ( * Context , [ ] uint64 , [ ] byte ) ( reflect . Type , * reflect . Value , [ ] byte , error )
2023-08-31 19:50:32 -06:00
type TypeInfo struct {
Type reflect . Type
Serialize TypeSerialize
Deserialize TypeDeserialize
2023-07-29 00:28:44 -06:00
}
2023-07-27 16:06:56 -06:00
// A Context stores all the data to run a graphvent process
2023-07-09 14:30:30 -06:00
type Context struct {
2023-07-10 22:31:43 -06:00
// DB is the database connection used to load and write nodes
2023-07-09 14:30:30 -06:00
DB * badger . DB
2023-07-27 16:06:56 -06:00
// Logging interface
2023-07-09 14:30:30 -06:00
Log Logger
2023-07-27 16:06:56 -06:00
// Map between database extension hashes and the registered info
2023-08-31 19:50:32 -06:00
Extensions map [ ExtType ] ExtensionInfo
ExtensionTypes map [ reflect . Type ] ExtType
2023-08-07 20:26:02 -06:00
// Map between databse policy hashes and the registered info
2023-08-31 19:50:32 -06:00
Policies map [ PolicyType ] reflect . Type
PolicyTypes map [ reflect . Type ] PolicyType
2023-07-29 00:28:44 -06:00
// Map between serialized signal hashes and the registered info
2023-08-31 19:50:32 -06:00
Signals map [ SignalType ] reflect . Type
SignalTypes map [ reflect . Type ] SignalType
2023-07-27 16:06:56 -06:00
// Map between database type hashes and the registered info
2023-08-31 19:50:32 -06:00
Nodes map [ NodeType ] NodeInfo
// Map between go types and registered info
Types map [ SerializedType ] TypeInfo
TypeReflects map [ reflect . Type ] SerializedType
2023-09-02 17:30:52 -06:00
Kinds map [ reflect . Kind ] KindInfo
KindTypes map [ SerializedType ] reflect . Kind
2023-07-27 16:06:56 -06:00
// Routing map to all the nodes local to this context
2023-08-31 19:50:32 -06:00
nodeMapLock sync . RWMutex
nodeMap map [ NodeID ] * Node
2023-07-10 21:15:01 -06:00
}
2023-07-27 16:06:56 -06:00
// Register a NodeType to the context, with the list of extensions it requires
2023-07-26 00:42:12 -06:00
func ( ctx * Context ) RegisterNodeType ( node_type NodeType , extensions [ ] ExtType ) error {
2023-08-31 19:50:32 -06:00
_ , exists := ctx . Nodes [ node_type ]
2023-07-26 00:18:11 -06:00
if exists == true {
2023-08-31 19:50:32 -06:00
return fmt . Errorf ( "Cannot register node type %+v, type already exists in context" , node_type )
2023-07-26 00:18:11 -06:00
}
2023-07-26 00:42:12 -06:00
ext_found := map [ ExtType ] bool { }
for _ , extension := range ( extensions ) {
2023-08-31 19:50:32 -06:00
_ , in_ctx := ctx . Extensions [ extension ]
2023-07-26 00:42:12 -06:00
if in_ctx == false {
2023-08-31 19:50:32 -06:00
return fmt . Errorf ( "Cannot register node type %+v, required extension %+v not in context" , node_type , extension )
2023-07-26 00:42:12 -06:00
}
_ , duplicate := ext_found [ extension ]
if duplicate == true {
2023-08-31 19:50:32 -06:00
return fmt . Errorf ( "Duplicate extension %+v found in extension list" , extension )
2023-07-26 00:42:12 -06:00
}
ext_found [ extension ] = true
}
2023-08-31 19:50:32 -06:00
ctx . Nodes [ node_type ] = NodeInfo {
2023-07-26 00:42:12 -06:00
Extensions : extensions ,
2023-07-26 00:18:11 -06:00
}
return nil
}
2023-08-31 19:50:32 -06:00
func ( ctx * Context ) RegisterPolicy ( reflect_type reflect . Type , policy_type PolicyType ) error {
_ , exists := ctx . Policies [ policy_type ]
2023-07-29 00:28:44 -06:00
if exists == true {
2023-08-31 19:50:32 -06:00
return fmt . Errorf ( "Cannot register policy of type %+v, type already exists in context" , policy_type )
2023-07-29 00:28:44 -06:00
}
2023-08-31 19:50:32 -06:00
ctx . Policies [ policy_type ] = reflect_type
ctx . PolicyTypes [ reflect_type ] = policy_type
return nil
}
func ( ctx * Context ) RegisterSignal ( reflect_type reflect . Type , signal_type SignalType ) error {
_ , exists := ctx . Signals [ signal_type ]
if exists == true {
return fmt . Errorf ( "Cannot register signal of type %+v, type already exists in context" , signal_type )
2023-07-29 00:28:44 -06:00
}
2023-08-31 19:50:32 -06:00
ctx . Signals [ signal_type ] = reflect_type
ctx . SignalTypes [ reflect_type ] = signal_type
2023-07-29 00:28:44 -06:00
return nil
}
2023-07-10 22:31:43 -06:00
// Add a node to a context, returns an error if the def is invalid or already exists in the context
2023-08-31 19:50:32 -06:00
func ( ctx * Context ) RegisterExtension ( reflect_type reflect . Type , ext_type ExtType , data interface { } ) error {
_ , exists := ctx . Extensions [ ext_type ]
2023-07-09 14:30:30 -06:00
if exists == true {
2023-08-31 19:50:32 -06:00
return fmt . Errorf ( "Cannot register extension of type %+v, type already exists in context" , ext_type )
2023-07-09 14:30:30 -06:00
}
2023-08-31 19:50:32 -06:00
ctx . Extensions [ ext_type ] = ExtensionInfo {
Type : reflect_type ,
2023-07-26 00:18:11 -06:00
Data : data ,
2023-07-10 21:15:01 -06:00
}
2023-08-31 19:50:32 -06:00
ctx . ExtensionTypes [ reflect_type ] = ext_type
return nil
}
2023-09-02 17:30:52 -06:00
func ( ctx * Context ) RegisterKind ( kind reflect . Kind , ctx_type SerializedType , serialize TypeSerialize , deserialize TypeDeserialize ) error {
_ , exists := ctx . Kinds [ kind ]
if exists == true {
return fmt . Errorf ( "Cannot register kind %+v, kind already exists in context" , kind )
}
_ , exists = ctx . KindTypes [ ctx_type ]
if exists == true {
return fmt . Errorf ( "0x%x is already registered, cannot use for %+v" , ctx_type , kind )
}
if deserialize == nil {
return fmt . Errorf ( "Cannot register field without deserialize function" )
}
if serialize == nil {
return fmt . Errorf ( "Cannot register field without serialize function" )
}
ctx . Kinds [ kind ] = KindInfo {
ctx_type ,
serialize ,
deserialize ,
}
ctx . KindTypes [ ctx_type ] = kind
return nil
}
2023-08-31 19:50:32 -06:00
func ( ctx * Context ) RegisterType ( reflect_type reflect . Type , ctx_type SerializedType , serialize TypeSerialize , deserialize TypeDeserialize ) error {
_ , exists := ctx . Types [ ctx_type ]
if exists == true {
return fmt . Errorf ( "Cannot register field of type %+v, type already exists in context" , ctx_type )
}
_ , exists = ctx . TypeReflects [ reflect_type ]
if exists == true {
return fmt . Errorf ( "Cannot register field with type %+v, type already registered in context" , reflect_type )
}
if deserialize == nil {
return fmt . Errorf ( "Cannot register field without deserialize function" )
}
if serialize == nil {
return fmt . Errorf ( "Cannot register field without serialize function" )
}
ctx . Types [ ctx_type ] = TypeInfo {
Type : reflect_type ,
Serialize : serialize ,
Deserialize : deserialize ,
}
ctx . TypeReflects [ reflect_type ] = ctx_type
2023-07-09 14:30:30 -06:00
return nil
}
2023-07-28 12:46:06 -06:00
func ( ctx * Context ) AddNode ( id NodeID , node * Node ) {
2023-08-31 19:50:32 -06:00
ctx . nodeMapLock . Lock ( )
ctx . nodeMap [ id ] = node
ctx . nodeMapLock . Unlock ( )
2023-07-28 12:46:06 -06:00
}
func ( ctx * Context ) Node ( id NodeID ) ( * Node , bool ) {
2023-08-31 19:50:32 -06:00
ctx . nodeMapLock . RLock ( )
node , exists := ctx . nodeMap [ id ]
ctx . nodeMapLock . RUnlock ( )
2023-07-28 12:46:06 -06:00
return node , exists
}
2023-07-28 00:04:18 -06:00
// Get a node from the context, or load from the database if not loaded
2023-08-31 19:50:32 -06:00
func ( ctx * Context ) getNode ( id NodeID ) ( * Node , error ) {
2023-07-28 12:46:06 -06:00
target , exists := ctx . Node ( id )
2023-07-27 15:49:21 -06:00
if exists == false {
2023-07-27 16:48:39 -06:00
var err error
target , err = LoadNode ( ctx , id )
if err != nil {
return nil , err
}
2023-07-27 15:49:21 -06:00
}
2023-07-27 16:48:39 -06:00
return target , nil
}
// Route a Signal to dest. Currently only local context routing is supported
2023-08-08 14:00:17 -06:00
func ( ctx * Context ) Send ( messages Messages ) error {
2023-08-07 20:26:02 -06:00
for _ , msg := range ( messages ) {
2023-08-15 18:23:06 -06:00
if msg . Dest == ZeroID {
panic ( "Can't send to null ID" )
}
2023-08-31 19:50:32 -06:00
target , err := ctx . getNode ( msg . Dest )
2023-08-07 20:26:02 -06:00
if err == nil {
select {
2023-08-08 14:00:17 -06:00
case target . MsgChan <- msg :
ctx . Log . Logf ( "signal" , "Sent %s -> %+v" , target . ID , msg )
2023-08-07 20:26:02 -06:00
default :
buf := make ( [ ] byte , 4096 )
n := runtime . Stack ( buf , false )
stack_str := string ( buf [ : n ] )
2023-08-08 14:00:17 -06:00
return fmt . Errorf ( "SIGNAL_OVERFLOW: %s - %s" , msg . Dest , stack_str )
2023-08-07 20:26:02 -06:00
}
} else if errors . Is ( err , NodeNotFoundError ) {
// TODO: Handle finding nodes in other contexts
return err
} else {
return err
2023-07-27 16:48:39 -06:00
}
2023-07-27 15:49:21 -06:00
}
2023-08-07 20:26:02 -06:00
return nil
2023-07-27 15:49:21 -06:00
}
2023-09-02 17:30:52 -06:00
type KindInfo struct {
2023-08-31 19:50:32 -06:00
Type SerializedType
2023-09-02 17:30:52 -06:00
Serialize TypeSerialize
Deserialize TypeDeserialize
2023-08-31 19:50:32 -06:00
}
type SerializedValue struct {
TypeStack [ ] uint64
Data [ ] byte
}
2023-08-31 22:31:29 -06:00
func SerializeValue ( ctx * Context , value reflect . Value ) ( SerializedValue , error ) {
val , err := serializeValue ( ctx , value . Type ( ) , & value )
2023-09-02 17:30:52 -06:00
ctx . Log . Logf ( "serialize" , "SERIALIZED_VALUE(%+v): %+v - %+v" , value . Type ( ) , val . TypeStack , val . Data )
2023-08-31 22:31:29 -06:00
return val , err
2023-08-31 19:50:32 -06:00
}
2023-08-31 22:31:29 -06:00
func serializeValue ( ctx * Context , t reflect . Type , value * reflect . Value ) ( SerializedValue , error ) {
2023-08-31 19:50:32 -06:00
var ctx_type uint64 = 0x00
ctype , exists := ctx . TypeReflects [ t ]
if exists == true {
2023-08-31 22:31:29 -06:00
type_info := ctx . Types [ ctype ]
2023-08-31 19:50:32 -06:00
ctx_type = uint64 ( ctype )
2023-09-02 17:30:52 -06:00
if type_info . Serialize != nil {
return type_info . Serialize ( ctx , ctx_type , t , value )
}
}
kind := t . Kind ( )
kind_info , handled := ctx . Kinds [ kind ]
if handled == false {
return SerializedValue { } , fmt . Errorf ( "Don't know how to serialize kind %+v" , kind )
} else if ctx_type == 0x00 {
ctx_type = uint64 ( kind_info . Type )
}
return kind_info . Serialize ( ctx , ctx_type , t , value )
}
func SerializeField ( ctx * Context , ext Extension , field_name string ) ( SerializedValue , error ) {
if ext == nil {
return SerializedValue { } , fmt . Errorf ( "Cannot get fields on nil Extension" )
}
ext_value := reflect . ValueOf ( ext ) . Elem ( )
field := ext_value . FieldByName ( field_name )
if field . IsValid ( ) == false {
return SerializedValue { } , fmt . Errorf ( "%s is not a field in %+v" , field_name , ext )
} else {
return SerializeValue ( ctx , field )
}
}
func ( value SerializedValue ) MarshalBinary ( ) ( [ ] byte , error ) {
data := make ( [ ] byte , value . SerializedSize ( ) )
binary . BigEndian . PutUint64 ( data [ 0 : 8 ] , uint64 ( len ( value . TypeStack ) ) )
binary . BigEndian . PutUint64 ( data [ 8 : 16 ] , uint64 ( len ( value . Data ) ) )
for i , t := range ( value . TypeStack ) {
type_start := ( i + 2 ) * 8
type_end := ( i + 3 ) * 8
binary . BigEndian . PutUint64 ( data [ type_start : type_end ] , t )
}
return append ( data , value . Data ... ) , nil
}
func ( value SerializedValue ) SerializedSize ( ) uint64 {
return uint64 ( ( len ( value . TypeStack ) + 2 ) * 8 )
}
func ParseSerializedValue ( ctx * Context , data [ ] byte ) ( SerializedValue , error ) {
if len ( data ) < 8 {
return SerializedValue { } , fmt . Errorf ( "SerializedValue required to have at least 8 bytes when serialized" )
}
num_types := int ( binary . BigEndian . Uint64 ( data [ 0 : 8 ] ) )
data_size := int ( binary . BigEndian . Uint64 ( data [ 8 : 16 ] ) )
type_stack := make ( [ ] uint64 , num_types )
for i := 0 ; i < num_types ; i += 1 {
type_start := ( i + 2 ) * 8
type_end := ( i + 3 ) * 8
type_stack [ i ] = binary . BigEndian . Uint64 ( data [ type_start : type_end ] )
}
2023-09-02 18:49:37 -06:00
types_end := 8 * ( num_types + 2 )
2023-09-02 17:30:52 -06:00
return SerializedValue {
type_stack ,
data [ types_end : ( types_end + data_size ) ] ,
} , nil
}
2023-09-02 18:49:37 -06:00
func DeserializeValue ( ctx * Context , type_stack [ ] uint64 , data [ ] byte , n int ) ( reflect . Type , [ ] reflect . Value , [ ] byte , error ) {
ret := make ( [ ] reflect . Value , n )
2023-09-02 17:30:52 -06:00
var deserialize TypeDeserialize = nil
2023-09-02 18:49:37 -06:00
var reflect_type reflect . Type = nil
ctx_type := type_stack [ 0 ]
type_stack = type_stack [ 1 : ]
2023-09-02 17:30:52 -06:00
type_info , exists := ctx . Types [ SerializedType ( ctx_type ) ]
if exists == true {
deserialize = type_info . Deserialize
2023-09-02 18:49:37 -06:00
reflect_type = type_info . Type
2023-09-02 17:30:52 -06:00
} else {
kind , exists := ctx . KindTypes [ SerializedType ( ctx_type ) ]
if exists == false {
2023-09-02 18:49:37 -06:00
return nil , nil , nil , fmt . Errorf ( "Cannot deserialize 0x%x: unknown type/kind" , ctx_type )
2023-09-02 17:30:52 -06:00
}
kind_info := ctx . Kinds [ kind ]
deserialize = kind_info . Deserialize
}
2023-09-02 18:49:37 -06:00
remaining_data := data
var value_type reflect . Type = nil
var err error = nil
if data == nil {
reflect_type , _ , _ , err = deserialize ( ctx , type_stack , nil )
2023-09-02 17:30:52 -06:00
if err != nil {
2023-09-02 18:49:37 -06:00
return nil , nil , nil , err
2023-09-02 17:30:52 -06:00
}
2023-09-02 18:49:37 -06:00
} else {
for i := 0 ; i < n ; i += 1 {
var elem * reflect . Value
var elem_type reflect . Type = nil
elem_type , elem , remaining_data , err = deserialize ( ctx , type_stack , remaining_data )
if err != nil {
return nil , nil , nil , err
}
if value_type == nil {
value_type = elem_type
}
if len ( remaining_data ) == 0 {
remaining_data = nil
}
if elem == nil {
return nil , nil , nil , fmt . Errorf ( "root deserialize returned no value" )
}
ret [ i ] = * elem
2023-09-02 17:30:52 -06:00
}
}
2023-09-02 18:49:37 -06:00
return reflect_type , ret , remaining_data , nil
2023-09-02 17:30:52 -06:00
}
// Create a new Context with the base library content added
func NewContext ( db * badger . DB , log Logger ) ( * Context , error ) {
ctx := & Context {
DB : db ,
Log : log ,
Policies : map [ PolicyType ] reflect . Type { } ,
PolicyTypes : map [ reflect . Type ] PolicyType { } ,
Extensions : map [ ExtType ] ExtensionInfo { } ,
ExtensionTypes : map [ reflect . Type ] ExtType { } ,
Signals : map [ SignalType ] reflect . Type { } ,
SignalTypes : map [ reflect . Type ] SignalType { } ,
Nodes : map [ NodeType ] NodeInfo { } ,
nodeMap : map [ NodeID ] * Node { } ,
Types : map [ SerializedType ] TypeInfo { } ,
TypeReflects : map [ reflect . Type ] SerializedType { } ,
Kinds : map [ reflect . Kind ] KindInfo { } ,
KindTypes : map [ SerializedType ] reflect . Kind { } ,
}
var err error
err = ctx . RegisterKind ( reflect . Pointer , NewSerializedType ( "pointer" ) ,
func ( ctx * Context , ctx_type uint64 , reflect_type reflect . Type , value * reflect . Value ) ( SerializedValue , error ) {
var data [ ] byte
var elem_value * reflect . Value = nil
if value == nil {
data = nil
} else if value . IsZero ( ) {
data = [ ] byte { 0x01 }
} else {
data = [ ] byte { 0x00 }
ev := value . Elem ( )
elem_value = & ev
}
elem , err := serializeValue ( ctx , reflect_type . Elem ( ) , elem_value )
if err != nil {
return SerializedValue { } , err
}
if elem . Data != nil {
data = append ( data , elem . Data ... )
}
return SerializedValue {
append ( [ ] uint64 { ctx_type } , elem . TypeStack ... ) ,
data ,
} , nil
2023-09-02 18:49:37 -06:00
} , func ( ctx * Context , type_stack [ ] uint64 , data [ ] byte ) ( reflect . Type , * reflect . Value , [ ] byte , error ) {
// TODO: figure out how to deal with the case where the pointer value is nil
// In that case need to figure out the type of the pointer to create the nil pointer, which involves continuing to recuse the type stack without parsing any data
if data == nil {
elem_type , _ , _ , err := DeserializeValue ( ctx , type_stack , nil , 1 )
if err != nil {
return nil , nil , nil , err
}
return elem_type , nil , nil , nil
} else {
if len ( data ) < 1 {
return nil , nil , nil , fmt . Errorf ( "Not enough data to deserialize pointer" )
}
pointer_flags := data [ 0 ]
if pointer_flags == 0x00 {
_ , elem_value , remaining_data , err := DeserializeValue ( ctx , type_stack , data [ 1 : ] , 1 )
if err != nil {
return nil , nil , nil , err
}
pointer_value := elem_value [ 0 ] . Addr ( )
return pointer_value . Type ( ) , & pointer_value , remaining_data , nil
} else if pointer_flags == 0x01 {
elem_type , _ , _ , err := DeserializeValue ( ctx , type_stack , nil , 1 )
if err != nil {
return nil , nil , nil , err
}
pointer_type := reflect . PointerTo ( elem_type )
pointer_value := reflect . New ( pointer_type ) . Elem ( )
return pointer_type , & pointer_value , data [ 1 : ] , nil
} else {
return nil , nil , nil , fmt . Errorf ( "unknown pointer flags: %d" , pointer_flags )
}
}
2023-09-02 17:30:52 -06:00
} )
if err != nil {
return nil , err
}
err = ctx . RegisterKind ( reflect . Struct , NewSerializedType ( "struct" ) ,
func ( ctx * Context , ctx_type uint64 , reflect_type reflect . Type , value * reflect . Value ) ( SerializedValue , error ) {
var m map [ int ] [ ] byte = nil
if value != nil {
m = map [ int ] [ ] byte { }
}
num_fields := 0
for _ , field := range ( reflect . VisibleFields ( reflect_type ) ) {
gv_tag , tagged_gv := field . Tag . Lookup ( "gv" )
if tagged_gv == false {
continue
} else if gv_tag == "" {
continue
} else if m != nil {
field_index , err := strconv . Atoi ( gv_tag )
if err != nil {
return SerializedValue { } , err
}
num_fields += 1
field_value := value . FieldByIndex ( field . Index )
field_ser , err := serializeValue ( ctx , field . Type , & field_value )
if err != nil {
return SerializedValue { } , err
}
m [ field_index ] , err = field_ser . MarshalBinary ( )
if err != nil {
return SerializedValue { } , nil
}
}
}
field_list := make ( [ ] [ ] byte , num_fields )
for i := range ( field_list ) {
var exists bool = false
field_list [ i ] , exists = m [ i ]
if exists == false {
return SerializedValue { } , fmt . Errorf ( "%+v missing gv:%d" , reflect_type , i )
}
}
list_value := reflect . ValueOf ( field_list )
list_serial , err := serializeValue ( ctx , list_value . Type ( ) , & list_value )
2023-08-31 22:31:29 -06:00
if err != nil {
return SerializedValue { } , err
}
return SerializedValue {
[ ] uint64 { ctx_type } ,
2023-09-02 17:30:52 -06:00
list_serial . Data ,
2023-08-31 22:31:29 -06:00
} , nil
2023-09-02 18:49:37 -06:00
} , func ( ctx * Context , type_stack [ ] uint64 , data [ ] byte ) ( reflect . Type , * reflect . Value , [ ] byte , error ) {
return nil , nil , nil , fmt . Errorf ( "deserialize struct not implemented" )
2023-09-02 17:30:52 -06:00
} )
if err != nil {
return nil , err
2023-08-31 19:50:32 -06:00
}
2023-09-02 17:30:52 -06:00
err = ctx . RegisterKind ( reflect . Int , NewSerializedType ( "int" ) ,
func ( ctx * Context , ctx_type uint64 , reflect_type reflect . Type , value * reflect . Value ) ( SerializedValue , error ) {
var data [ ] byte = nil
if value != nil {
data = make ( [ ] byte , 8 )
binary . BigEndian . PutUint64 ( data , value . Uint ( ) )
2023-08-31 19:50:32 -06:00
}
2023-09-02 17:30:52 -06:00
return SerializedValue {
[ ] uint64 { ctx_type } ,
data ,
} , nil
2023-09-02 18:49:37 -06:00
} , func ( ctx * Context , type_stack [ ] uint64 , data [ ] byte ) ( reflect . Type , * reflect . Value , [ ] byte , error ) {
if len ( data ) < 8 {
return nil , nil , nil , fmt . Errorf ( "invalid length: %d/8" , len ( data ) )
2023-09-02 17:30:52 -06:00
}
2023-09-02 18:49:37 -06:00
remaining_data := data [ 8 : ]
2023-09-02 17:30:52 -06:00
if len ( remaining_data ) == 0 {
remaining_data = nil
}
2023-09-02 18:49:37 -06:00
int_val := reflect . ValueOf ( binary . BigEndian . Uint64 ( data [ 0 : 8 ] ) )
return int_val . Type ( ) , & int_val , remaining_data , nil
2023-09-02 17:30:52 -06:00
} )
if err != nil {
return nil , err
}
err = ctx . RegisterKind ( reflect . Uint32 , NewSerializedType ( "uint32" ) ,
func ( ctx * Context , ctx_type uint64 , reflect_type reflect . Type , value * reflect . Value ) ( SerializedValue , error ) {
data := make ( [ ] byte , 4 )
if value != nil {
binary . BigEndian . PutUint32 ( data , uint32 ( value . Uint ( ) ) )
}
return SerializedValue {
[ ] uint64 { ctx_type } ,
data ,
} , nil
2023-09-02 18:49:37 -06:00
} , func ( ctx * Context , type_stack [ ] uint64 , data [ ] byte ) ( reflect . Type , * reflect . Value , [ ] byte , error ) {
return nil , nil , nil , fmt . Errorf ( "deserialize uint32 unimplemented" )
2023-09-02 17:30:52 -06:00
} )
if err != nil {
return nil , err
}
err = ctx . RegisterKind ( reflect . String , NewSerializedType ( "string" ) ,
func ( ctx * Context , ctx_type uint64 , reflect_type reflect . Type , value * reflect . Value ) ( SerializedValue , error ) {
if value == nil {
return SerializedValue {
[ ] uint64 { ctx_type } ,
nil ,
} , nil
}
data := make ( [ ] byte , 8 )
str := value . String ( )
binary . BigEndian . PutUint64 ( data , uint64 ( len ( str ) ) )
return SerializedValue {
[ ] uint64 { uint64 ( ctx_type ) } ,
append ( data , [ ] byte ( str ) ... ) ,
} , nil
2023-09-02 18:49:37 -06:00
} , func ( ctx * Context , type_stack [ ] uint64 , data [ ] byte ) ( reflect . Type , * reflect . Value , [ ] byte , error ) {
return nil , nil , nil , fmt . Errorf ( "deserialize string unimplemented" )
2023-09-02 17:30:52 -06:00
} )
if err != nil {
return nil , err
}
err = ctx . RegisterKind ( reflect . Array , NewSerializedType ( "array" ) ,
func ( ctx * Context , ctx_type uint64 , reflect_type reflect . Type , value * reflect . Value ) ( SerializedValue , error ) {
var data [ ] byte
if value == nil {
data = nil
} else if value . Len ( ) == 0 {
data = [ ] byte { 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 }
} else {
data := make ( [ ] byte , 8 )
binary . BigEndian . PutUint64 ( data , uint64 ( value . Len ( ) ) )
var type_stack [ ] uint64 = nil
for i := 0 ; i < value . Len ( ) ; i += 1 {
val := value . Index ( i )
element , err := serializeValue ( ctx , reflect_type . Elem ( ) , & val )
if err != nil {
return SerializedValue { } , err
}
if type_stack == nil {
type_stack = append ( [ ] uint64 { ctx_type } , element . TypeStack ... )
}
data = append ( data , element . Data ... )
}
}
elem , err := serializeValue ( ctx , reflect_type . Elem ( ) , nil )
if err != nil {
return SerializedValue { } , err
}
return SerializedValue {
append ( [ ] uint64 { ctx_type } , elem . TypeStack ... ) ,
data ,
} , nil
2023-09-02 18:49:37 -06:00
} , func ( ctx * Context , type_stack [ ] uint64 , data [ ] byte ) ( reflect . Type , * reflect . Value , [ ] byte , error ) {
return nil , nil , nil , fmt . Errorf ( "deserialize array unimplemented" )
2023-09-02 17:30:52 -06:00
} )
if err != nil {
return nil , err
}
err = ctx . RegisterKind ( reflect . Interface , NewSerializedType ( "interface" ) ,
func ( ctx * Context , ctx_type uint64 , reflect_type reflect . Type , value * reflect . Value ) ( SerializedValue , error ) {
var data [ ] byte
type_stack := [ ] uint64 { }
if value == nil {
data = nil
} else if value . IsZero ( ) {
return SerializedValue { } , fmt . Errorf ( "Cannot serialize nil interfaces" )
} else {
elem_value := value . Elem ( )
elem , err := serializeValue ( ctx , value . Elem ( ) . Type ( ) , & elem_value )
if err != nil {
return SerializedValue { } , err
}
data = elem . Data
type_stack = elem . TypeStack
}
return SerializedValue {
append ( [ ] uint64 { ctx_type } , type_stack ... ) ,
data ,
} , nil
2023-09-02 18:49:37 -06:00
} , func ( ctx * Context , type_stack [ ] uint64 , data [ ] byte ) ( reflect . Type , * reflect . Value , [ ] byte , error ) {
return nil , nil , nil , fmt . Errorf ( "deserialize interface unimplemented" )
2023-09-02 17:30:52 -06:00
} )
if err != nil {
return nil , err
}
err = ctx . RegisterKind ( reflect . Map , NewSerializedType ( "map" ) ,
func ( ctx * Context , ctx_type uint64 , reflect_type reflect . Type , value * reflect . Value ) ( SerializedValue , error ) {
2023-08-31 22:31:29 -06:00
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 ( )
2023-09-02 17:30:52 -06:00
key , err := serializeValue ( ctx , reflect_type . Key ( ) , & key_value )
2023-08-31 22:31:29 -06:00
if err != nil {
return SerializedValue { } , err
}
2023-09-02 17:30:52 -06:00
val , err := serializeValue ( ctx , reflect_type . Elem ( ) , & val_value )
2023-08-31 22:31:29 -06:00
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
}
2023-09-02 17:30:52 -06:00
key , err := serializeValue ( ctx , reflect_type . Key ( ) , nil )
2023-08-31 19:50:32 -06:00
if err != nil {
2023-08-31 22:31:29 -06:00
return SerializedValue { } , err
2023-08-31 19:50:32 -06:00
}
2023-09-02 17:30:52 -06:00
elem , err := serializeValue ( ctx , reflect_type . Elem ( ) , nil )
2023-08-31 19:50:32 -06:00
if err != nil {
2023-08-31 22:31:29 -06:00
return SerializedValue { } , err
2023-08-31 19:50:32 -06:00
}
2023-08-31 22:31:29 -06:00
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
2023-09-02 18:49:37 -06:00
} , func ( ctx * Context , type_stack [ ] uint64 , data [ ] byte ) ( reflect . Type , * reflect . Value , [ ] byte , error ) {
return nil , nil , nil , fmt . Errorf ( "deserialize map unimplemented" )
2023-09-02 17:30:52 -06:00
} )
if err != nil {
return nil , err
}
err = ctx . RegisterKind ( reflect . Uint8 , NewSerializedType ( "uint8" ) ,
func ( ctx * Context , ctx_type uint64 , reflect_type reflect . Type , value * reflect . Value ) ( SerializedValue , error ) {
var data [ ] byte = nil
if value != nil {
data = [ ] byte { uint8 ( value . Uint ( ) ) }
2023-08-31 19:50:32 -06:00
}
2023-09-02 17:30:52 -06:00
return SerializedValue {
[ ] uint64 { ctx_type } ,
data ,
} , nil
2023-09-02 18:49:37 -06:00
} , func ( ctx * Context , type_stack [ ] uint64 , data [ ] byte ) ( reflect . Type , * reflect . Value , [ ] byte , error ) {
return nil , nil , nil , fmt . Errorf ( "deserialize uint8 unimplemented" )
2023-09-02 17:30:52 -06:00
} )
if err != nil {
return nil , err
}
err = ctx . RegisterKind ( reflect . Uint64 , NewSerializedType ( "uint64" ) ,
func ( ctx * Context , ctx_type uint64 , reflect_type reflect . Type , value * reflect . Value ) ( SerializedValue , error ) {
var data [ ] byte = nil
if value != nil {
data = make ( [ ] byte , 8 )
binary . BigEndian . PutUint64 ( data , value . Uint ( ) )
}
return SerializedValue {
[ ] uint64 { ctx_type } ,
data ,
} , nil
2023-09-02 18:49:37 -06:00
} , func ( ctx * Context , type_stack [ ] uint64 , data [ ] byte ) ( reflect . Type , * reflect . Value , [ ] byte , error ) {
return nil , nil , nil , fmt . Errorf ( "deserialize uint64 unimplemented" )
2023-09-02 17:30:52 -06:00
} )
if err != nil {
return nil , err
}
err = ctx . RegisterKind ( reflect . Slice , NewSerializedType ( "slice" ) ,
func ( ctx * Context , ctx_type uint64 , reflect_type reflect . Type , value * reflect . Value ) ( SerializedValue , error ) {
2023-08-31 22:31:29 -06:00
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 {
data := make ( [ ] byte , 8 )
binary . BigEndian . PutUint64 ( data , uint64 ( value . Len ( ) ) )
2023-09-02 17:30:52 -06:00
var type_stack [ ] uint64
2023-08-31 22:31:29 -06:00
for i := 0 ; i < value . Len ( ) ; i += 1 {
val := value . Index ( i )
2023-09-02 17:30:52 -06:00
element , err := serializeValue ( ctx , reflect_type . Elem ( ) , & val )
2023-08-31 22:31:29 -06:00
if err != nil {
return SerializedValue { } , err
}
2023-09-02 17:30:52 -06:00
if type_stack == nil {
type_stack = append ( [ ] uint64 { ctx_type } , element . TypeStack ... )
2023-08-31 22:31:29 -06:00
}
2023-09-02 17:30:52 -06:00
data = append ( data , element . Data ... )
2023-08-31 22:31:29 -06:00
}
return SerializedValue {
2023-09-02 17:30:52 -06:00
append ( [ ] uint64 { ctx_type } , type_stack ... ) ,
2023-08-31 22:31:29 -06:00
data ,
} , nil
}
2023-09-02 17:30:52 -06:00
elem , err := serializeValue ( ctx , reflect_type . Elem ( ) , nil )
2023-08-31 19:50:32 -06:00
if err != nil {
2023-08-31 22:31:29 -06:00
return SerializedValue { } , err
2023-08-31 19:50:32 -06:00
}
2023-08-31 22:31:29 -06:00
return SerializedValue {
2023-09-02 17:30:52 -06:00
elem . TypeStack ,
2023-08-31 22:31:29 -06:00
data ,
} , nil
2023-09-02 18:49:37 -06:00
} , func ( ctx * Context , type_stack [ ] uint64 , data [ ] byte ) ( reflect . Type , * reflect . Value , [ ] byte , error ) {
return nil , nil , nil , fmt . Errorf ( "not implemented" )
} )
if err != nil {
return nil , err
}
err = ctx . RegisterType ( reflect . TypeOf ( StringError ( "" ) ) , ErrorType ,
func ( ctx * Context , ctx_type uint64 , t reflect . Type , value * reflect . Value ) ( SerializedValue , error ) {
if value == nil {
return SerializedValue {
[ ] uint64 { ctx_type } ,
nil ,
} , nil
}
data := make ( [ ] byte , 8 )
err := value . Interface ( ) . ( StringError )
str := string ( err )
binary . BigEndian . PutUint64 ( data , uint64 ( len ( str ) ) )
return SerializedValue {
[ ] uint64 { uint64 ( ctx_type ) } ,
append ( data , [ ] byte ( str ) ... ) ,
} , nil
} , func ( ctx * Context , type_stack [ ] uint64 , data [ ] byte ) ( reflect . Type , * reflect . Value , [ ] byte , error ) {
return nil , nil , nil , fmt . Errorf ( "unimplemented" )
} )
err = ctx . RegisterType ( reflect . TypeOf ( RandID ( ) ) , NewSerializedType ( "NodeID" ) ,
func ( ctx * Context , ctx_type uint64 , t reflect . Type , value * reflect . Value ) ( SerializedValue , error ) {
var id_ser [ ] byte = nil
if value != nil {
var err error = nil
id_ser , err = value . Interface ( ) . ( NodeID ) . MarshalBinary ( )
if err != nil {
return SerializedValue { } , err
}
}
return SerializedValue {
[ ] uint64 { ctx_type } ,
id_ser ,
} , nil
} , func ( ctx * Context , type_stack [ ] uint64 , data [ ] byte ) ( reflect . Type , * reflect . Value , [ ] byte , error ) {
return nil , nil , nil , fmt . Errorf ( "unimplemented" )
2023-09-02 17:30:52 -06:00
} )
if err != nil {
return nil , err
}
err = ctx . RegisterType ( reflect . TypeOf ( Up ) , NewSerializedType ( "SignalDirection" ) ,
func ( ctx * Context , ctx_type uint64 , t reflect . Type , value * reflect . Value ) ( SerializedValue , error ) {
var data [ ] byte = nil
if value != nil {
val := value . Interface ( ) . ( SignalDirection )
data = [ ] byte { byte ( val ) }
2023-08-31 22:31:29 -06:00
}
return SerializedValue {
2023-09-02 17:30:52 -06:00
[ ] uint64 { ctx_type } ,
2023-08-31 22:31:29 -06:00
data ,
} , nil
2023-09-02 18:49:37 -06:00
} , func ( ctx * Context , type_stack [ ] uint64 , data [ ] byte ) ( reflect . Type , * reflect . Value , [ ] byte , error ) {
return reflect . TypeOf ( Up ) , nil , nil , fmt . Errorf ( "unimplemented" )
2023-09-02 17:30:52 -06:00
} )
if err != nil {
return nil , err
}
2023-08-31 19:50:32 -06:00
2023-09-02 17:30:52 -06:00
err = ctx . RegisterType ( reflect . TypeOf ( ReqState ( 0 ) ) , NewSerializedType ( "ReqState" ) ,
func ( ctx * Context , ctx_type uint64 , t reflect . Type , value * reflect . Value ) ( SerializedValue , error ) {
var data [ ] byte = nil
if value != nil {
val := value . Interface ( ) . ( ReqState )
data = [ ] byte { byte ( val ) }
2023-08-31 22:31:29 -06:00
}
return SerializedValue {
2023-09-02 17:30:52 -06:00
[ ] uint64 { ctx_type } ,
data ,
2023-08-31 22:31:29 -06:00
} , nil
2023-09-02 18:49:37 -06:00
} , func ( ctx * Context , type_stack [ ] uint64 , data [ ] byte ) ( reflect . Type , * reflect . Value , [ ] byte , error ) {
return reflect . TypeOf ( ReqState ( 0 ) ) , nil , nil , fmt . Errorf ( "unimplemented" )
2023-09-02 17:30:52 -06:00
} )
2023-08-31 19:50:32 -06:00
if err != nil {
2023-09-02 17:30:52 -06:00
return nil , err
2023-07-09 14:30:30 -06:00
}
2023-08-31 19:50:32 -06:00
err = ctx . RegisterExtension ( reflect . TypeOf ( ( * LockableExt ) ( nil ) ) , LockableExtType , nil )
2023-07-26 00:18:11 -06:00
if err != nil {
return nil , err
}
2023-08-31 19:50:32 -06:00
err = ctx . RegisterExtension ( reflect . TypeOf ( ( * ListenerExt ) ( nil ) ) , ListenerExtType , nil )
2023-07-26 11:56:10 -06:00
if err != nil {
return nil , err
}
2023-08-31 19:50:32 -06:00
err = ctx . RegisterExtension ( reflect . TypeOf ( ( * GroupExt ) ( nil ) ) , GroupExtType , nil )
2023-07-26 00:18:11 -06:00
if err != nil {
return nil , err
}
2023-08-31 19:50:32 -06:00
gql_ctx := NewGQLExtContext ( )
err = ctx . RegisterExtension ( reflect . TypeOf ( ( * GQLExt ) ( nil ) ) , GQLExtType , gql_ctx )
2023-07-26 00:18:11 -06:00
if err != nil {
return nil , err
}
2023-08-31 19:50:32 -06:00
err = ctx . RegisterSignal ( reflect . TypeOf ( ( * StopSignal ) ( nil ) ) , StopSignalType )
if err != nil {
return nil , err
}
err = ctx . RegisterSignal ( reflect . TypeOf ( ( * CreateSignal ) ( nil ) ) , CreateSignalType )
2023-07-25 09:51:55 -06:00
if err != nil {
2023-07-25 21:43:15 -06:00
return nil , err
2023-07-25 09:51:55 -06:00
}
2023-07-10 21:15:01 -06:00
2023-08-31 19:50:32 -06:00
err = ctx . RegisterSignal ( reflect . TypeOf ( ( * StartSignal ) ( nil ) ) , StartSignalType )
2023-08-01 20:55:15 -06:00
if err != nil {
return nil , err
}
2023-07-29 00:28:44 -06:00
2023-08-31 19:50:32 -06:00
err = ctx . RegisterSignal ( reflect . TypeOf ( ( * ReadSignal ) ( nil ) ) , ReadSignalType )
2023-08-06 12:47:47 -06:00
if err != nil {
return nil , err
}
2023-08-31 19:50:32 -06:00
err = ctx . RegisterSignal ( reflect . TypeOf ( ( * ReadResultSignal ) ( nil ) ) , ReadResultSignalType )
2023-08-06 12:47:47 -06:00
if err != nil {
return nil , err
}
2023-08-07 20:26:02 -06:00
err = ctx . RegisterNodeType ( GQLNodeType , [ ] ExtType { GroupExtType , GQLExtType } )
2023-07-26 23:57:50 -06:00
if err != nil {
return nil , err
}
schema , err := BuildSchema ( gql_ctx )
if err != nil {
return nil , err
}
gql_ctx . Schema = schema
2023-07-25 21:43:15 -06:00
return ctx , nil
2023-07-09 14:30:30 -06:00
}