package main
import "C"
import (
"context"
"fmt"
"time"
"unsafe"
pb "github.com/authzed/authzed-go/proto/authzed/api/v1"
"google.golang.org/grpc"
"google.golang.org/protobuf/proto"
)
func runRPC(handle C.ulonglong, reqBytes []byte, outResp **C.uchar, outLen *C.int, outErr **C.char,
unmarshalReq func([]byte) (proto.Message, error),
callRPC func(context.Context, *grpc.ClientConn, proto.Message) (proto.Message, error),
) {
*outResp = nil
*outLen = 0
*outErr = nil
instanceMu.RLock()
instance, ok := instances[uint64(handle)]
instanceMu.RUnlock()
if !ok || instance == nil {
*outErr = C.CString(fmt.Sprintf("invalid handle: %d", handle))
return
}
if instance.clientConn == nil {
*outErr = C.CString("instance not available for FFI RPCs")
return
}
req, err := unmarshalReq(reqBytes)
if err != nil {
*outErr = C.CString(err.Error())
return
}
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
resp, err := callRPC(ctx, instance.clientConn, req)
if err != nil {
*outErr = C.CString(err.Error())
return
}
respBytes, err := proto.Marshal(resp)
if err != nil {
*outErr = C.CString(fmt.Sprintf("failed to marshal response: %v", err))
return
}
n := len(respBytes)
*outLen = C.int(n)
if n > 0 {
*outResp = (*C.uchar)(C.CBytes(respBytes))
}
}
func spicedb_free_bytes(ptr *C.void) {
if ptr != nil {
C.free(unsafe.Pointer(ptr))
}
}
func spicedb_permissions_check_bulk_permissions(
handle C.ulonglong,
requestBytes *C.uchar,
requestLen C.int,
outResponseBytes **C.uchar,
outResponseLen *C.int,
outError **C.char,
) {
reqBytes := C.GoBytes(unsafe.Pointer(requestBytes), requestLen)
runRPC(handle, reqBytes, outResponseBytes, outResponseLen, outError,
func(b []byte) (proto.Message, error) {
var req pb.CheckBulkPermissionsRequest
if err := proto.Unmarshal(b, &req); err != nil {
return nil, err
}
return &req, nil
},
func(ctx context.Context, conn *grpc.ClientConn, req proto.Message) (proto.Message, error) {
return pb.NewPermissionsServiceClient(conn).CheckBulkPermissions(ctx, req.(*pb.CheckBulkPermissionsRequest))
},
)
}
func spicedb_permissions_check_permission(
handle C.ulonglong,
requestBytes *C.uchar,
requestLen C.int,
outResponseBytes **C.uchar,
outResponseLen *C.int,
outError **C.char,
) {
reqBytes := C.GoBytes(unsafe.Pointer(requestBytes), requestLen)
runRPC(handle, reqBytes, outResponseBytes, outResponseLen, outError,
func(b []byte) (proto.Message, error) {
var req pb.CheckPermissionRequest
if err := proto.Unmarshal(b, &req); err != nil {
return nil, err
}
return &req, nil
},
func(ctx context.Context, conn *grpc.ClientConn, req proto.Message) (proto.Message, error) {
return pb.NewPermissionsServiceClient(conn).CheckPermission(ctx, req.(*pb.CheckPermissionRequest))
},
)
}
func spicedb_permissions_delete_relationships(
handle C.ulonglong,
requestBytes *C.uchar,
requestLen C.int,
outResponseBytes **C.uchar,
outResponseLen *C.int,
outError **C.char,
) {
reqBytes := C.GoBytes(unsafe.Pointer(requestBytes), requestLen)
runRPC(handle, reqBytes, outResponseBytes, outResponseLen, outError,
func(b []byte) (proto.Message, error) {
var req pb.DeleteRelationshipsRequest
if err := proto.Unmarshal(b, &req); err != nil {
return nil, err
}
return &req, nil
},
func(ctx context.Context, conn *grpc.ClientConn, req proto.Message) (proto.Message, error) {
return pb.NewPermissionsServiceClient(conn).DeleteRelationships(ctx, req.(*pb.DeleteRelationshipsRequest))
},
)
}
func spicedb_permissions_expand_permission_tree(
handle C.ulonglong,
requestBytes *C.uchar,
requestLen C.int,
outResponseBytes **C.uchar,
outResponseLen *C.int,
outError **C.char,
) {
reqBytes := C.GoBytes(unsafe.Pointer(requestBytes), requestLen)
runRPC(handle, reqBytes, outResponseBytes, outResponseLen, outError,
func(b []byte) (proto.Message, error) {
var req pb.ExpandPermissionTreeRequest
if err := proto.Unmarshal(b, &req); err != nil {
return nil, err
}
return &req, nil
},
func(ctx context.Context, conn *grpc.ClientConn, req proto.Message) (proto.Message, error) {
return pb.NewPermissionsServiceClient(conn).ExpandPermissionTree(ctx, req.(*pb.ExpandPermissionTreeRequest))
},
)
}
func spicedb_permissions_write_relationships(
handle C.ulonglong,
requestBytes *C.uchar,
requestLen C.int,
outResponseBytes **C.uchar,
outResponseLen *C.int,
outError **C.char,
) {
reqBytes := C.GoBytes(unsafe.Pointer(requestBytes), requestLen)
runRPC(handle, reqBytes, outResponseBytes, outResponseLen, outError,
func(b []byte) (proto.Message, error) {
var req pb.WriteRelationshipsRequest
if err := proto.Unmarshal(b, &req); err != nil {
return nil, err
}
return &req, nil
},
func(ctx context.Context, conn *grpc.ClientConn, req proto.Message) (proto.Message, error) {
return pb.NewPermissionsServiceClient(conn).WriteRelationships(ctx, req.(*pb.WriteRelationshipsRequest))
},
)
}
func spicedb_schema_read_schema(
handle C.ulonglong,
requestBytes *C.uchar,
requestLen C.int,
outResponseBytes **C.uchar,
outResponseLen *C.int,
outError **C.char,
) {
reqBytes := C.GoBytes(unsafe.Pointer(requestBytes), requestLen)
runRPC(handle, reqBytes, outResponseBytes, outResponseLen, outError,
func(b []byte) (proto.Message, error) {
var req pb.ReadSchemaRequest
if err := proto.Unmarshal(b, &req); err != nil {
return nil, err
}
return &req, nil
},
func(ctx context.Context, conn *grpc.ClientConn, req proto.Message) (proto.Message, error) {
return pb.NewSchemaServiceClient(conn).ReadSchema(ctx, req.(*pb.ReadSchemaRequest))
},
)
}
func spicedb_schema_write_schema(
handle C.ulonglong,
requestBytes *C.uchar,
requestLen C.int,
outResponseBytes **C.uchar,
outResponseLen *C.int,
outError **C.char,
) {
reqBytes := C.GoBytes(unsafe.Pointer(requestBytes), requestLen)
runRPC(handle, reqBytes, outResponseBytes, outResponseLen, outError,
func(b []byte) (proto.Message, error) {
var req pb.WriteSchemaRequest
if err := proto.Unmarshal(b, &req); err != nil {
return nil, err
}
return &req, nil
},
func(ctx context.Context, conn *grpc.ClientConn, req proto.Message) (proto.Message, error) {
return pb.NewSchemaServiceClient(conn).WriteSchema(ctx, req.(*pb.WriteSchemaRequest))
},
)
}