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"
2023-09-03 17:50:12 -06:00
"math"
2023-09-02 17:30:52 -06:00
"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-03 17:50:12 -06:00
type TypeDeserialize func ( * Context , SerializedValue ) ( reflect . Type , * reflect . Value , SerializedValue , 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 )
}
2023-09-03 17:50:12 -06:00
func ParseSerializedValue ( data [ ] byte ) ( SerializedValue , [ ] byte , error ) {
2023-09-02 17:30:52 -06:00
if len ( data ) < 8 {
2023-09-03 17:50:12 -06:00
return SerializedValue { } , nil , fmt . Errorf ( "SerializedValue required to have at least 8 bytes when serialized" )
2023-09-02 17:30:52 -06:00
}
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-03 17:50:12 -06:00
data_end := types_end + data_size
2023-09-02 17:30:52 -06:00
return SerializedValue {
type_stack ,
2023-09-03 17:50:12 -06:00
data [ types_end : data_end ] ,
} , data [ data_end : ] , nil
2023-09-02 17:30:52 -06:00
}
2023-09-03 17:50:12 -06:00
func DeserializeValue ( ctx * Context , value SerializedValue , n int ) ( reflect . Type , [ ] reflect . Value , SerializedValue , error ) {
ctx . Log . Logf ( "serialize" , "DeserializeValue: %+v - %d" , value , n )
2023-09-02 18:49:37 -06:00
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
2023-09-03 17:50:12 -06:00
ctx_type := value . TypeStack [ 0 ]
value . TypeStack = value . TypeStack [ 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-03 17:50:12 -06:00
return nil , nil , SerializedValue { } , 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-03 17:50:12 -06:00
ctx . Log . Logf ( "serialize" , "Deserializing: %d x %d" , ctx_type , n )
if value . Data == nil {
reflect_type , _ , val , err := deserialize ( ctx , value )
2023-09-02 17:30:52 -06:00
if err != nil {
2023-09-03 17:50:12 -06:00
return nil , nil , SerializedValue { } , err
2023-09-02 17:30:52 -06:00
}
2023-09-03 17:50:12 -06:00
return reflect_type , nil , val , nil
}
val := SerializedValue {
value . TypeStack ,
value . Data ,
}
for i := 0 ; i < n ; i += 1 {
val . TypeStack = value . TypeStack
var elem * reflect . Value
var err error
reflect_type , elem , val , err = deserialize ( ctx , val )
if err != nil {
return nil , nil , SerializedValue { } , err
2023-09-02 17:30:52 -06:00
}
2023-09-03 17:50:12 -06:00
ret [ i ] = * elem
2023-09-02 17:30:52 -06:00
}
2023-09-03 17:50:12 -06:00
ctx . Log . Logf ( "serialize" , "DeserializeValue: DONE %+v - %+v" , val , ret )
return reflect_type , ret , val , 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-03 17:50:12 -06:00
} , func ( ctx * Context , value SerializedValue ) ( reflect . Type , * reflect . Value , SerializedValue , error ) {
if value . Data == nil {
elem_type , _ , _ , err := DeserializeValue ( ctx , value , 1 )
2023-09-02 18:49:37 -06:00
if err != nil {
2023-09-03 17:50:12 -06:00
return nil , nil , SerializedValue { } , err
2023-09-02 18:49:37 -06:00
}
2023-09-03 17:50:12 -06:00
return reflect . PointerTo ( elem_type ) , nil , value , nil
} else if len ( value . Data ) < 1 {
return nil , nil , SerializedValue { } , fmt . Errorf ( "Not enough data to deserialize pointer" )
2023-09-02 18:49:37 -06:00
} else {
2023-09-03 17:50:12 -06:00
pointer_flags := value . Data [ 0 ]
value . Data = value . Data [ 1 : ]
2023-09-02 18:49:37 -06:00
if pointer_flags == 0x00 {
2023-09-03 17:50:12 -06:00
_ , elem_value , remaining_data , err := DeserializeValue ( ctx , value , 1 )
2023-09-02 18:49:37 -06:00
if err != nil {
2023-09-03 17:50:12 -06:00
return nil , nil , SerializedValue { } , err
2023-09-02 18:49:37 -06:00
}
pointer_value := elem_value [ 0 ] . Addr ( )
return pointer_value . Type ( ) , & pointer_value , remaining_data , nil
} else if pointer_flags == 0x01 {
2023-09-03 17:50:12 -06:00
elem_type , _ , remaining_data , err := DeserializeValue ( ctx , value , 1 )
2023-09-02 18:49:37 -06:00
if err != nil {
2023-09-03 17:50:12 -06:00
return nil , nil , SerializedValue { } , err
2023-09-02 18:49:37 -06:00
}
pointer_type := reflect . PointerTo ( elem_type )
pointer_value := reflect . New ( pointer_type ) . Elem ( )
2023-09-03 17:50:12 -06:00
return pointer_type , & pointer_value , remaining_data , nil
2023-09-02 18:49:37 -06:00
} else {
2023-09-03 17:50:12 -06:00
return nil , nil , SerializedValue { } , fmt . Errorf ( "unknown pointer flags: %d" , pointer_flags )
2023-09-02 18:49:37 -06:00
}
}
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 ) {
2023-09-03 17:50:12 -06:00
// TODO: Switch from serializing each field as a []byte of a SerializedValue.MarshalBinary to just running serializeValue and adding the TypeStack and Data together
serialized_value := SerializedValue {
[ ] uint64 { ctx_type } ,
nil ,
2023-09-02 17:30:52 -06:00
}
num_fields := 0
2023-09-03 17:50:12 -06:00
field_values := map [ int ] SerializedValue { }
2023-09-02 17:30:52 -06:00
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
2023-09-03 17:50:12 -06:00
} else {
// Add to the type stack and data stack
2023-09-02 17:30:52 -06:00
field_index , err := strconv . Atoi ( gv_tag )
if err != nil {
return SerializedValue { } , err
}
num_fields += 1
2023-09-03 17:50:12 -06:00
if value == nil {
field_ser , err := serializeValue ( ctx , field . Type , nil )
if err != nil {
return SerializedValue { } , err
}
field_values [ field_index ] = field_ser
} else {
field_value := value . FieldByIndex ( field . Index )
field_ser , err := serializeValue ( ctx , field . Type , & field_value )
if err != nil {
return SerializedValue { } , err
}
field_values [ field_index ] = field_ser
2023-09-02 17:30:52 -06:00
}
}
}
2023-09-03 17:50:12 -06:00
for i := 0 ; i < num_fields ; i += 1 {
field_value , exists := field_values [ i ]
2023-09-02 17:30:52 -06:00
if exists == false {
return SerializedValue { } , fmt . Errorf ( "%+v missing gv:%d" , reflect_type , i )
}
2023-09-03 17:50:12 -06:00
serialized_value . TypeStack = append ( serialized_value . TypeStack , field_value . TypeStack ... )
if value != nil {
serialized_value . Data = append ( serialized_value . Data , field_value . Data ... )
}
2023-09-02 17:30:52 -06:00
}
2023-09-03 17:50:12 -06:00
return serialized_value , nil
} , func ( ctx * Context , value SerializedValue ) ( reflect . Type , * reflect . Value , SerializedValue , error ) {
return nil , nil , SerializedValue { } , fmt . Errorf ( "deserialize struct not implemented" )
} )
if err != nil {
return nil , err
}
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 , uint64 ( value . Int ( ) ) )
2023-08-31 22:31:29 -06:00
}
return SerializedValue {
[ ] uint64 { ctx_type } ,
2023-09-03 17:50:12 -06:00
data ,
2023-08-31 22:31:29 -06:00
} , nil
2023-09-03 17:50:12 -06:00
} , func ( ctx * Context , value SerializedValue ) ( reflect . Type , * reflect . Value , SerializedValue , error ) {
if value . Data == nil {
return reflect . TypeOf ( 0 ) , nil , value , nil
}
if len ( value . Data ) < 8 {
return nil , nil , SerializedValue { } , fmt . Errorf ( "invalid length: %d/8" , len ( value . Data ) )
}
int_val := reflect . ValueOf ( int ( binary . BigEndian . Uint64 ( value . Data [ 0 : 8 ] ) ) )
value . Data = value . Data [ 8 : ]
return int_val . Type ( ) , & int_val , value , nil
2023-09-02 17:30:52 -06:00
} )
if err != nil {
return nil , err
2023-08-31 19:50:32 -06:00
}
2023-09-03 17:50:12 -06:00
err = ctx . RegisterKind ( reflect . Bool , NewSerializedType ( "bool" ) ,
2023-09-02 17:30:52 -06:00
func ( ctx * Context , ctx_type uint64 , reflect_type reflect . Type , value * reflect . Value ) ( SerializedValue , error ) {
var data [ ] byte = nil
if value != nil {
2023-09-03 17:50:12 -06:00
b := value . Bool ( )
if b == true {
data = [ ] byte { 0x01 }
} else {
data = [ ] byte { 0x00 }
}
}
return SerializedValue {
[ ] uint64 { ctx_type } ,
data ,
} , nil
} , func ( ctx * Context , value SerializedValue ) ( reflect . Type , * reflect . Value , SerializedValue , error ) {
if value . Data == nil {
return reflect . TypeOf ( true ) , nil , value , nil
} else if len ( value . Data ) == 0 {
return nil , nil , SerializedValue { } , fmt . Errorf ( "not enough data to deserialize bool" )
} else {
b := value . Data [ 0 ]
value . Data = value . Data [ 1 : ]
var val reflect . Value
switch b {
case 0x00 :
val = reflect . ValueOf ( false )
case 0x01 :
val = reflect . ValueOf ( true )
default :
return nil , nil , SerializedValue { } , fmt . Errorf ( "unknown boolean 0x%x" , b )
}
return reflect . TypeOf ( true ) , & val , value , nil
}
} )
if err != nil {
return nil , err
}
err = ctx . RegisterKind ( reflect . Float64 , NewSerializedType ( "float64" ) ,
func ( ctx * Context , ctx_type uint64 , reflect_type reflect . Type , value * reflect . Value ) ( SerializedValue , error ) {
var data [ ] byte = nil
if value != nil {
// TODO: fix if underlying memory layout of float32 changes(or if it's architecture-dependent)
2023-09-02 17:30:52 -06:00
data = make ( [ ] byte , 8 )
2023-09-03 17:50:12 -06:00
val := math . Float64bits ( float64 ( value . Float ( ) ) )
binary . BigEndian . PutUint64 ( data , val )
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-03 17:50:12 -06:00
} , func ( ctx * Context , value SerializedValue ) ( reflect . Type , * reflect . Value , SerializedValue , error ) {
if value . Data == nil {
return reflect . TypeOf ( float64 ( 0 ) ) , nil , value , nil
} else {
if len ( value . Data ) < 8 {
return nil , nil , SerializedValue { } , fmt . Errorf ( "Not enough data to deserialize float32" )
}
val_int := binary . BigEndian . Uint64 ( value . Data [ 0 : 8 ] )
value . Data = value . Data [ 8 : ]
val := math . Float64frombits ( val_int )
float_val := reflect . ValueOf ( val )
return float_val . Type ( ) , & float_val , value , nil
2023-09-02 17:30:52 -06:00
}
2023-09-03 17:50:12 -06:00
} )
if err != nil {
return nil , err
}
err = ctx . RegisterKind ( reflect . Float32 , NewSerializedType ( "float32" ) ,
func ( ctx * Context , ctx_type uint64 , reflect_type reflect . Type , value * reflect . Value ) ( SerializedValue , error ) {
var data [ ] byte = nil
if value != nil {
// TODO: fix if underlying memory layout of float32 changes(or if it's architecture-dependent)
data = make ( [ ] byte , 4 )
val := math . Float32bits ( float32 ( value . Float ( ) ) )
binary . BigEndian . PutUint32 ( data , val )
}
return SerializedValue {
[ ] uint64 { ctx_type } ,
data ,
} , nil
} , func ( ctx * Context , value SerializedValue ) ( reflect . Type , * reflect . Value , SerializedValue , error ) {
if value . Data == nil {
return reflect . TypeOf ( float32 ( 0 ) ) , nil , value , nil
} else {
if len ( value . Data ) < 4 {
return nil , nil , SerializedValue { } , fmt . Errorf ( "Not enough data to deserialize float32" )
}
val_int := binary . BigEndian . Uint32 ( value . Data [ 0 : 4 ] )
value . Data = value . Data [ 4 : ]
val := math . Float32frombits ( val_int )
float_value := reflect . ValueOf ( val )
return float_value . Type ( ) , & float_value , value , 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-03 17:50:12 -06:00
} , func ( ctx * Context , value SerializedValue ) ( reflect . Type , * reflect . Value , SerializedValue , error ) {
if value . Data == nil {
return reflect . TypeOf ( uint32 ( 0 ) ) , nil , value , nil
} else {
if len ( value . Data ) < 4 {
return nil , nil , SerializedValue { } , fmt . Errorf ( "Not enough data to deserialize uint32" )
}
val := binary . BigEndian . Uint32 ( value . Data [ 0 : 4 ] )
value . Data = value . Data [ 4 : ]
int_value := reflect . ValueOf ( val )
return int_value . Type ( ) , & int_value , value , nil
}
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-03 17:50:12 -06:00
} , func ( ctx * Context , value SerializedValue ) ( reflect . Type , * reflect . Value , SerializedValue , error ) {
if value . Data == nil {
return reflect . TypeOf ( "" ) , nil , value , nil
} else if len ( value . Data ) < 8 {
return nil , nil , SerializedValue { } , fmt . Errorf ( "Not enough data to deserialize string" )
} else {
str_len := binary . BigEndian . Uint64 ( value . Data [ 0 : 8 ] )
value . Data = value . Data [ 8 : ]
if len ( value . Data ) < int ( str_len ) {
return nil , nil , SerializedValue { } , fmt . Errorf ( "Not enough data to deserialize string of length %d(%d)" , str_len , len ( value . Data ) )
}
string_bytes := value . Data [ : str_len ]
value . Data = value . Data [ str_len : ]
str_value := reflect . ValueOf ( string ( string_bytes ) )
return reflect . TypeOf ( "" ) , & str_value , value , nil
}
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-03 17:50:12 -06:00
} , func ( ctx * Context , value SerializedValue ) ( reflect . Type , * reflect . Value , SerializedValue , error ) {
return nil , nil , SerializedValue { } , 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-03 17:50:12 -06:00
} , func ( ctx * Context , value SerializedValue ) ( reflect . Type , * reflect . Value , SerializedValue , error ) {
return nil , nil , SerializedValue { } , 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-03 17:50:12 -06:00
} , func ( ctx * Context , value SerializedValue ) ( reflect . Type , * reflect . Value , SerializedValue , error ) {
if value . Data == nil {
var key_type , elem_type reflect . Type
key_type , _ , value , err = DeserializeValue ( ctx , value , 1 )
if err != nil {
return nil , nil , SerializedValue { } , err
}
elem_type , _ , value , err = DeserializeValue ( ctx , value , 1 )
if err != nil {
return nil , nil , SerializedValue { } , err
}
return reflect . MapOf ( key_type , elem_type ) , nil , value , nil
} else if len ( value . Data ) < 8 {
return nil , nil , SerializedValue { } , fmt . Errorf ( "Not enough data to deserialize map" )
} else {
map_len := binary . BigEndian . Uint64 ( value . Data [ 0 : 8 ] )
value . Data = value . Data [ 8 : ]
if map_len == 0xFFFFFFFFFFFFFFFF {
temp_value := SerializedValue {
value . TypeStack ,
nil ,
}
var key_type , elem_type reflect . Type
key_type , _ , temp_value , err = DeserializeValue ( ctx , temp_value , 1 )
if err != nil {
return nil , nil , SerializedValue { } , err
}
elem_type , _ , temp_value , err = DeserializeValue ( ctx , temp_value , 1 )
if err != nil {
return nil , nil , SerializedValue { } , err
}
map_type := reflect . MapOf ( key_type , elem_type )
map_value := reflect . New ( map_type ) . Elem ( )
return map_type , & map_value , SerializedValue {
temp_value . TypeStack ,
value . Data ,
} , nil
} else if map_len == 0x00 {
temp_value := SerializedValue {
value . TypeStack ,
nil ,
}
var key_type , elem_type reflect . Type
key_type , _ , temp_value , err = DeserializeValue ( ctx , temp_value , 1 )
if err != nil {
return nil , nil , SerializedValue { } , err
}
elem_type , _ , temp_value , err = DeserializeValue ( ctx , temp_value , 1 )
if err != nil {
return nil , nil , SerializedValue { } , err
}
map_type := reflect . MapOf ( key_type , elem_type )
map_value := reflect . MakeMap ( map_type )
return map_type , & map_value , SerializedValue {
temp_value . TypeStack ,
value . Data ,
} , nil
} else {
var key_type , elem_type reflect . Type
var key_values , elem_values [ ] reflect . Value
key_type , key_values , value , err = DeserializeValue ( ctx , value , int ( map_len ) )
if err != nil {
return nil , nil , SerializedValue { } , err
}
elem_type , elem_values , value , err = DeserializeValue ( ctx , value , int ( map_len ) )
if err != nil {
return nil , nil , SerializedValue { } , err
}
map_type := reflect . MapOf ( key_type , elem_type )
map_value := reflect . MakeMap ( map_type )
for i := 0 ; i < int ( map_len ) ; i += 1 {
map_value . SetMapIndex ( key_values [ i ] , elem_values [ i ] )
}
return map_type , & map_value , value , nil
}
}
2023-09-02 17:30:52 -06:00
} )
if err != nil {
return nil , err
}
2023-09-03 17:50:12 -06:00
err = ctx . RegisterKind ( reflect . Int8 , NewSerializedType ( "int8" ) ,
func ( ctx * Context , ctx_type uint64 , reflect_type reflect . Type , value * reflect . Value ) ( SerializedValue , error ) {
var data [ ] byte = nil
if value != nil {
data = [ ] byte { byte ( value . Int ( ) ) }
}
return SerializedValue {
[ ] uint64 { ctx_type } ,
data ,
} , nil
} , func ( ctx * Context , value SerializedValue ) ( reflect . Type , * reflect . Value , SerializedValue , error ) {
if value . Data == nil {
return reflect . TypeOf ( int8 ( 0 ) ) , nil , value , nil
} else {
if len ( value . Data ) < 1 {
return nil , nil , SerializedValue { } , fmt . Errorf ( "Not enough data to deserialize int8" )
}
i := int8 ( value . Data [ 0 ] )
value . Data = value . Data [ 1 : ]
val := reflect . ValueOf ( i )
return val . Type ( ) , & val , value , nil
}
} )
if err != nil {
return nil , err
}
2023-09-02 17:30:52 -06:00
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-03 17:50:12 -06:00
} , func ( ctx * Context , value SerializedValue ) ( reflect . Type , * reflect . Value , SerializedValue , error ) {
if value . Data == nil {
return reflect . TypeOf ( uint8 ( 0 ) ) , nil , value , nil
} else {
if len ( value . Data ) < 1 {
return nil , nil , SerializedValue { } , fmt . Errorf ( "Not enough data to deserialize uint8" )
}
i := uint8 ( value . Data [ 0 ] )
value . Data = value . Data [ 1 : ]
val := reflect . ValueOf ( i )
return val . Type ( ) , & val , value , nil
}
} )
if err != nil {
return nil , err
}
err = ctx . RegisterKind ( reflect . Uint16 , NewSerializedType ( "uint16" ) ,
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 , 2 )
binary . BigEndian . PutUint16 ( data , uint16 ( value . Uint ( ) ) )
}
return SerializedValue {
[ ] uint64 { ctx_type } ,
data ,
} , nil
} , func ( ctx * Context , value SerializedValue ) ( reflect . Type , * reflect . Value , SerializedValue , error ) {
if value . Data == nil {
return reflect . TypeOf ( uint16 ( 0 ) ) , nil , value , nil
} else {
if len ( value . Data ) < 2 {
return nil , nil , SerializedValue { } , fmt . Errorf ( "Not enough data to deserialize uint16" )
}
val := binary . BigEndian . Uint16 ( value . Data [ 0 : 2 ] )
value . Data = value . Data [ 2 : ]
i := reflect . ValueOf ( val )
return i . Type ( ) , & i , value , nil
}
} )
if err != nil {
return nil , err
}
err = ctx . RegisterKind ( reflect . Int16 , NewSerializedType ( "int16" ) ,
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 , 2 )
binary . BigEndian . PutUint16 ( data , uint16 ( value . Int ( ) ) )
}
return SerializedValue {
[ ] uint64 { ctx_type } ,
data ,
} , nil
} , func ( ctx * Context , value SerializedValue ) ( reflect . Type , * reflect . Value , SerializedValue , error ) {
if value . Data == nil {
return reflect . TypeOf ( int16 ( 0 ) ) , nil , value , nil
} else {
if len ( value . Data ) < 2 {
return nil , nil , SerializedValue { } , fmt . Errorf ( "Not enough data to deserialize uint16" )
}
val := int16 ( binary . BigEndian . Uint16 ( value . Data [ 0 : 2 ] ) )
value . Data = value . Data [ 2 : ]
i := reflect . ValueOf ( val )
return i . Type ( ) , & i , value , nil
}
} )
if err != nil {
return nil , err
}
err = ctx . RegisterKind ( reflect . Int32 , NewSerializedType ( "int32" ) ,
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 , 4 )
binary . BigEndian . PutUint32 ( data , uint32 ( value . Int ( ) ) )
}
return SerializedValue {
[ ] uint64 { ctx_type } ,
data ,
} , nil
} , func ( ctx * Context , value SerializedValue ) ( reflect . Type , * reflect . Value , SerializedValue , error ) {
if value . Data == nil {
return reflect . TypeOf ( int32 ( 0 ) ) , nil , value , nil
} else {
if len ( value . Data ) < 4 {
return nil , nil , SerializedValue { } , fmt . Errorf ( "Not enough data to deserialize uint16" )
}
val := int32 ( binary . BigEndian . Uint32 ( value . Data [ 0 : 4 ] ) )
value . Data = value . Data [ 4 : ]
i := reflect . ValueOf ( val )
return i . Type ( ) , & i , value , nil
}
} )
if err != nil {
return nil , err
}
err = ctx . RegisterKind ( reflect . Uint , NewSerializedType ( "uint" ) ,
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
} , func ( ctx * Context , value SerializedValue ) ( reflect . Type , * reflect . Value , SerializedValue , error ) {
if value . Data == nil {
return reflect . TypeOf ( uint ( 0 ) ) , nil , value , nil
} else {
if len ( value . Data ) < 8 {
return nil , nil , SerializedValue { } , fmt . Errorf ( "Not enough data to deserialize uint64" )
}
val := uint ( binary . BigEndian . Uint64 ( value . Data [ 0 : 8 ] ) )
value . Data = value . Data [ 8 : ]
i := reflect . ValueOf ( val )
return i . Type ( ) , & i , value , nil
}
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-03 17:50:12 -06:00
} , func ( ctx * Context , value SerializedValue ) ( reflect . Type , * reflect . Value , SerializedValue , error ) {
if value . Data == nil {
return reflect . TypeOf ( uint64 ( 0 ) ) , nil , value , nil
} else {
if len ( value . Data ) < 8 {
return nil , nil , SerializedValue { } , fmt . Errorf ( "Not enough data to deserialize uint64" )
}
val := binary . BigEndian . Uint64 ( value . Data [ 0 : 8 ] )
value . Data = value . Data [ 8 : ]
i := reflect . ValueOf ( val )
return i . Type ( ) , & i , value , nil
}
} )
if err != nil {
return nil , err
}
err = ctx . RegisterKind ( reflect . Int64 , NewSerializedType ( "int64" ) ,
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 , uint64 ( value . Int ( ) ) )
}
return SerializedValue {
[ ] uint64 { ctx_type } ,
data ,
} , nil
} , func ( ctx * Context , value SerializedValue ) ( reflect . Type , * reflect . Value , SerializedValue , error ) {
if value . Data == nil {
return reflect . TypeOf ( int64 ( 0 ) ) , nil , value , nil
} else {
if len ( value . Data ) < 8 {
return nil , nil , SerializedValue { } , fmt . Errorf ( "Not enough data to deserialize uint64" )
}
val := int64 ( binary . BigEndian . Uint64 ( value . Data [ 0 : 8 ] ) )
value . Data = value . Data [ 8 : ]
i := reflect . ValueOf ( val )
return i . Type ( ) , & i , value , nil
}
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
2023-09-03 17:50:12 -06:00
var type_stack [ ] uint64 = nil
2023-08-31 22:31:29 -06:00
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 ( ) ) )
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-03 17:50:12 -06:00
type_stack ,
2023-08-31 22:31:29 -06:00
data ,
} , nil
}
2023-09-03 17:50:12 -06:00
element , 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-03 17:50:12 -06:00
append ( [ ] uint64 { ctx_type } , element . TypeStack ... ) ,
2023-08-31 22:31:29 -06:00
data ,
} , nil
2023-09-03 17:50:12 -06:00
} , func ( ctx * Context , value SerializedValue ) ( reflect . Type , * reflect . Value , SerializedValue , error ) {
if value . Data == nil {
elem_type , _ , _ , err := DeserializeValue ( ctx , value , 1 )
if err != nil {
return nil , nil , SerializedValue { } , err
}
return reflect . SliceOf ( elem_type ) , nil , value , nil
} else if len ( value . Data ) < 8 {
return nil , nil , SerializedValue { } , fmt . Errorf ( "Not enough data to deserialize slice" )
} else {
slice_length := binary . BigEndian . Uint64 ( value . Data [ 0 : 8 ] )
value . Data = value . Data [ 8 : ]
if slice_length == 0xFFFFFFFFFFFFFFFF {
elem_type , _ , remaining , err := DeserializeValue ( ctx , SerializedValue {
value . TypeStack ,
nil ,
} , 1 )
if err != nil {
return nil , nil , SerializedValue { } , err
}
reflect_type := reflect . SliceOf ( elem_type )
reflect_value := reflect . New ( reflect_type ) . Elem ( )
return reflect_type , & reflect_value , SerializedValue {
remaining . TypeStack ,
value . Data ,
} , nil
} else if slice_length == 0x00 {
elem_type , _ , remaining , err := DeserializeValue ( ctx , value , 1 )
if err != nil {
return nil , nil , SerializedValue { } , err
}
reflect_value := reflect . MakeSlice ( reflect . SliceOf ( elem_type ) , 0 , 0 )
return reflect_value . Type ( ) , & reflect_value , SerializedValue {
remaining . TypeStack ,
value . Data ,
} , nil
} else {
elem_type , elements , remaining_data , err := DeserializeValue ( ctx , value , int ( slice_length ) )
if err != nil {
return nil , nil , SerializedValue { } , err
}
reflect_value := reflect . MakeSlice ( reflect . SliceOf ( elem_type ) , 0 , int ( slice_length ) )
for i := 0 ; i < int ( slice_length ) ; i += 1 {
reflect_value = reflect . Append ( reflect_value , elements [ i ] )
}
return reflect_value . Type ( ) , & reflect_value , remaining_data , nil
}
}
2023-09-02 18:49:37 -06:00
} )
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
2023-09-03 17:50:12 -06:00
} , func ( ctx * Context , value SerializedValue ) ( reflect . Type , * reflect . Value , SerializedValue , error ) {
return nil , nil , SerializedValue { } , fmt . Errorf ( "unimplemented" )
2023-09-02 18:49:37 -06:00
} )
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
2023-09-03 17:50:12 -06:00
} , func ( ctx * Context , value SerializedValue ) ( reflect . Type , * reflect . Value , SerializedValue , error ) {
return nil , nil , SerializedValue { } , 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-03 17:50:12 -06:00
} , func ( ctx * Context , value SerializedValue ) ( reflect . Type , * reflect . Value , SerializedValue , error ) {
return reflect . TypeOf ( Up ) , nil , SerializedValue { } , 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-03 17:50:12 -06:00
} , func ( ctx * Context , value SerializedValue ) ( reflect . Type , * reflect . Value , SerializedValue , error ) {
return reflect . TypeOf ( ReqState ( 0 ) ) , nil , SerializedValue { } , 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
}