Added more serialized stuf

gql_cataclysm
noah metz 2023-10-16 00:54:10 -06:00
parent 92bb4bf976
commit 95939fb020
4 changed files with 190 additions and 76 deletions

@ -1186,6 +1186,36 @@ func NewContext(db * badger.DB, log Logger) (*Context, error) {
return nil, err
}
err = ctx.RegisterType(reflect.TypeOf(time.Duration(0)), DurationType,
func(ctx *Context, ctx_type SerializedType, reflect_type reflect.Type, value *reflect.Value)(SerializedValue,error){
var data []byte
type_stack := []SerializedType{ctx_type}
if value == nil {
data = nil
} else {
data := make([]byte, 8)
binary.BigEndian.PutUint64(data, uint64(value.Int()))
}
return SerializedValue{
type_stack,
data,
}, nil
},func(ctx *Context, value SerializedValue)(reflect.Type,*reflect.Value,SerializedValue,error){
if value.Data == nil {
return reflect.TypeOf(time.Duration(0)), nil, value, nil
} else {
var bytes []byte
var err error
bytes, value, err = value.PopData(8)
if err != nil {
return nil, nil, value, err
}
duration := time.Duration(int64(binary.BigEndian.Uint64(bytes)))
duration_value := reflect.ValueOf(duration)
return duration_value.Type(), &duration_value, value, nil
}
})
err = ctx.RegisterType(reflect.TypeOf(time.Time{}), TimeType,
func(ctx *Context, ctx_type SerializedType, reflect_type reflect.Type, value *reflect.Value)(SerializedValue,error) {
var data []byte
@ -1321,6 +1351,11 @@ func NewContext(db * badger.DB, log Logger) (*Context, error) {
return nil, err
}
err = ctx.RegisterSignal(reflect.TypeOf(StoppedSignal{}), StoppedSignalType)
if err != nil {
return nil, err
}
err = ctx.RegisterSignal(reflect.TypeOf(AddSubGroupSignal{}), AddSubGroupSignalType)
if err != nil {
return nil, err

109
gql.go

@ -843,6 +843,9 @@ type GQLExtContext struct {
Query *graphql.Object
Mutation *graphql.Object
Subscription *graphql.Object
TypeMap map[reflect.Type]GQLTypeInfo
KindMap map[reflect.Kind]GQLTypeInfo
}
func (ctx *GQLExtContext) GetACLFields(obj_name string, names []string) (map[ExtType][]string, error) {
@ -1159,6 +1162,110 @@ func NewGQLExtContext() *GQLExtContext {
Fields: graphql.Fields{},
})
kind_map := map[reflect.Kind]GQLTypeInfo{
reflect.String: {
func(ctx *GQLExtContext, reflect_type reflect.Type)(graphql.Type, error) {
return graphql.String, nil
},
func(ctx *GQLExtContext, value interface{})(reflect.Value, error) {
return reflect.ValueOf(value), nil
},
},
reflect.Bool: {
func(ctx *GQLExtContext, reflect_type reflect.Type)(graphql.Type, error) {
return graphql.Boolean, nil
},
func(ctx *GQLExtContext, value interface{})(reflect.Value, error) {
return reflect.ValueOf(value), nil
},
},
}
type_map := map[reflect.Type]GQLTypeInfo{
reflect.TypeOf([2]NodeID{}): {
func(ctx *GQLExtContext, reflect_type reflect.Type)(graphql.Type, error) {
return graphql.NewList(graphql.String), nil
},
func(ctx *GQLExtContext, value interface{})(reflect.Value, error) {
l, ok := value.([]interface{})
if ok == false {
return reflect.Value{}, fmt.Errorf("not list: %s", reflect.TypeOf(value))
} else if len(l) != 2 {
return reflect.Value{}, fmt.Errorf("wrong length: %d/2", len(l))
}
id1_str, ok := l[0].(string)
if ok == false {
return reflect.Value{}, fmt.Errorf("not strg: %s", reflect.TypeOf(l[0]))
}
id1, err := ParseID(id1_str)
if err != nil {
return reflect.Value{}, err
}
id2_str, ok := l[1].(string)
if ok == false {
return reflect.Value{}, fmt.Errorf("not strg: %s", reflect.TypeOf(l[1]))
}
id2, err := ParseID(id2_str)
if err != nil {
return reflect.Value{}, err
}
return_value := reflect.New(reflect.TypeOf([2]NodeID{})).Elem()
return_value.Index(0).Set(reflect.ValueOf(id1))
return_value.Index(1).Set(reflect.ValueOf(id2))
return return_value, nil
},
},
reflect.TypeOf(time.Time{}): {
func(ctx *GQLExtContext, reflect_type reflect.Type) (graphql.Type, error) {
return graphql.DateTime, nil
},
func(ctx *GQLExtContext, value interface{}) (reflect.Value, error) {
return reflect.ValueOf(value), nil
},
},
reflect.TypeOf(&NodeID{}): {
func(ctx *GQLExtContext, reflect_type reflect.Type) (graphql.Type, error) {
return graphql.String, nil
},
func(ctx *GQLExtContext, value interface{}) (reflect.Value, error) {
str, ok := value.(string)
if ok == false {
return reflect.Value{}, fmt.Errorf("value is not string")
}
if str == "" {
return reflect.New(reflect.TypeOf(&NodeID{})).Elem(), nil
}
id_parsed, err := ParseID(str)
if err != nil {
return reflect.Value{}, err
}
return reflect.ValueOf(&id_parsed), nil
},
},
reflect.TypeOf(NodeID{}): {
func(ctx *GQLExtContext, reflect_type reflect.Type)(graphql.Type, error) {
return graphql.String, nil
},
func(ctx *GQLExtContext, value interface{})(reflect.Value, error) {
str, ok := value.(string)
if ok == false {
return reflect.Value{}, fmt.Errorf("value is not string")
}
id_parsed, err := ParseID(str)
if err != nil {
return reflect.Value{}, err
}
return reflect.ValueOf(id_parsed), nil
},
},
}
context := GQLExtContext{
Schema: graphql.Schema{},
Types: []graphql.Type{},
@ -1168,6 +1275,8 @@ func NewGQLExtContext() *GQLExtContext {
NodeTypes: map[NodeType]*graphql.Object{},
Interfaces: map[string]*Interface{},
Fields: map[string]Field{},
KindMap: kind_map,
TypeMap: type_map,
}
var err error

@ -8,63 +8,25 @@ import (
"time"
)
type GQLTypeConverter func(*GQLExtContext, reflect.Type)(graphql.Type, error)
type GQLValueConverter func(*GQLExtContext, interface{})(reflect.Value, error)
type GQLTypeInfo struct {
graphql.Type
FromGQL func(interface{})(reflect.Value, error)
Type GQLTypeConverter
Value GQLValueConverter
}
var kind_gql_map = map[reflect.Kind]GQLTypeInfo{
reflect.String: {
graphql.String,
func(value interface{})(reflect.Value, error) {
return reflect.ValueOf(value), nil
},
},
reflect.Bool: {
graphql.Boolean,
func(value interface{})(reflect.Value, error) {
return reflect.ValueOf(value), nil
},
},
}
var type_gql_map = map[reflect.Type]GQLTypeInfo{
reflect.TypeOf(&NodeID{}): {
graphql.String,
func(value interface{}) (reflect.Value, error) {
str, ok := value.(string)
if ok == false {
return reflect.Value{}, fmt.Errorf("value is not string")
}
if str == "" {
return reflect.New(reflect.TypeOf(&NodeID{})).Elem(), nil
}
id_parsed, err := ParseID(str)
if err != nil {
return reflect.Value{}, err
}
return reflect.ValueOf(&id_parsed), nil
},
},
reflect.TypeOf(NodeID{}): {
graphql.String,
func(value interface{})(reflect.Value, error) {
str, ok := value.(string)
if ok == false {
return reflect.Value{}, fmt.Errorf("value is not string")
func GetGQLTypeInfo(ctx *GQLExtContext, reflect_type reflect.Type) (*GQLTypeInfo, error) {
type_info, type_mapped := ctx.TypeMap[reflect_type]
if type_mapped == false {
kind_info, kind_mapped := ctx.KindMap[reflect_type.Kind()]
if kind_mapped == false {
return nil, fmt.Errorf("Signal has unsupported type/kind: %s/%s", reflect_type, reflect_type.Kind())
} else {
return &kind_info, nil
}
id_parsed, err := ParseID(str)
if err != nil {
return reflect.Value{}, err
} else {
return &type_info, nil
}
return reflect.ValueOf(id_parsed), nil
},
},
}
type StructFieldInfo struct {
@ -74,7 +36,7 @@ type StructFieldInfo struct {
Index []int
}
func SignalFromArgs(signal_type reflect.Type, fields []StructFieldInfo, args map[string]interface{}, id_index, direction_index []int) (Signal, error) {
func SignalFromArgs(ctx *GQLExtContext, signal_type reflect.Type, fields []StructFieldInfo, args map[string]interface{}, id_index, direction_index []int) (Signal, error) {
signal_value := reflect.New(signal_type)
id_field := signal_value.Elem().FieldByIndex(id_index)
@ -92,7 +54,7 @@ func SignalFromArgs(signal_type reflect.Type, fields []StructFieldInfo, args map
if field_value.CanConvert(field.Type) == false {
return nil, fmt.Errorf("Arg %s wrong type %s/%s", field.Name, field_value.Type(), field.Type)
}
value, err := field.GQL.FromGQL(arg)
value, err := field.GQL.Value(ctx, arg)
if err != nil {
return nil, err
}
@ -101,6 +63,25 @@ func SignalFromArgs(signal_type reflect.Type, fields []StructFieldInfo, args map
return signal_value.Interface().(Signal), nil
}
func ArgumentInfo(ctx *GQLExtContext, field reflect.StructField, gv_tag string) (*graphql.ArgumentConfig, StructFieldInfo, error) {
gql_info, err := GetGQLTypeInfo(ctx, field.Type)
if err != nil {
return nil, StructFieldInfo{}, err
}
gql_type, err := gql_info.Type(ctx, field.Type)
if err != nil {
return nil, StructFieldInfo{}, err
}
return &graphql.ArgumentConfig{
Type: gql_type,
}, StructFieldInfo{
gv_tag,
field.Type,
gql_info,
field.Index,
}, nil
}
func (ext *GQLExtContext) AddSignalMutation(name string, send_id_key string, signal_type reflect.Type) error {
args := graphql.FieldConfigArgument{}
arg_info := []StructFieldInfo{}
@ -118,27 +99,14 @@ func (ext *GQLExtContext) AddSignalMutation(name string, send_id_key string, sig
_, exists := args[gv_tag]
if exists == true {
return fmt.Errorf("Signal has repeated tag %s", gv_tag)
} else {
config, info, err := ArgumentInfo(ext, field, gv_tag)
if err != nil {
return err
}
var gql_info GQLTypeInfo
var type_mapped bool
gql_info, type_mapped = type_gql_map[field.Type]
if type_mapped == false {
var kind_mapped bool
gql_info, kind_mapped = kind_gql_map[field.Type.Kind()]
if kind_mapped == false {
return fmt.Errorf("Signal has unsupported type/kind: %s/%s", field.Type, field.Type.Kind())
}
}
args[gv_tag] = &graphql.ArgumentConfig{
Type: gql_info.Type,
args[gv_tag] = config
arg_info = append(arg_info, info)
}
arg_info = append(arg_info, StructFieldInfo{
gv_tag,
field.Type,
&gql_info,
field.Index,
})
}
}
}
@ -161,7 +129,7 @@ func (ext *GQLExtContext) AddSignalMutation(name string, send_id_key string, sig
return nil, err
}
signal, err := SignalFromArgs(signal_type, arg_info, p.Args, id_index, direction_index)
signal, err := SignalFromArgs(ctx.GQLContext, signal_type, arg_info, p.Args, id_index, direction_index)
if err != nil {
return nil, err
}

@ -106,6 +106,7 @@ var (
ACLSignalType = NewSignalType("ACL")
AddSubGroupSignalType = NewSignalType("ADD_SUBGROUP")
RemoveSubGroupSignalType = NewSignalType("REMOVE_SUBGROUP")
StoppedSignalType = NewSignalType("STOPPED")
MemberOfPolicyType = NewPolicyType("USER_OF")
RequirementOfPolicyType = NewPolicyType("REQUIEMENT_OF")
@ -152,6 +153,7 @@ var (
PendingACLType = NewSerializedType("PENDING_ACL")
PendingSignalType = NewSerializedType("PENDING_SIGNAL")
TimeType = NewSerializedType("TIME")
DurationType = NewSerializedType("DURATION")
ResponseType = NewSerializedType("RESPONSE")
StatusType = NewSerializedType("STATUS")
TreeType = NewSerializedType("TREE")