summaryrefslogtreecommitdiff
path: root/grpc
diff options
context:
space:
mode:
Diffstat (limited to 'grpc')
-rw-r--r--grpc/examples/README.md7
-rw-r--r--grpc/examples/generate.sh18
-rw-r--r--grpc/examples/go/greeter/.gitignore2
-rw-r--r--grpc/examples/go/greeter/README.md25
-rw-r--r--grpc/examples/go/greeter/client/go.mod11
-rw-r--r--grpc/examples/go/greeter/client/main.go74
-rw-r--r--grpc/examples/go/greeter/models/Greeter_grpc.go158
-rw-r--r--grpc/examples/go/greeter/models/HelloReply.go52
-rw-r--r--grpc/examples/go/greeter/models/HelloRequest.go52
-rw-r--r--grpc/examples/go/greeter/models/go.mod8
-rw-r--r--grpc/examples/go/greeter/server/go.mod11
-rw-r--r--grpc/examples/go/greeter/server/main.go78
-rw-r--r--grpc/examples/greeter.fbs14
-rw-r--r--grpc/src/compiler/go_generator.cc159
-rw-r--r--grpc/src/compiler/schema_interface.h4
-rw-r--r--grpc/tests/go_test.go4
16 files changed, 623 insertions, 54 deletions
diff --git a/grpc/examples/README.md b/grpc/examples/README.md
new file mode 100644
index 00000000..f5694a84
--- /dev/null
+++ b/grpc/examples/README.md
@@ -0,0 +1,7 @@
+## Languages known issues
+
+### Go
+
+- Always requires the `content-type` of the payload to be set to `application/grpc+flatbuffers`
+
+example: `.SayHello(ctx, b, grpc.CallContentSubtype("flatbuffers"))` \ No newline at end of file
diff --git a/grpc/examples/generate.sh b/grpc/examples/generate.sh
new file mode 100644
index 00000000..4f481919
--- /dev/null
+++ b/grpc/examples/generate.sh
@@ -0,0 +1,18 @@
+current_dir=`pwd`
+
+cd ../..
+
+main_dir=`pwd`
+
+cd ${current_dir}
+
+alias fbc='${main_dir}/Debug/flatc'
+generator="--grpc $current_dir/greeter.fbs"
+
+# Regenerate Go lang code
+cd go/
+
+cd greeter
+fbc --go ${generator}
+
+cd ../.. \ No newline at end of file
diff --git a/grpc/examples/go/greeter/.gitignore b/grpc/examples/go/greeter/.gitignore
new file mode 100644
index 00000000..535db5e3
--- /dev/null
+++ b/grpc/examples/go/greeter/.gitignore
@@ -0,0 +1,2 @@
+**/server
+**/client \ No newline at end of file
diff --git a/grpc/examples/go/greeter/README.md b/grpc/examples/go/greeter/README.md
new file mode 100644
index 00000000..33905088
--- /dev/null
+++ b/grpc/examples/go/greeter/README.md
@@ -0,0 +1,25 @@
+# Go Greeter example
+
+## Project Structure
+
+ .
+ ├── server # Server module
+ ├── client # Client module
+ ├── models # Flatbuffers models & main grpc code.
+ └── README.md
+
+## How to run Server:
+
+- `cd server`
+
+- `go clean`
+
+- `go run main.go`
+
+## How to run Client:
+
+- `cd client`
+
+- `go clean`
+
+- `go run main.go --name NAME` \ No newline at end of file
diff --git a/grpc/examples/go/greeter/client/go.mod b/grpc/examples/go/greeter/client/go.mod
new file mode 100644
index 00000000..19689dd4
--- /dev/null
+++ b/grpc/examples/go/greeter/client/go.mod
@@ -0,0 +1,11 @@
+module github.com/google/flatbuffers/grpc/examples/go/greeter/client
+
+go 1.15
+
+replace github.com/google/flatbuffers/grpc/examples/go/greeter/models v0.0.0 => ../models
+
+require (
+ github.com/google/flatbuffers v1.12.0
+ github.com/google/flatbuffers/grpc/examples/go/greeter/models v0.0.0
+ google.golang.org/grpc v1.35.0
+)
diff --git a/grpc/examples/go/greeter/client/main.go b/grpc/examples/go/greeter/client/main.go
new file mode 100644
index 00000000..49935761
--- /dev/null
+++ b/grpc/examples/go/greeter/client/main.go
@@ -0,0 +1,74 @@
+package main
+
+import (
+ "context"
+ "flag"
+ "fmt"
+ "io"
+ "log"
+ "time"
+
+ flatbuffers "github.com/google/flatbuffers/go"
+ models "github.com/google/flatbuffers/grpc/examples/go/greeter/models"
+ "google.golang.org/grpc"
+)
+
+var (
+ addr = "3000"
+ name = flag.String("name", "Flatbuffers", "name to be sent to server :D")
+)
+
+func printSayHello(client models.GreeterClient, name string) {
+ log.Printf("Name to be sent (%s)", name)
+ b := flatbuffers.NewBuilder(0)
+ i := b.CreateString(name)
+ models.HelloRequestStart(b)
+ models.HelloRequestAddName(b, i)
+ b.Finish(models.HelloRequestEnd(b))
+
+ ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
+ defer cancel()
+ request, err := client.SayHello(ctx, b, grpc.CallContentSubtype("flatbuffers"))
+ if err != nil {
+ log.Fatalf("%v.SayHello(_) = _, %v: ", client, err)
+ }
+ log.Printf("server said %q", request.Message())
+}
+
+func printSayManyHello(client models.GreeterClient, name string) {
+ log.Printf("Name to be sent (%s)", name)
+ b := flatbuffers.NewBuilder(0)
+ i := b.CreateString(name)
+ models.HelloRequestStart(b)
+ models.HelloRequestAddName(b, i)
+ b.Finish(models.HelloRequestEnd(b))
+
+ ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
+ defer cancel()
+ stream, err := client.SayManyHellos(ctx, b, grpc.CallContentSubtype("flatbuffers"))
+ if err != nil {
+ log.Fatalf("%v.SayManyHellos(_) = _, %v", client, err)
+ }
+ for {
+ request, err := stream.Recv()
+ if err == io.EOF {
+ break
+ }
+ if err != nil {
+ log.Fatalf("%v.SayManyHellos(_) = _, %v", client, err)
+ }
+ log.Printf("server said %q", request.Message())
+ }
+}
+
+func main() {
+ flag.Parse()
+ conn, err := grpc.Dial(fmt.Sprintf("localhost:%d", 3000), grpc.WithInsecure(), grpc.WithCodec(flatbuffers.FlatbuffersCodec{}))
+ if err != nil {
+ log.Fatalf("fail to dial: %v", err)
+ }
+ defer conn.Close()
+ client := models.NewGreeterClient(conn)
+ printSayHello(client, *name)
+ printSayManyHello(client, *name)
+}
diff --git a/grpc/examples/go/greeter/models/Greeter_grpc.go b/grpc/examples/go/greeter/models/Greeter_grpc.go
new file mode 100644
index 00000000..9a2405c7
--- /dev/null
+++ b/grpc/examples/go/greeter/models/Greeter_grpc.go
@@ -0,0 +1,158 @@
+//Generated by gRPC Go plugin
+//If you make any local changes, they will be lost
+//source: greeter
+
+package models
+
+import (
+ context "context"
+ flatbuffers "github.com/google/flatbuffers/go"
+ grpc "google.golang.org/grpc"
+ "google.golang.org/grpc/codes"
+ "google.golang.org/grpc/status"
+)
+
+// Client API for Greeter service
+type GreeterClient interface {
+ SayHello(ctx context.Context, in *flatbuffers.Builder,
+ opts ...grpc.CallOption) (*HelloReply, error)
+ SayManyHellos(ctx context.Context, in *flatbuffers.Builder,
+ opts ...grpc.CallOption) (Greeter_SayManyHellosClient, error)
+}
+
+type greeterClient struct {
+ cc grpc.ClientConnInterface
+}
+
+func NewGreeterClient(cc grpc.ClientConnInterface) GreeterClient {
+ return &greeterClient{cc}
+}
+
+func (c *greeterClient) SayHello(ctx context.Context, in *flatbuffers.Builder,
+ opts ...grpc.CallOption) (*HelloReply, error) {
+ out := new(HelloReply)
+ err := c.cc.Invoke(ctx, "/models.Greeter/SayHello", in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *greeterClient) SayManyHellos(ctx context.Context, in *flatbuffers.Builder,
+ opts ...grpc.CallOption) (Greeter_SayManyHellosClient, error) {
+ stream, err := c.cc.NewStream(ctx, &_Greeter_serviceDesc.Streams[0], "/models.Greeter/SayManyHellos", opts...)
+ if err != nil {
+ return nil, err
+ }
+ x := &greeterSayManyHellosClient{stream}
+ if err := x.ClientStream.SendMsg(in); err != nil {
+ return nil, err
+ }
+ if err := x.ClientStream.CloseSend(); err != nil {
+ return nil, err
+ }
+ return x, nil
+}
+
+type Greeter_SayManyHellosClient interface {
+ Recv() (*HelloReply, error)
+ grpc.ClientStream
+}
+
+type greeterSayManyHellosClient struct {
+ grpc.ClientStream
+}
+
+func (x *greeterSayManyHellosClient) Recv() (*HelloReply, error) {
+ m := new(HelloReply)
+ if err := x.ClientStream.RecvMsg(m); err != nil {
+ return nil, err
+ }
+ return m, nil
+}
+
+// Server API for Greeter service
+type GreeterServer interface {
+ SayHello(context.Context, *HelloRequest) (*flatbuffers.Builder, error)
+ SayManyHellos(*HelloRequest, Greeter_SayManyHellosServer) error
+ mustEmbedUnimplementedGreeterServer()
+}
+
+type UnimplementedGreeterServer struct {
+}
+
+func (UnimplementedGreeterServer) SayHello(context.Context, *HelloRequest) (*flatbuffers.Builder, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method SayHello not implemented")
+}
+
+func (UnimplementedGreeterServer) SayManyHellos(*HelloRequest, Greeter_SayManyHellosServer) error {
+ return status.Errorf(codes.Unimplemented, "method SayManyHellos not implemented")
+}
+
+func (UnimplementedGreeterServer) mustEmbedUnimplementedGreeterServer() {}
+
+type UnsafeGreeterServer interface {
+ mustEmbedUnimplementedGreeterServer()
+}
+
+func RegisterGreeterServer(s grpc.ServiceRegistrar, srv GreeterServer) {
+ s.RegisterService(&_Greeter_serviceDesc, srv)
+}
+
+func _Greeter_SayHello_Handler(srv interface{}, ctx context.Context,
+ dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(HelloRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(GreeterServer).SayHello(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/models.Greeter/SayHello",
+ }
+
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(GreeterServer).SayHello(ctx, req.(*HelloRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+func _Greeter_SayManyHellos_Handler(srv interface{}, stream grpc.ServerStream) error {
+ m := new(HelloRequest)
+ if err := stream.RecvMsg(m); err != nil {
+ return err
+ }
+ return srv.(GreeterServer).SayManyHellos(m, &greeterSayManyHellosServer{stream})
+}
+
+type Greeter_SayManyHellosServer interface {
+ Send(*flatbuffers.Builder) error
+ grpc.ServerStream
+}
+
+type greeterSayManyHellosServer struct {
+ grpc.ServerStream
+}
+
+func (x *greeterSayManyHellosServer) Send(m *flatbuffers.Builder) error {
+ return x.ServerStream.SendMsg(m)
+}
+
+var _Greeter_serviceDesc = grpc.ServiceDesc{
+ ServiceName: "models.Greeter",
+ HandlerType: (*GreeterServer)(nil),
+ Methods: []grpc.MethodDesc{
+ {
+ MethodName: "SayHello",
+ Handler: _Greeter_SayHello_Handler,
+ },
+ },
+ Streams: []grpc.StreamDesc{
+ {
+ StreamName: "SayManyHellos",
+ Handler: _Greeter_SayManyHellos_Handler,
+ ServerStreams: true,
+ },
+ },
+}
diff --git a/grpc/examples/go/greeter/models/HelloReply.go b/grpc/examples/go/greeter/models/HelloReply.go
new file mode 100644
index 00000000..bb5db407
--- /dev/null
+++ b/grpc/examples/go/greeter/models/HelloReply.go
@@ -0,0 +1,52 @@
+// Code generated by the FlatBuffers compiler. DO NOT EDIT.
+
+package models
+
+import (
+ flatbuffers "github.com/google/flatbuffers/go"
+)
+
+type HelloReply struct {
+ _tab flatbuffers.Table
+}
+
+func GetRootAsHelloReply(buf []byte, offset flatbuffers.UOffsetT) *HelloReply {
+ n := flatbuffers.GetUOffsetT(buf[offset:])
+ x := &HelloReply{}
+ x.Init(buf, n+offset)
+ return x
+}
+
+func GetSizePrefixedRootAsHelloReply(buf []byte, offset flatbuffers.UOffsetT) *HelloReply {
+ n := flatbuffers.GetUOffsetT(buf[offset+flatbuffers.SizeUint32:])
+ x := &HelloReply{}
+ x.Init(buf, n+offset+flatbuffers.SizeUint32)
+ return x
+}
+
+func (rcv *HelloReply) Init(buf []byte, i flatbuffers.UOffsetT) {
+ rcv._tab.Bytes = buf
+ rcv._tab.Pos = i
+}
+
+func (rcv *HelloReply) Table() flatbuffers.Table {
+ return rcv._tab
+}
+
+func (rcv *HelloReply) Message() []byte {
+ o := flatbuffers.UOffsetT(rcv._tab.Offset(4))
+ if o != 0 {
+ return rcv._tab.ByteVector(o + rcv._tab.Pos)
+ }
+ return nil
+}
+
+func HelloReplyStart(builder *flatbuffers.Builder) {
+ builder.StartObject(1)
+}
+func HelloReplyAddMessage(builder *flatbuffers.Builder, message flatbuffers.UOffsetT) {
+ builder.PrependUOffsetTSlot(0, flatbuffers.UOffsetT(message), 0)
+}
+func HelloReplyEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
+ return builder.EndObject()
+}
diff --git a/grpc/examples/go/greeter/models/HelloRequest.go b/grpc/examples/go/greeter/models/HelloRequest.go
new file mode 100644
index 00000000..52feab97
--- /dev/null
+++ b/grpc/examples/go/greeter/models/HelloRequest.go
@@ -0,0 +1,52 @@
+// Code generated by the FlatBuffers compiler. DO NOT EDIT.
+
+package models
+
+import (
+ flatbuffers "github.com/google/flatbuffers/go"
+)
+
+type HelloRequest struct {
+ _tab flatbuffers.Table
+}
+
+func GetRootAsHelloRequest(buf []byte, offset flatbuffers.UOffsetT) *HelloRequest {
+ n := flatbuffers.GetUOffsetT(buf[offset:])
+ x := &HelloRequest{}
+ x.Init(buf, n+offset)
+ return x
+}
+
+func GetSizePrefixedRootAsHelloRequest(buf []byte, offset flatbuffers.UOffsetT) *HelloRequest {
+ n := flatbuffers.GetUOffsetT(buf[offset+flatbuffers.SizeUint32:])
+ x := &HelloRequest{}
+ x.Init(buf, n+offset+flatbuffers.SizeUint32)
+ return x
+}
+
+func (rcv *HelloRequest) Init(buf []byte, i flatbuffers.UOffsetT) {
+ rcv._tab.Bytes = buf
+ rcv._tab.Pos = i
+}
+
+func (rcv *HelloRequest) Table() flatbuffers.Table {
+ return rcv._tab
+}
+
+func (rcv *HelloRequest) Name() []byte {
+ o := flatbuffers.UOffsetT(rcv._tab.Offset(4))
+ if o != 0 {
+ return rcv._tab.ByteVector(o + rcv._tab.Pos)
+ }
+ return nil
+}
+
+func HelloRequestStart(builder *flatbuffers.Builder) {
+ builder.StartObject(1)
+}
+func HelloRequestAddName(builder *flatbuffers.Builder, name flatbuffers.UOffsetT) {
+ builder.PrependUOffsetTSlot(0, flatbuffers.UOffsetT(name), 0)
+}
+func HelloRequestEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
+ return builder.EndObject()
+}
diff --git a/grpc/examples/go/greeter/models/go.mod b/grpc/examples/go/greeter/models/go.mod
new file mode 100644
index 00000000..01976de5
--- /dev/null
+++ b/grpc/examples/go/greeter/models/go.mod
@@ -0,0 +1,8 @@
+module github.com/google/flatbuffers/grpc/examples/go/greeter/models
+
+go 1.15
+
+require (
+ github.com/google/flatbuffers v1.12.0
+ google.golang.org/grpc v1.35.0
+)
diff --git a/grpc/examples/go/greeter/server/go.mod b/grpc/examples/go/greeter/server/go.mod
new file mode 100644
index 00000000..2572feee
--- /dev/null
+++ b/grpc/examples/go/greeter/server/go.mod
@@ -0,0 +1,11 @@
+module github.com/google/flatbuffers/grpc/examples/go/greeter/server
+
+go 1.15
+
+replace github.com/google/flatbuffers/grpc/examples/go/greeter/models v0.0.0 => ../models
+
+require (
+ github.com/google/flatbuffers v1.12.0
+ github.com/google/flatbuffers/grpc/examples/go/greeter/models v0.0.0
+ google.golang.org/grpc v1.35.0
+)
diff --git a/grpc/examples/go/greeter/server/main.go b/grpc/examples/go/greeter/server/main.go
new file mode 100644
index 00000000..61914208
--- /dev/null
+++ b/grpc/examples/go/greeter/server/main.go
@@ -0,0 +1,78 @@
+package main
+
+import (
+ "context"
+ "fmt"
+ "log"
+ "net"
+
+ flatbuffers "github.com/google/flatbuffers/go"
+ models "github.com/google/flatbuffers/grpc/examples/go/greeter/models"
+ "google.golang.org/grpc"
+ "google.golang.org/grpc/encoding"
+)
+
+var (
+ greetings = [...]string{"Hi", "Hallo", "Ciao"}
+)
+
+type greeterServer struct {
+ models.UnimplementedGreeterServer
+}
+
+func (s *greeterServer) SayHello(ctx context.Context, request *models.HelloRequest) (*flatbuffers.Builder, error) {
+ v := request.Name()
+ var m string
+ if v == nil {
+ m = "Unknown"
+ } else {
+ m = string(v)
+ }
+ b := flatbuffers.NewBuilder(0)
+ idx := b.CreateString("welcome " + m)
+ models.HelloReplyStart(b)
+ models.HelloReplyAddMessage(b, idx)
+ b.Finish(models.HelloReplyEnd(b))
+ return b, nil
+}
+
+func (s *greeterServer) SayManyHellos(request *models.HelloRequest, stream models.Greeter_SayManyHellosServer) error {
+ v := request.Name()
+ var m string
+ if v == nil {
+ m = "Unknown"
+ } else {
+ m = string(v)
+ }
+ b := flatbuffers.NewBuilder(0)
+
+ for _, greeting := range greetings {
+ idx := b.CreateString(greeting + " " + m)
+ models.HelloReplyStart(b)
+ models.HelloReplyAddMessage(b, idx)
+ b.Finish(models.HelloReplyEnd(b))
+ if err := stream.Send(b); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func newServer() *greeterServer {
+ s := &greeterServer{}
+ return s
+}
+
+func main() {
+ lis, err := net.Listen("tcp", fmt.Sprintf("localhost:%d", 3000))
+ if err != nil {
+ log.Fatalf("failed to listen: %v", err)
+ }
+ grpcServer := grpc.NewServer()
+ encoding.RegisterCodec(flatbuffers.FlatbuffersCodec{})
+ models.RegisterGreeterServer(grpcServer, newServer())
+ if err := grpcServer.Serve(lis); err != nil {
+ fmt.Print(err)
+ panic(err)
+ }
+}
diff --git a/grpc/examples/greeter.fbs b/grpc/examples/greeter.fbs
new file mode 100644
index 00000000..651fb677
--- /dev/null
+++ b/grpc/examples/greeter.fbs
@@ -0,0 +1,14 @@
+namespace models;
+
+table HelloReply {
+ message:string;
+}
+
+table HelloRequest {
+ name:string;
+}
+
+rpc_service Greeter {
+ SayHello(HelloRequest):HelloReply;
+ SayManyHellos(HelloRequest):HelloReply (streaming: "server");
+}
diff --git a/grpc/src/compiler/go_generator.cc b/grpc/src/compiler/go_generator.cc
index 604828d6..d646451a 100644
--- a/grpc/src/compiler/go_generator.cc
+++ b/grpc/src/compiler/go_generator.cc
@@ -70,6 +70,17 @@ grpc::string exportName(grpc::string s) {
return s;
}
+void GenerateError(grpc_generator::Printer *printer,
+ std::map<grpc::string, grpc::string> vars,
+ const bool multiple_return = true) {
+ printer->Print(vars, "if $Error_Check$ {\n");
+ printer->Indent();
+ vars["Return"] = multiple_return ? "nil, err" : "err";
+ printer->Print(vars, "return $Return$\n");
+ printer->Outdent();
+ printer->Print("}\n");
+}
+
// Generates imports for the service
void GenerateImports(grpc_generator::File *file, grpc_generator::Printer *printer,
std::map<grpc::string, grpc::string> vars) {
@@ -78,14 +89,13 @@ void GenerateImports(grpc_generator::File *file, grpc_generator::Printer *printe
printer->Print("//If you make any local changes, they will be lost\n");
printer->Print(vars, "//source: $filename$\n\n");
printer->Print(vars, "package $Package$\n\n");
- if (file->additional_headers() != "") {
- printer->Print(file->additional_headers().c_str());
- printer->Print("\n\n");
- }
printer->Print("import (\n");
printer->Indent();
printer->Print(vars, "$context$ \"context\"\n");
+ printer->Print("flatbuffers \"github.com/google/flatbuffers/go\"\n");
printer->Print(vars, "$grpc$ \"google.golang.org/grpc\"\n");
+ printer->Print("\"google.golang.org/grpc/codes\"\n");
+ printer->Print("\"google.golang.org/grpc/status\"\n");
printer->Outdent();
printer->Print(")\n\n");
}
@@ -93,15 +103,15 @@ void GenerateImports(grpc_generator::File *file, grpc_generator::Printer *printe
// Generates Server method signature source
void GenerateServerMethodSignature(const grpc_generator::Method *method, grpc_generator::Printer *printer,
std::map<grpc::string, grpc::string> vars) {
- vars["Method"] = exportName(method->name());
+ vars["Method"] = exportName(method->name());
vars["Request"] = method->get_input_type_name();
vars["Response"] = (vars["CustomMethodIO"] == "") ? method->get_output_type_name() : vars["CustomMethodIO"];
if (method->NoStreaming()) {
- printer->Print(vars, "$Method$($context$.Context, *$Request$) (*$Response$, error)");
+ printer->Print(vars, "$Method$($context$.Context, *$Request$) (*$Response$, error)$Ending$");
} else if (ServerOnlyStreaming(method)) {
- printer->Print(vars, "$Method$(*$Request$, $Service$_$Method$Server) error");
+ printer->Print(vars, "$Method$(*$Request$, $Service$_$Method$Server) error$Ending$");
} else {
- printer->Print(vars, "$Method$($Service$_$Method$Server) error");
+ printer->Print(vars, "$Method$($Service$_$Method$Server) error$Ending$");
}
}
@@ -110,28 +120,36 @@ void GenerateServerMethod(const grpc_generator::Method *method, grpc_generator::
vars["Method"] = exportName(method->name());
vars["Request"] = method->get_input_type_name();
vars["Response"] = (vars["CustomMethodIO"] == "") ? method->get_output_type_name() : vars["CustomMethodIO"];
- vars["FullMethodName"] = "/" + vars["ServicePrefix"] + "." + vars["Service"] + "/" + vars["Method"];
+ vars["FullMethodName"] = "/" + vars["ServicePrefix"] + vars["Service"] + "/" + vars["Method"];
vars["Handler"] = "_" + vars["Service"] + "_" + vars["Method"] + "_Handler";
if (method->NoStreaming()) {
printer->Print(vars, "func $Handler$(srv interface{}, ctx $context$.Context,\n\tdec func(interface{}) error, interceptor $grpc$.UnaryServerInterceptor) (interface{}, error) {\n");
printer->Indent();
printer->Print(vars, "in := new($Request$)\n");
- printer->Print("if err := dec(in); err != nil { return nil, err }\n");
- printer->Print(vars, "if interceptor == nil { return srv.($Service$Server).$Method$(ctx, in) }\n");
+ vars["Error_Check"] = "err := dec(in); err != nil";
+ GenerateError(printer, vars);
+ printer->Print("if interceptor == nil {\n");
+ printer->Indent();
+ printer->Print(vars, "return srv.($Service$Server).$Method$(ctx, in)\n");
+ printer->Outdent();
+ printer->Print("}\n");
printer->Print(vars, "info := &$grpc$.UnaryServerInfo{\n");
printer->Indent();
- printer->Print("Server: srv,\n");
+ printer->Print("Server: srv,\n");
printer->Print(vars, "FullMethod: \"$FullMethodName$\",\n");
printer->Outdent();
- printer->Print("}\n\n");
+ printer->Print("}\n");
+ printer->Outdent();
+ printer->Print("\n");
+ printer->Indent();
printer->Print(vars, "handler := func(ctx $context$.Context, req interface{}) (interface{}, error) {\n");
printer->Indent();
- printer->Print(vars, "return srv.($Service$Server).$Method$(ctx, req.(* $Request$))\n");
+ printer->Print(vars, "return srv.($Service$Server).$Method$(ctx, req.(*$Request$))\n");
printer->Outdent();
printer->Print("}\n");
printer->Print("return interceptor(ctx, in, info, handler)\n");
printer->Outdent();
- printer->Print("}\n\n");
+ printer->Print("}\n");
return;
}
vars["StreamType"] = vars["ServiceUnexported"] + vars["Method"] + "Server";
@@ -139,7 +157,8 @@ void GenerateServerMethod(const grpc_generator::Method *method, grpc_generator::
printer->Indent();
if (ServerOnlyStreaming(method)) {
printer->Print(vars, "m := new($Request$)\n");
- printer->Print(vars, "if err := stream.RecvMsg(m); err != nil { return err }\n");
+ vars["Error_Check"] = "err := stream.RecvMsg(m); err != nil";
+ GenerateError(printer, vars, false);
printer->Print(vars, "return srv.($Service$Server).$Method$(m, &$StreamType${stream})\n");
} else {
printer->Print(vars, "return srv.($Service$Server).$Method$(&$StreamType${stream})\n");
@@ -151,16 +170,16 @@ void GenerateServerMethod(const grpc_generator::Method *method, grpc_generator::
bool genRecv = method->BidiStreaming() || ClientOnlyStreaming(method);
bool genSendAndClose = ClientOnlyStreaming(method);
- printer->Print(vars, "type $Service$_$Method$Server interface { \n");
+ printer->Print(vars, "type $Service$_$Method$Server interface {\n");
printer->Indent();
if (genSend) {
- printer->Print(vars, "Send(* $Response$) error\n");
+ printer->Print(vars, "Send(*$Response$) error\n");
}
if (genRecv) {
- printer->Print(vars, "Recv() (* $Request$, error)\n");
+ printer->Print(vars, "Recv() (*$Request$, error)\n");
}
if (genSendAndClose) {
- printer->Print(vars, "SendAndClose(* $Response$) error\n");
+ printer->Print(vars, "SendAndClose(*$Response$) error\n");
}
printer->Print(vars, "$grpc$.ServerStream\n");
printer->Outdent();
@@ -183,7 +202,8 @@ void GenerateServerMethod(const grpc_generator::Method *method, grpc_generator::
printer->Print(vars, "func (x *$StreamType$) Recv() (*$Request$, error) {\n");
printer->Indent();
printer->Print(vars, "m := new($Request$)\n");
- printer->Print("if err := x.ServerStream.RecvMsg(m); err != nil { return nil, err }\n");
+ vars["Error_Check"] = "err := x.ServerStream.RecvMsg(m); err != nil";
+ GenerateError(printer, vars);
printer->Print("return m, nil\n");
printer->Outdent();
printer->Print("}\n\n");
@@ -206,43 +226,47 @@ void GenerateClientMethodSignature(const grpc_generator::Method *method, grpc_ge
if (ClientOnlyStreaming(method) || method->BidiStreaming()) {
vars["Request"] = "";
}
- vars["Response"] = "* " + method->get_output_type_name();
+ vars["Response"] = "*" + method->get_output_type_name();
if (ClientOnlyStreaming(method) || method->BidiStreaming() || ServerOnlyStreaming(method)) {
vars["Response"] = vars["Service"] + "_" + vars["Method"] + "Client" ;
}
- printer->Print(vars, "$Method$(ctx $context$.Context$Request$, \n\topts... $grpc$.CallOption) ($Response$, error)");
+ printer->Print(vars, "$Method$(ctx $context$.Context$Request$,\n\topts ...$grpc$.CallOption) ($Response$, error)$Ending$");
}
// Generates Client method source
void GenerateClientMethod(const grpc_generator::Method *method, grpc_generator::Printer *printer,
std::map<grpc::string, grpc::string> vars) {
printer->Print(vars, "func (c *$ServiceUnexported$Client) ");
+ vars["Ending"] = " {\n";
GenerateClientMethodSignature(method, printer, vars);
- printer->Print(" {\n");
printer->Indent();
vars["Method"] = exportName(method->name());
vars["Request"] = (vars["CustomMethodIO"] == "") ? method->get_input_type_name() : vars["CustomMethodIO"];
vars["Response"] = method->get_output_type_name();
- vars["FullMethodName"] = "/" + vars["ServicePrefix"] + "." + vars["Service"] + "/" + vars["Method"];
+ vars["FullMethodName"] = "/" + vars["ServicePrefix"] + vars["Service"] + "/" + vars["Method"];
if (method->NoStreaming()) {
printer->Print(vars, "out := new($Response$)\n");
- printer->Print(vars, "err := $grpc$.Invoke(ctx, \"$FullMethodName$\", in, out, c.cc, opts...)\n");
- printer->Print("if err != nil { return nil, err }\n");
+ printer->Print(vars, "err := c.cc.Invoke(ctx, \"$FullMethodName$\", in, out, opts...)\n");
+ vars["Error_Check"] = "err != nil";
+ GenerateError(printer, vars);
printer->Print("return out, nil\n");
printer->Outdent();
printer->Print("}\n\n");
return;
}
vars["StreamType"] = vars["ServiceUnexported"] + vars["Method"] + "Client";
- printer->Print(vars, "stream, err := $grpc$.NewClientStream(ctx, &$MethodDesc$, c.cc, \"$FullMethodName$\", opts...)\n");
- printer->Print("if err != nil { return nil, err }\n");
+ printer->Print(vars, "stream, err := c.cc.NewStream(ctx, &$MethodDesc$, \"$FullMethodName$\", opts...)\n");
+ vars["Error_Check"] = "err != nil";
+ GenerateError(printer, vars);
printer->Print(vars, "x := &$StreamType${stream}\n");
if (ServerOnlyStreaming(method)) {
- printer->Print("if err := x.ClientStream.SendMsg(in); err != nil { return nil, err }\n");
- printer->Print("if err := x.ClientStream.CloseSend(); err != nil { return nil, err }\n");
+ vars["Error_Check"] = "err := x.ClientStream.SendMsg(in); err != nil";
+ GenerateError(printer, vars);
+ vars["Error_Check"] = "err := x.ClientStream.CloseSend(); err != nil";
+ GenerateError(printer, vars);
}
- printer->Print("return x,nil\n");
+ printer->Print("return x, nil\n");
printer->Outdent();
printer->Print("}\n\n");
@@ -267,7 +291,7 @@ void GenerateClientMethod(const grpc_generator::Method *method, grpc_generator::
printer->Print("}\n\n");
//Stream Client
- printer->Print(vars, "type $StreamType$ struct{\n");
+ printer->Print(vars, "type $StreamType$ struct {\n");
printer->Indent();
printer->Print(vars, "$grpc$.ClientStream\n");
printer->Outdent();
@@ -285,7 +309,8 @@ void GenerateClientMethod(const grpc_generator::Method *method, grpc_generator::
printer->Print(vars, "func (x *$StreamType$) Recv() (*$Response$, error) {\n");
printer->Indent();
printer->Print(vars, "m := new($Response$)\n");
- printer->Print("if err := x.ClientStream.RecvMsg(m); err != nil { return nil, err }\n");
+ vars["Error_Check"] = "err := x.ClientStream.RecvMsg(m); err != nil";
+ GenerateError(printer, vars);
printer->Print("return m, nil\n");
printer->Outdent();
printer->Print("}\n\n");
@@ -294,9 +319,11 @@ void GenerateClientMethod(const grpc_generator::Method *method, grpc_generator::
if (genCloseAndRecv) {
printer->Print(vars, "func (x *$StreamType$) CloseAndRecv() (*$Response$, error) {\n");
printer->Indent();
- printer->Print("if err := x.ClientStream.CloseSend(); err != nil { return nil, err }\n");
- printer->Print(vars, "m := new ($Response$)\n");
- printer->Print("if err := x.ClientStream.RecvMsg(m); err != nil { return nil, err }\n");
+ vars["Error_Check"] = "err := x.ClientStream.CloseSend(); err != nil";
+ GenerateError(printer, vars);
+ printer->Print(vars, "m := new($Response$)\n");
+ vars["Error_Check"] = "err := x.ClientStream.RecvMsg(m); err != nil";
+ GenerateError(printer, vars);
printer->Print("return m, nil\n");
printer->Outdent();
printer->Print("}\n\n");
@@ -309,11 +336,11 @@ void GenerateService(const grpc_generator::Service *service, grpc_generator::Pri
vars["Service"] = exportName(service->name());
// Client Interface
printer->Print(vars, "// Client API for $Service$ service\n");
- printer->Print(vars, "type $Service$Client interface{\n");
+ printer->Print(vars, "type $Service$Client interface {\n");
printer->Indent();
+ vars["Ending"] = "\n";
for (int i = 0; i < service->method_count(); i++) {
GenerateClientMethodSignature(service->method(i).get(), printer, vars);
- printer->Print("\n");
}
printer->Outdent();
printer->Print("}\n\n");
@@ -322,12 +349,12 @@ void GenerateService(const grpc_generator::Service *service, grpc_generator::Pri
vars["ServiceUnexported"] = unexportName(vars["Service"]);
printer->Print(vars, "type $ServiceUnexported$Client struct {\n");
printer->Indent();
- printer->Print(vars, "cc *$grpc$.ClientConn\n");
+ printer->Print(vars, "cc $grpc$.ClientConnInterface\n");
printer->Outdent();
printer->Print("}\n\n");
// NewClient
- printer->Print(vars, "func New$Service$Client(cc *$grpc$.ClientConn) $Service$Client {\n");
+ printer->Print(vars, "func New$Service$Client(cc $grpc$.ClientConnInterface) $Service$Client {\n");
printer->Indent();
printer->Print(vars, "return &$ServiceUnexported$Client{cc}");
printer->Outdent();
@@ -351,15 +378,41 @@ void GenerateService(const grpc_generator::Service *service, grpc_generator::Pri
printer->Print(vars, "// Server API for $Service$ service\n");
printer->Print(vars, "type $Service$Server interface {\n");
printer->Indent();
+ vars["Ending"] = "\n";
for (int i = 0; i < service->method_count(); i++) {
GenerateServerMethodSignature(service->method(i).get(), printer, vars);
- printer->Print("\n");
}
+ printer->Print(vars, "mustEmbedUnimplemented$Service$Server()\n");
printer->Outdent();
printer->Print("}\n\n");
+ printer->Print(vars, "type Unimplemented$Service$Server struct {\n");
+ printer->Print("}\n\n");
+
+ vars["Ending"] = " {\n";
+ for (int i = 0; i < service->method_count(); i++) {
+ auto method = service->method(i);
+ vars["Method"] = exportName(method->name());
+ vars["Nil"] = method->NoStreaming() ? "nil, " : "";
+ printer->Print(vars, "func (Unimplemented$Service$Server) ");
+ GenerateServerMethodSignature(method.get(), printer, vars);
+ printer->Indent();
+ printer->Print(vars, "return $Nil$status.Errorf(codes.Unimplemented, \"method $Method$ not implemented\")\n");
+ printer->Outdent();
+ printer->Print("}\n");
+ printer->Print("\n");
+ }
+
+ printer->Print(vars, "func (Unimplemented$Service$Server) mustEmbedUnimplemented$Service$Server() {}");
+ printer->Print("\n\n");
+
+ printer->Print(vars, "type Unsafe$Service$Server interface {\n");
+ printer->Indent();
+ printer->Print(vars, "mustEmbedUnimplemented$Service$Server()\n");
+ printer->Outdent();
+ printer->Print("}\n\n");
// Server registration.
- printer->Print(vars, "func Register$Service$Server(s *$grpc$.Server, srv $Service$Server) {\n");
+ printer->Print(vars, "func Register$Service$Server(s $grpc$.ServiceRegistrar, srv $Service$Server) {\n");
printer->Indent();
printer->Print(vars, "s.RegisterService(&$ServiceDesc$, srv)\n");
printer->Outdent();
@@ -367,26 +420,25 @@ void GenerateService(const grpc_generator::Service *service, grpc_generator::Pri
for (int i = 0; i < service->method_count(); i++) {
GenerateServerMethod(service->method(i).get(), printer, vars);
- printer->Print("\n");
}
//Service Descriptor
printer->Print(vars, "var $ServiceDesc$ = $grpc$.ServiceDesc{\n");
printer->Indent();
- printer->Print(vars, "ServiceName: \"$ServicePrefix$.$Service$\",\n");
+ printer->Print(vars, "ServiceName: \"$ServicePrefix$$Service$\",\n");
printer->Print(vars, "HandlerType: (*$Service$Server)(nil),\n");
printer->Print(vars, "Methods: []$grpc$.MethodDesc{\n");
printer->Indent();
for (int i = 0; i < service->method_count(); i++) {
auto method = service->method(i);
- vars["Method"] = method->name();
+ vars["Method"] = exportName(method->name());
vars["Handler"] = "_" + vars["Service"] + "_" + vars["Method"] + "_Handler";
if (method->NoStreaming()) {
printer->Print("{\n");
printer->Indent();
printer->Print(vars, "MethodName: \"$Method$\",\n");
- printer->Print(vars, "Handler: $Handler$, \n");
+ printer->Print(vars, "Handler: $Handler$,\n");
printer->Outdent();
printer->Print("},\n");
}
@@ -397,13 +449,13 @@ void GenerateService(const grpc_generator::Service *service, grpc_generator::Pri
printer->Indent();
for (int i = 0; i < service->method_count(); i++) {
auto method = service->method(i);
- vars["Method"] = method->name();
+ vars["Method"] = exportName(method->name());
vars["Handler"] = "_" + vars["Service"] + "_" + vars["Method"] + "_Handler";
if (!method->NoStreaming()) {
printer->Print("{\n");
printer->Indent();
- printer->Print(vars, "StreamName: \"$Method$\",\n");
- printer->Print(vars, "Handler: $Handler$, \n");
+ printer->Print(vars, "StreamName: \"$Method$\",\n");
+ printer->Print(vars, "Handler: $Handler$,\n");
if (ClientOnlyStreaming(method.get())) {
printer->Print("ClientStreams: true,\n");
} else if (ServerOnlyStreaming(method.get())) {
@@ -419,7 +471,7 @@ void GenerateService(const grpc_generator::Service *service, grpc_generator::Pri
printer->Outdent();
printer->Print("},\n");
printer->Outdent();
- printer->Print("}\n\n");
+ printer->Print("}\n");
}
@@ -429,11 +481,14 @@ grpc::string GenerateServiceSource(grpc_generator::File *file,
const grpc_generator::Service *service,
grpc_go_generator::Parameters *parameters) {
grpc::string out;
- auto p = file->CreatePrinter(&out);
+ auto p = file->CreatePrinter(&out, '\t');
+ p->SetIndentationSize(1);
auto printer = p.get();
std::map<grpc::string, grpc::string> vars;
vars["Package"] = parameters->package_name;
vars["ServicePrefix"] = parameters->service_prefix;
+ if (!parameters->service_prefix.empty())
+ vars["ServicePrefix"].append(".");
vars["grpc"] = "grpc";
vars["context"] = "context";
GenerateImports(file, printer, vars);
diff --git a/grpc/src/compiler/schema_interface.h b/grpc/src/compiler/schema_interface.h
index c03ffe7a..04494981 100644
--- a/grpc/src/compiler/schema_interface.h
+++ b/grpc/src/compiler/schema_interface.h
@@ -93,6 +93,7 @@ struct Printer {
virtual void Print(const std::map<grpc::string, grpc::string> &vars,
const char *template_string) = 0;
virtual void Print(const char *string) = 0;
+ virtual void SetIndentationSize(const int size) = 0;
virtual void Indent() = 0;
virtual void Outdent() = 0;
};
@@ -111,7 +112,8 @@ struct File : public CommentHolder {
virtual int service_count() const = 0;
virtual std::unique_ptr<const Service> service(int i) const = 0;
- virtual std::unique_ptr<Printer> CreatePrinter(grpc::string *str) const = 0;
+ virtual std::unique_ptr<Printer> CreatePrinter(
+ grpc::string *str, const char indentation_type = ' ') const = 0;
};
} // namespace grpc_generator
diff --git a/grpc/tests/go_test.go b/grpc/tests/go_test.go
index 12681697..260e236a 100644
--- a/grpc/tests/go_test.go
+++ b/grpc/tests/go_test.go
@@ -2,12 +2,14 @@ package testing
import (
"../../tests/MyGame/Example"
+ flatbuffers "github.com/google/flatbuffers/go"
"context"
"net"
"testing"
"google.golang.org/grpc"
+ "google.golang.org/grpc/encoding"
)
type server struct{}
@@ -75,7 +77,7 @@ func TestGRPC(t *testing.T) {
t.Fatalf("Failed to listen: %v", err)
}
ser := grpc.NewServer()
- encoding.RegisterCodec(flatbuffers.FlatbuffersCodec{})
+ encoding.RegisterCodec(flatbuffers.FlatbuffersCodec{})
Example.RegisterMonsterStorageServer(ser, &server{})
go func() {
if err := ser.Serve(lis); err != nil {