blob: 2a9895e43c4e04906926a01748595a7dac277037 [file] [log] [blame]
nnobleebebb7e2014-12-10 16:31:01 -08001/*
2 *
3 * Copyright 2014, Google Inc.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following disclaimer
14 * in the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Google Inc. nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 */
33
Nicolas "Pixel" Noble36f53232015-01-16 06:39:58 +010034#include <string>
35#include <map>
36
nnobleebebb7e2014-12-10 16:31:01 -080037#include "src/compiler/cpp_generator.h"
38
39#include "src/compiler/cpp_generator_helpers.h"
40#include <google/protobuf/descriptor.h>
41#include <google/protobuf/descriptor.pb.h>
42#include <google/protobuf/io/printer.h>
43#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
Craig Tiller8c8d0aa2015-02-12 11:38:36 -080044#include <sstream>
nnobleebebb7e2014-12-10 16:31:01 -080045
46namespace grpc_cpp_generator {
47namespace {
48
Craig Tiller8c8d0aa2015-02-12 11:38:36 -080049template <class T>
50std::string as_string(T x) {
51 std::ostringstream out;
52 out << x;
53 return out.str();
54}
55
Craig Tillerecd49342015-01-18 14:36:47 -080056bool NoStreaming(const google::protobuf::MethodDescriptor *method) {
Craig Tillerb5dcec52015-01-13 11:13:42 -080057 return !method->client_streaming() && !method->server_streaming();
nnobleebebb7e2014-12-10 16:31:01 -080058}
59
Craig Tillerecd49342015-01-18 14:36:47 -080060bool ClientOnlyStreaming(const google::protobuf::MethodDescriptor *method) {
Craig Tillerb5dcec52015-01-13 11:13:42 -080061 return method->client_streaming() && !method->server_streaming();
nnobleebebb7e2014-12-10 16:31:01 -080062}
63
Craig Tillerecd49342015-01-18 14:36:47 -080064bool ServerOnlyStreaming(const google::protobuf::MethodDescriptor *method) {
yangg1b151092015-01-09 15:31:05 -080065 return !method->client_streaming() && method->server_streaming();
nnobleebebb7e2014-12-10 16:31:01 -080066}
67
Craig Tillerecd49342015-01-18 14:36:47 -080068bool BidiStreaming(const google::protobuf::MethodDescriptor *method) {
Craig Tillerb5dcec52015-01-13 11:13:42 -080069 return method->client_streaming() && method->server_streaming();
nnobleebebb7e2014-12-10 16:31:01 -080070}
71
Craig Tiller2dff17d2015-02-09 12:42:23 -080072bool HasUnaryCalls(const google::protobuf::FileDescriptor *file) {
73 for (int i = 0; i < file->service_count(); i++) {
74 for (int j = 0; j < file->service(i)->method_count(); j++) {
75 if (NoStreaming(file->service(i)->method(j))) {
76 return true;
77 }
78 }
79 }
80 return false;
81}
82
Craig Tillerecd49342015-01-18 14:36:47 -080083bool HasClientOnlyStreaming(const google::protobuf::FileDescriptor *file) {
nnobleebebb7e2014-12-10 16:31:01 -080084 for (int i = 0; i < file->service_count(); i++) {
85 for (int j = 0; j < file->service(i)->method_count(); j++) {
86 if (ClientOnlyStreaming(file->service(i)->method(j))) {
87 return true;
88 }
89 }
90 }
91 return false;
92}
93
Craig Tillerecd49342015-01-18 14:36:47 -080094bool HasServerOnlyStreaming(const google::protobuf::FileDescriptor *file) {
nnobleebebb7e2014-12-10 16:31:01 -080095 for (int i = 0; i < file->service_count(); i++) {
96 for (int j = 0; j < file->service(i)->method_count(); j++) {
97 if (ServerOnlyStreaming(file->service(i)->method(j))) {
98 return true;
99 }
100 }
101 }
102 return false;
103}
104
Craig Tillerecd49342015-01-18 14:36:47 -0800105bool HasBidiStreaming(const google::protobuf::FileDescriptor *file) {
nnobleebebb7e2014-12-10 16:31:01 -0800106 for (int i = 0; i < file->service_count(); i++) {
107 for (int j = 0; j < file->service(i)->method_count(); j++) {
108 if (BidiStreaming(file->service(i)->method(j))) {
109 return true;
110 }
111 }
112 }
113 return false;
114}
115} // namespace
116
Craig Tillerecd49342015-01-18 14:36:47 -0800117std::string GetHeaderIncludes(const google::protobuf::FileDescriptor *file) {
Nicolas Noblef5c5d802015-01-15 16:36:13 -0800118 std::string temp =
Craig Tiller14a65f92015-02-09 13:13:14 -0800119 "#include <grpc++/impl/internal_stub.h>\n"
120 "#include <grpc++/impl/service_type.h>\n"
121 "#include <grpc++/status.h>\n"
nnobleebebb7e2014-12-10 16:31:01 -0800122 "\n"
123 "namespace grpc {\n"
Craig Tiller8c8d0aa2015-02-12 11:38:36 -0800124 "class CompletionQueue;\n"
nnobleebebb7e2014-12-10 16:31:01 -0800125 "class ChannelInterface;\n"
yangga4b6f5d2014-12-17 15:53:12 -0800126 "class RpcService;\n"
127 "class ServerContext;\n";
Craig Tiller2dff17d2015-02-09 12:42:23 -0800128 if (HasUnaryCalls(file)) {
Craig Tiller5ef5db12015-02-09 12:47:21 -0800129 temp.append(
130 "template <class OutMessage> class ServerAsyncResponseWriter;\n");
Craig Tiller2dff17d2015-02-09 12:42:23 -0800131 }
nnobleebebb7e2014-12-10 16:31:01 -0800132 if (HasClientOnlyStreaming(file)) {
133 temp.append("template <class OutMessage> class ClientWriter;\n");
134 temp.append("template <class InMessage> class ServerReader;\n");
Craig Tiller2dff17d2015-02-09 12:42:23 -0800135 temp.append("template <class OutMessage> class ClientAsyncWriter;\n");
Yang Gao005f18a2015-02-13 10:22:33 -0800136 temp.append("template <class OutMessage, class InMessage> class ServerAsyncReader;\n");
nnobleebebb7e2014-12-10 16:31:01 -0800137 }
138 if (HasServerOnlyStreaming(file)) {
139 temp.append("template <class InMessage> class ClientReader;\n");
140 temp.append("template <class OutMessage> class ServerWriter;\n");
Craig Tiller2dff17d2015-02-09 12:42:23 -0800141 temp.append("template <class OutMessage> class ClientAsyncReader;\n");
142 temp.append("template <class InMessage> class ServerAsyncWriter;\n");
nnobleebebb7e2014-12-10 16:31:01 -0800143 }
144 if (HasBidiStreaming(file)) {
145 temp.append(
146 "template <class OutMessage, class InMessage>\n"
147 "class ClientReaderWriter;\n");
148 temp.append(
149 "template <class OutMessage, class InMessage>\n"
150 "class ServerReaderWriter;\n");
Craig Tiller225f7be2015-02-09 22:32:37 -0800151 temp.append(
152 "template <class OutMessage, class InMessage>\n"
153 "class ClientAsyncReaderWriter;\n");
154 temp.append(
155 "template <class OutMessage, class InMessage>\n"
156 "class ServerAsyncReaderWriter;\n");
nnobleebebb7e2014-12-10 16:31:01 -0800157 }
158 temp.append("} // namespace grpc\n");
159 return temp;
160}
161
Nicolas Noblef5c5d802015-01-15 16:36:13 -0800162std::string GetSourceIncludes() {
Craig Tiller2dff17d2015-02-09 12:42:23 -0800163 return "#include <grpc++/channel_interface.h>\n"
Craig Tiller80e00a82015-02-09 20:54:25 -0800164 "#include <grpc++/impl/client_unary_call.h>\n"
Craig Tiller2dff17d2015-02-09 12:42:23 -0800165 "#include <grpc++/impl/rpc_method.h>\n"
166 "#include <grpc++/impl/rpc_service_method.h>\n"
Craig Tiller14a65f92015-02-09 13:13:14 -0800167 "#include <grpc++/impl/service_type.h>\n"
Craig Tiller2dff17d2015-02-09 12:42:23 -0800168 "#include <grpc++/stream.h>\n";
nnobleebebb7e2014-12-10 16:31:01 -0800169}
170
Craig Tillerecd49342015-01-18 14:36:47 -0800171void PrintHeaderClientMethod(google::protobuf::io::Printer *printer,
172 const google::protobuf::MethodDescriptor *method,
173 std::map<std::string, std::string> *vars) {
nnobleebebb7e2014-12-10 16:31:01 -0800174 (*vars)["Method"] = method->name();
175 (*vars)["Request"] =
176 grpc_cpp_generator::ClassName(method->input_type(), true);
177 (*vars)["Response"] =
178 grpc_cpp_generator::ClassName(method->output_type(), true);
179 if (NoStreaming(method)) {
180 printer->Print(*vars,
181 "::grpc::Status $Method$(::grpc::ClientContext* context, "
Craig Tiller5ef5db12015-02-09 12:47:21 -0800182 "const $Request$& request, $Response$* response);\n");
183 printer->Print(*vars,
184 "void $Method$(::grpc::ClientContext* context, "
185 "const $Request$& request, $Response$* response, "
Yang Gao068c85b2015-02-12 15:21:24 -0800186 "::grpc::Status* status, "
187 "::grpc::CompletionQueue* cq, void* tag);\n");
nnobleebebb7e2014-12-10 16:31:01 -0800188 } else if (ClientOnlyStreaming(method)) {
Craig Tiller5ef5db12015-02-09 12:47:21 -0800189 printer->Print(*vars,
190 "::grpc::ClientWriter< $Request$>* $Method$("
191 "::grpc::ClientContext* context, $Response$* response);\n");
192 printer->Print(*vars,
Yang Gaoe0b73fd2015-02-12 14:05:47 -0800193 "::grpc::ClientAsyncWriter< $Request$>* $Method$("
Craig Tiller5ef5db12015-02-09 12:47:21 -0800194 "::grpc::ClientContext* context, $Response$* response, "
Yang Gao068c85b2015-02-12 15:21:24 -0800195 "::grpc::CompletionQueue* cq, void* tag);\n");
nnobleebebb7e2014-12-10 16:31:01 -0800196 } else if (ServerOnlyStreaming(method)) {
197 printer->Print(
198 *vars,
Yang Gao1ff11f62015-01-14 11:45:32 -0800199 "::grpc::ClientReader< $Response$>* $Method$("
Craig Tiller5ef5db12015-02-09 12:47:21 -0800200 "::grpc::ClientContext* context, const $Request$* request);\n");
201 printer->Print(*vars,
Yang Gaoe0b73fd2015-02-12 14:05:47 -0800202 "::grpc::ClientAsyncReader< $Response$>* $Method$("
Craig Tiller5ef5db12015-02-09 12:47:21 -0800203 "::grpc::ClientContext* context, const $Request$* request, "
Yang Gao068c85b2015-02-12 15:21:24 -0800204 "::grpc::CompletionQueue* cq, void* tag);\n");
nnobleebebb7e2014-12-10 16:31:01 -0800205 } else if (BidiStreaming(method)) {
206 printer->Print(*vars,
Yang Gao1ff11f62015-01-14 11:45:32 -0800207 "::grpc::ClientReaderWriter< $Request$, $Response$>* "
Craig Tiller5ef5db12015-02-09 12:47:21 -0800208 "$Method$(::grpc::ClientContext* context);\n");
209 printer->Print(*vars,
Craig Tiller225f7be2015-02-09 22:32:37 -0800210 "::grpc::ClientAsyncReaderWriter< $Request$, $Response$>* "
Craig Tiller5ef5db12015-02-09 12:47:21 -0800211 "$Method$(::grpc::ClientContext* context, "
Yang Gao068c85b2015-02-12 15:21:24 -0800212 "::grpc::CompletionQueue* cq, void* tag);\n");
nnobleebebb7e2014-12-10 16:31:01 -0800213 }
214}
215
Craig Tiller5ef5db12015-02-09 12:47:21 -0800216void PrintHeaderServerMethodSync(
217 google::protobuf::io::Printer *printer,
218 const google::protobuf::MethodDescriptor *method,
219 std::map<std::string, std::string> *vars) {
nnobleebebb7e2014-12-10 16:31:01 -0800220 (*vars)["Method"] = method->name();
221 (*vars)["Request"] =
222 grpc_cpp_generator::ClassName(method->input_type(), true);
223 (*vars)["Response"] =
224 grpc_cpp_generator::ClassName(method->output_type(), true);
225 if (NoStreaming(method)) {
226 printer->Print(*vars,
yangga4b6f5d2014-12-17 15:53:12 -0800227 "virtual ::grpc::Status $Method$("
228 "::grpc::ServerContext* context, const $Request$* request, "
nnobleebebb7e2014-12-10 16:31:01 -0800229 "$Response$* response);\n");
230 } else if (ClientOnlyStreaming(method)) {
231 printer->Print(*vars,
232 "virtual ::grpc::Status $Method$("
yangga4b6f5d2014-12-17 15:53:12 -0800233 "::grpc::ServerContext* context, "
Yang Gao1ff11f62015-01-14 11:45:32 -0800234 "::grpc::ServerReader< $Request$>* reader, "
nnobleebebb7e2014-12-10 16:31:01 -0800235 "$Response$* response);\n");
236 } else if (ServerOnlyStreaming(method)) {
237 printer->Print(*vars,
yangga4b6f5d2014-12-17 15:53:12 -0800238 "virtual ::grpc::Status $Method$("
239 "::grpc::ServerContext* context, const $Request$* request, "
Yang Gao1ff11f62015-01-14 11:45:32 -0800240 "::grpc::ServerWriter< $Response$>* writer);\n");
nnobleebebb7e2014-12-10 16:31:01 -0800241 } else if (BidiStreaming(method)) {
Yang Gao5680ff42015-01-14 12:14:21 -0800242 printer->Print(
243 *vars,
244 "virtual ::grpc::Status $Method$("
245 "::grpc::ServerContext* context, "
246 "::grpc::ServerReaderWriter< $Response$, $Request$>* stream);"
247 "\n");
nnobleebebb7e2014-12-10 16:31:01 -0800248 }
249}
250
Craig Tiller5ef5db12015-02-09 12:47:21 -0800251void PrintHeaderServerMethodAsync(
252 google::protobuf::io::Printer *printer,
253 const google::protobuf::MethodDescriptor *method,
254 std::map<std::string, std::string> *vars) {
Craig Tiller2dff17d2015-02-09 12:42:23 -0800255 (*vars)["Method"] = method->name();
256 (*vars)["Request"] =
257 grpc_cpp_generator::ClassName(method->input_type(), true);
258 (*vars)["Response"] =
259 grpc_cpp_generator::ClassName(method->output_type(), true);
260 if (NoStreaming(method)) {
261 printer->Print(*vars,
Yang Gaoca3cb3e2015-02-12 00:05:11 -0800262 "void Request$Method$("
Craig Tiller2dff17d2015-02-09 12:42:23 -0800263 "::grpc::ServerContext* context, $Request$* request, "
264 "::grpc::ServerAsyncResponseWriter< $Response$>* response, "
265 "::grpc::CompletionQueue* cq, void *tag);\n");
266 } else if (ClientOnlyStreaming(method)) {
267 printer->Print(*vars,
Yang Gaoca3cb3e2015-02-12 00:05:11 -0800268 "void Request$Method$("
Craig Tiller2dff17d2015-02-09 12:42:23 -0800269 "::grpc::ServerContext* context, "
Yang Gao005f18a2015-02-13 10:22:33 -0800270 "::grpc::ServerAsyncReader< $Response$, $Request$>* reader, "
Craig Tiller2dff17d2015-02-09 12:42:23 -0800271 "::grpc::CompletionQueue* cq, void *tag);\n");
272 } else if (ServerOnlyStreaming(method)) {
273 printer->Print(*vars,
Yang Gaoca3cb3e2015-02-12 00:05:11 -0800274 "void Request$Method$("
Craig Tiller2dff17d2015-02-09 12:42:23 -0800275 "::grpc::ServerContext* context, $Request$* request, "
276 "::grpc::ServerAsyncWriter< $Response$>* writer, "
277 "::grpc::CompletionQueue* cq, void *tag);\n");
278 } else if (BidiStreaming(method)) {
279 printer->Print(
280 *vars,
Yang Gaoca3cb3e2015-02-12 00:05:11 -0800281 "void Request$Method$("
Craig Tiller2dff17d2015-02-09 12:42:23 -0800282 "::grpc::ServerContext* context, "
Craig Tiller225f7be2015-02-09 22:32:37 -0800283 "::grpc::ServerAsyncReaderWriter< $Response$, $Request$>* stream, "
Craig Tiller5ef5db12015-02-09 12:47:21 -0800284 "::grpc::CompletionQueue* cq, void *tag);\n");
Craig Tiller2dff17d2015-02-09 12:42:23 -0800285 }
286}
287
Craig Tillerecd49342015-01-18 14:36:47 -0800288void PrintHeaderService(google::protobuf::io::Printer *printer,
289 const google::protobuf::ServiceDescriptor *service,
290 std::map<std::string, std::string> *vars) {
nnobleebebb7e2014-12-10 16:31:01 -0800291 (*vars)["Service"] = service->name();
292
293 printer->Print(*vars,
Craig Tiller2dff17d2015-02-09 12:42:23 -0800294 "class $Service$ final {\n"
nnobleebebb7e2014-12-10 16:31:01 -0800295 " public:\n");
296 printer->Indent();
297
298 // Client side
Craig Tillerb5dcec52015-01-13 11:13:42 -0800299 printer->Print(
Craig Tiller2dff17d2015-02-09 12:42:23 -0800300 "class Stub final : public ::grpc::InternalStub {\n"
Craig Tillerb5dcec52015-01-13 11:13:42 -0800301 " public:\n");
nnobleebebb7e2014-12-10 16:31:01 -0800302 printer->Indent();
303 for (int i = 0; i < service->method_count(); ++i) {
304 PrintHeaderClientMethod(printer, service->method(i), vars);
305 }
306 printer->Outdent();
307 printer->Print("};\n");
308 printer->Print(
Yang Gao1ff11f62015-01-14 11:45:32 -0800309 "static Stub* NewStub(const std::shared_ptr< ::grpc::ChannelInterface>& "
nnobleebebb7e2014-12-10 16:31:01 -0800310 "channel);\n");
311
312 printer->Print("\n");
313
Craig Tiller2dff17d2015-02-09 12:42:23 -0800314 // Server side - Synchronous
Craig Tillerb5dcec52015-01-13 11:13:42 -0800315 printer->Print(
Craig Tiller14a65f92015-02-09 13:13:14 -0800316 "class Service : public ::grpc::SynchronousService {\n"
Craig Tillerb5dcec52015-01-13 11:13:42 -0800317 " public:\n");
nnobleebebb7e2014-12-10 16:31:01 -0800318 printer->Indent();
319 printer->Print("Service() : service_(nullptr) {}\n");
320 printer->Print("virtual ~Service();\n");
321 for (int i = 0; i < service->method_count(); ++i) {
Craig Tiller2dff17d2015-02-09 12:42:23 -0800322 PrintHeaderServerMethodSync(printer, service->method(i), vars);
323 }
Craig Tiller40fcdaf2015-02-09 15:43:34 -0800324 printer->Print("::grpc::RpcService* service() override final;\n");
Craig Tiller2dff17d2015-02-09 12:42:23 -0800325 printer->Outdent();
326 printer->Print(
327 " private:\n"
328 " ::grpc::RpcService* service_;\n");
329 printer->Print("};\n");
330
331 // Server side - Asynchronous
332 printer->Print(
Craig Tiller14a65f92015-02-09 13:13:14 -0800333 "class AsyncService final : public ::grpc::AsynchronousService {\n"
Craig Tiller2dff17d2015-02-09 12:42:23 -0800334 " public:\n");
335 printer->Indent();
Craig Tiller8c8d0aa2015-02-12 11:38:36 -0800336 (*vars)["MethodCount"] = as_string(service->method_count());
337 printer->Print("explicit AsyncService(::grpc::CompletionQueue* cq);\n");
Craig Tiller0220cf12015-02-12 17:39:26 -0800338 printer->Print("~AsyncService() {};\n");
Craig Tiller2dff17d2015-02-09 12:42:23 -0800339 for (int i = 0; i < service->method_count(); ++i) {
340 PrintHeaderServerMethodAsync(printer, service->method(i), vars);
nnobleebebb7e2014-12-10 16:31:01 -0800341 }
nnobleebebb7e2014-12-10 16:31:01 -0800342 printer->Outdent();
nnobleebebb7e2014-12-10 16:31:01 -0800343 printer->Print("};\n");
344
345 printer->Outdent();
346 printer->Print("};\n");
347}
348
Craig Tillerecd49342015-01-18 14:36:47 -0800349std::string GetHeaderServices(const google::protobuf::FileDescriptor *file) {
Nicolas Noblef5c5d802015-01-15 16:36:13 -0800350 std::string output;
nnobleebebb7e2014-12-10 16:31:01 -0800351 google::protobuf::io::StringOutputStream output_stream(&output);
352 google::protobuf::io::Printer printer(&output_stream, '$');
Nicolas Noblef5c5d802015-01-15 16:36:13 -0800353 std::map<std::string, std::string> vars;
nnobleebebb7e2014-12-10 16:31:01 -0800354
355 for (int i = 0; i < file->service_count(); ++i) {
samuelwca9f3592014-12-15 14:22:04 -0800356 PrintHeaderService(&printer, file->service(i), &vars);
nnobleebebb7e2014-12-10 16:31:01 -0800357 printer.Print("\n");
358 }
359 return output;
360}
361
Craig Tillerecd49342015-01-18 14:36:47 -0800362void PrintSourceClientMethod(google::protobuf::io::Printer *printer,
363 const google::protobuf::MethodDescriptor *method,
364 std::map<std::string, std::string> *vars) {
nnobleebebb7e2014-12-10 16:31:01 -0800365 (*vars)["Method"] = method->name();
366 (*vars)["Request"] =
367 grpc_cpp_generator::ClassName(method->input_type(), true);
368 (*vars)["Response"] =
369 grpc_cpp_generator::ClassName(method->output_type(), true);
370 if (NoStreaming(method)) {
371 printer->Print(*vars,
372 "::grpc::Status $Service$::Stub::$Method$("
373 "::grpc::ClientContext* context, "
374 "const $Request$& request, $Response$* response) {\n");
375 printer->Print(*vars,
Craig Tiller1c9a2a92015-02-12 14:10:25 -0800376 " return ::grpc::BlockingUnaryCall(channel(),"
Craig Tiller8c8d0aa2015-02-12 11:38:36 -0800377 "::grpc::RpcMethod($Service$_method_names[$Idx$]), "
nnobleebebb7e2014-12-10 16:31:01 -0800378 "context, request, response);\n"
379 "}\n\n");
Yang Gao068c85b2015-02-12 15:21:24 -0800380 printer->Print(*vars,
381 "void $Service$::Stub::$Method$("
382 "::grpc::ClientContext* context, "
383 "const $Request$& request, $Response$* response, ::grpc::Status* status, "
384 "::grpc::CompletionQueue* cq, void* tag) {\n");
385 printer->Print(*vars,
386 " ::grpc::AsyncUnaryCall(channel(),"
387 "::grpc::RpcMethod($Service$_method_names[$Idx$]), "
388 "context, request, response, status, cq, tag);\n"
389 "}\n\n");
nnobleebebb7e2014-12-10 16:31:01 -0800390 } else if (ClientOnlyStreaming(method)) {
Yang Gao5680ff42015-01-14 12:14:21 -0800391 printer->Print(
392 *vars,
393 "::grpc::ClientWriter< $Request$>* $Service$::Stub::$Method$("
394 "::grpc::ClientContext* context, $Response$* response) {\n");
yangg5bcea0d2015-01-06 10:35:03 -0800395 printer->Print(*vars,
Yang Gao1ff11f62015-01-14 11:45:32 -0800396 " return new ::grpc::ClientWriter< $Request$>("
Craig Tillerc4965752015-02-09 09:51:00 -0800397 "channel(),"
Craig Tiller8c8d0aa2015-02-12 11:38:36 -0800398 "::grpc::RpcMethod($Service$_method_names[$Idx$], "
yangg5bcea0d2015-01-06 10:35:03 -0800399 "::grpc::RpcMethod::RpcType::CLIENT_STREAMING), "
Craig Tillerc4965752015-02-09 09:51:00 -0800400 "context, response);\n"
yangg5bcea0d2015-01-06 10:35:03 -0800401 "}\n\n");
Yang Gao068c85b2015-02-12 15:21:24 -0800402 printer->Print(
403 *vars,
404 "::grpc::ClientAsyncWriter< $Request$>* $Service$::Stub::$Method$("
405 "::grpc::ClientContext* context, $Response$* response, "
406 "::grpc::CompletionQueue* cq, void* tag) {\n");
407 printer->Print(*vars,
408 " return new ::grpc::ClientAsyncWriter< $Request$>("
409 "channel(), cq, "
410 "::grpc::RpcMethod($Service$_method_names[$Idx$], "
411 "::grpc::RpcMethod::RpcType::CLIENT_STREAMING), "
412 "context, response, tag);\n"
413 "}\n\n");
nnobleebebb7e2014-12-10 16:31:01 -0800414 } else if (ServerOnlyStreaming(method)) {
415 printer->Print(
416 *vars,
Yang Gao1ff11f62015-01-14 11:45:32 -0800417 "::grpc::ClientReader< $Response$>* $Service$::Stub::$Method$("
nnobleebebb7e2014-12-10 16:31:01 -0800418 "::grpc::ClientContext* context, const $Request$* request) {\n");
yangg5bcea0d2015-01-06 10:35:03 -0800419 printer->Print(*vars,
Yang Gao1ff11f62015-01-14 11:45:32 -0800420 " return new ::grpc::ClientReader< $Response$>("
Craig Tillerc4965752015-02-09 09:51:00 -0800421 "channel(),"
Craig Tiller8c8d0aa2015-02-12 11:38:36 -0800422 "::grpc::RpcMethod($Service$_method_names[$Idx$], "
yangg5bcea0d2015-01-06 10:35:03 -0800423 "::grpc::RpcMethod::RpcType::SERVER_STREAMING), "
Craig Tillerc4965752015-02-09 09:51:00 -0800424 "context, *request);\n"
yangg5bcea0d2015-01-06 10:35:03 -0800425 "}\n\n");
Yang Gao068c85b2015-02-12 15:21:24 -0800426 printer->Print(
427 *vars,
428 "::grpc::ClientAsyncReader< $Response$>* $Service$::Stub::$Method$("
429 "::grpc::ClientContext* context, const $Request$* request, "
430 "::grpc::CompletionQueue* cq, void* tag) {\n");
431 printer->Print(*vars,
432 " return new ::grpc::ClientAsyncReader< $Response$>("
433 "channel(), cq, "
434 "::grpc::RpcMethod($Service$_method_names[$Idx$], "
435 "::grpc::RpcMethod::RpcType::SERVER_STREAMING), "
436 "context, *request, tag);\n"
437 "}\n\n");
nnobleebebb7e2014-12-10 16:31:01 -0800438 } else if (BidiStreaming(method)) {
439 printer->Print(
440 *vars,
Yang Gao1ff11f62015-01-14 11:45:32 -0800441 "::grpc::ClientReaderWriter< $Request$, $Response$>* "
nnobleebebb7e2014-12-10 16:31:01 -0800442 "$Service$::Stub::$Method$(::grpc::ClientContext* context) {\n");
443 printer->Print(
444 *vars,
Yang Gao1ff11f62015-01-14 11:45:32 -0800445 " return new ::grpc::ClientReaderWriter< $Request$, $Response$>("
Craig Tillerc4965752015-02-09 09:51:00 -0800446 "channel(),"
Craig Tiller8c8d0aa2015-02-12 11:38:36 -0800447 "::grpc::RpcMethod($Service$_method_names[$Idx$], "
nnobleebebb7e2014-12-10 16:31:01 -0800448 "::grpc::RpcMethod::RpcType::BIDI_STREAMING), "
Craig Tillerc4965752015-02-09 09:51:00 -0800449 "context);\n"
nnobleebebb7e2014-12-10 16:31:01 -0800450 "}\n\n");
Yang Gao068c85b2015-02-12 15:21:24 -0800451 printer->Print(
452 *vars,
453 "::grpc::ClientAsyncReaderWriter< $Request$, $Response$>* "
454 "$Service$::Stub::$Method$(::grpc::ClientContext* context, "
455 "::grpc::CompletionQueue* cq, void* tag) {\n");
456 printer->Print(
457 *vars,
458 " return new ::grpc::ClientAsyncReaderWriter< $Request$, $Response$>("
459 "channel(), cq, "
460 "::grpc::RpcMethod($Service$_method_names[$Idx$], "
461 "::grpc::RpcMethod::RpcType::BIDI_STREAMING), "
462 "context, tag);\n"
463 "}\n\n");
nnobleebebb7e2014-12-10 16:31:01 -0800464 }
465}
466
Craig Tillerecd49342015-01-18 14:36:47 -0800467void PrintSourceServerMethod(google::protobuf::io::Printer *printer,
468 const google::protobuf::MethodDescriptor *method,
469 std::map<std::string, std::string> *vars) {
nnobleebebb7e2014-12-10 16:31:01 -0800470 (*vars)["Method"] = method->name();
471 (*vars)["Request"] =
472 grpc_cpp_generator::ClassName(method->input_type(), true);
473 (*vars)["Response"] =
474 grpc_cpp_generator::ClassName(method->output_type(), true);
475 if (NoStreaming(method)) {
476 printer->Print(*vars,
477 "::grpc::Status $Service$::Service::$Method$("
yangga4b6f5d2014-12-17 15:53:12 -0800478 "::grpc::ServerContext* context, "
nnobleebebb7e2014-12-10 16:31:01 -0800479 "const $Request$* request, $Response$* response) {\n");
480 printer->Print(
481 " return ::grpc::Status("
482 "::grpc::StatusCode::UNIMPLEMENTED);\n");
483 printer->Print("}\n\n");
484 } else if (ClientOnlyStreaming(method)) {
485 printer->Print(*vars,
486 "::grpc::Status $Service$::Service::$Method$("
yangga4b6f5d2014-12-17 15:53:12 -0800487 "::grpc::ServerContext* context, "
Yang Gao1ff11f62015-01-14 11:45:32 -0800488 "::grpc::ServerReader< $Request$>* reader, "
nnobleebebb7e2014-12-10 16:31:01 -0800489 "$Response$* response) {\n");
490 printer->Print(
491 " return ::grpc::Status("
492 "::grpc::StatusCode::UNIMPLEMENTED);\n");
493 printer->Print("}\n\n");
494 } else if (ServerOnlyStreaming(method)) {
495 printer->Print(*vars,
496 "::grpc::Status $Service$::Service::$Method$("
yangga4b6f5d2014-12-17 15:53:12 -0800497 "::grpc::ServerContext* context, "
nnobleebebb7e2014-12-10 16:31:01 -0800498 "const $Request$* request, "
Yang Gao1ff11f62015-01-14 11:45:32 -0800499 "::grpc::ServerWriter< $Response$>* writer) {\n");
nnobleebebb7e2014-12-10 16:31:01 -0800500 printer->Print(
501 " return ::grpc::Status("
502 "::grpc::StatusCode::UNIMPLEMENTED);\n");
503 printer->Print("}\n\n");
504 } else if (BidiStreaming(method)) {
505 printer->Print(*vars,
506 "::grpc::Status $Service$::Service::$Method$("
yangga4b6f5d2014-12-17 15:53:12 -0800507 "::grpc::ServerContext* context, "
Yang Gao1ff11f62015-01-14 11:45:32 -0800508 "::grpc::ServerReaderWriter< $Response$, $Request$>* "
nnobleebebb7e2014-12-10 16:31:01 -0800509 "stream) {\n");
510 printer->Print(
511 " return ::grpc::Status("
512 "::grpc::StatusCode::UNIMPLEMENTED);\n");
513 printer->Print("}\n\n");
514 }
515}
516
Craig Tiller8c8d0aa2015-02-12 11:38:36 -0800517void PrintSourceServerAsyncMethod(
518 google::protobuf::io::Printer *printer,
519 const google::protobuf::MethodDescriptor *method,
520 std::map<std::string, std::string> *vars) {
Craig Tiller225f7be2015-02-09 22:32:37 -0800521 (*vars)["Method"] = method->name();
522 (*vars)["Request"] =
523 grpc_cpp_generator::ClassName(method->input_type(), true);
524 (*vars)["Response"] =
525 grpc_cpp_generator::ClassName(method->output_type(), true);
526 if (NoStreaming(method)) {
527 printer->Print(*vars,
Yang Gaoca3cb3e2015-02-12 00:05:11 -0800528 "void $Service$::AsyncService::Request$Method$("
Craig Tiller225f7be2015-02-09 22:32:37 -0800529 "::grpc::ServerContext* context, "
530 "$Request$* request, "
531 "::grpc::ServerAsyncResponseWriter< $Response$>* response, "
532 "::grpc::CompletionQueue* cq, void* tag) {\n");
Craig Tiller1c9a2a92015-02-12 14:10:25 -0800533 printer->Print(
534 *vars,
535 " AsynchronousService::RequestAsyncUnary($Idx$, context, request, response, cq, tag);\n");
Craig Tiller225f7be2015-02-09 22:32:37 -0800536 printer->Print("}\n\n");
537 } else if (ClientOnlyStreaming(method)) {
538 printer->Print(*vars,
Yang Gaoca3cb3e2015-02-12 00:05:11 -0800539 "void $Service$::AsyncService::Request$Method$("
Craig Tiller225f7be2015-02-09 22:32:37 -0800540 "::grpc::ServerContext* context, "
Yang Gao005f18a2015-02-13 10:22:33 -0800541 "::grpc::ServerAsyncReader< $Response$, $Request$>* reader, "
Craig Tiller225f7be2015-02-09 22:32:37 -0800542 "::grpc::CompletionQueue* cq, void* tag) {\n");
Craig Tiller1c9a2a92015-02-12 14:10:25 -0800543 printer->Print(
544 *vars,
545 " AsynchronousService::RequestClientStreaming($Idx$, context, reader, cq, tag);\n");
Craig Tiller225f7be2015-02-09 22:32:37 -0800546 printer->Print("}\n\n");
547 } else if (ServerOnlyStreaming(method)) {
548 printer->Print(*vars,
Yang Gaoca3cb3e2015-02-12 00:05:11 -0800549 "void $Service$::AsyncService::Request$Method$("
Craig Tiller225f7be2015-02-09 22:32:37 -0800550 "::grpc::ServerContext* context, "
551 "$Request$* request, "
552 "::grpc::ServerAsyncWriter< $Response$>* writer, "
553 "::grpc::CompletionQueue* cq, void* tag) {\n");
Craig Tiller1c9a2a92015-02-12 14:10:25 -0800554 printer->Print(
555 *vars,
556 " AsynchronousService::RequestServerStreaming($Idx$, context, request, writer, cq, tag);\n");
Craig Tiller225f7be2015-02-09 22:32:37 -0800557 printer->Print("}\n\n");
558 } else if (BidiStreaming(method)) {
Craig Tiller8c8d0aa2015-02-12 11:38:36 -0800559 printer->Print(
560 *vars,
561 "void $Service$::AsyncService::Request$Method$("
562 "::grpc::ServerContext* context, "
563 "::grpc::ServerAsyncReaderWriter< $Response$, $Request$>* stream, "
564 "::grpc::CompletionQueue* cq, void *tag) {\n");
Craig Tiller1c9a2a92015-02-12 14:10:25 -0800565 printer->Print(
566 *vars,
567 " AsynchronousService::RequestBidiStreaming($Idx$, context, stream, cq, tag);\n");
Craig Tiller225f7be2015-02-09 22:32:37 -0800568 printer->Print("}\n\n");
569 }
570}
571
Craig Tillerecd49342015-01-18 14:36:47 -0800572void PrintSourceService(google::protobuf::io::Printer *printer,
573 const google::protobuf::ServiceDescriptor *service,
574 std::map<std::string, std::string> *vars) {
nnobleebebb7e2014-12-10 16:31:01 -0800575 (*vars)["Service"] = service->name();
Craig Tiller8c8d0aa2015-02-12 11:38:36 -0800576
577 printer->Print(*vars, "static const char* $Service$_method_names[] = {\n");
578 for (int i = 0; i < service->method_count(); ++i) {
579 (*vars)["Method"] = service->method(i)->name();
580 printer->Print(*vars, " \"/$Package$$Service$/$Method$\",\n");
581 }
582 printer->Print(*vars, "};\n\n");
583
Yang Gao5680ff42015-01-14 12:14:21 -0800584 printer->Print(
585 *vars,
586 "$Service$::Stub* $Service$::NewStub("
587 "const std::shared_ptr< ::grpc::ChannelInterface>& channel) {\n"
588 " $Service$::Stub* stub = new $Service$::Stub();\n"
589 " stub->set_channel(channel);\n"
590 " return stub;\n"
591 "};\n\n");
nnobleebebb7e2014-12-10 16:31:01 -0800592 for (int i = 0; i < service->method_count(); ++i) {
Craig Tiller8c8d0aa2015-02-12 11:38:36 -0800593 (*vars)["Idx"] = as_string(i);
nnobleebebb7e2014-12-10 16:31:01 -0800594 PrintSourceClientMethod(printer, service->method(i), vars);
595 }
596
Craig Tiller8c8d0aa2015-02-12 11:38:36 -0800597 (*vars)["MethodCount"] = as_string(service->method_count());
598 printer->Print(
599 *vars,
600 "$Service$::AsyncService::AsyncService(::grpc::CompletionQueue* cq) : "
601 "::grpc::AsynchronousService(cq, $Service$_method_names, $MethodCount$) "
602 "{}\n\n");
603
nnobleebebb7e2014-12-10 16:31:01 -0800604 printer->Print(*vars,
605 "$Service$::Service::~Service() {\n"
606 " delete service_;\n"
607 "}\n\n");
608 for (int i = 0; i < service->method_count(); ++i) {
Craig Tiller1c9a2a92015-02-12 14:10:25 -0800609 (*vars)["Idx"] = as_string(i);
nnobleebebb7e2014-12-10 16:31:01 -0800610 PrintSourceServerMethod(printer, service->method(i), vars);
Craig Tiller225f7be2015-02-09 22:32:37 -0800611 PrintSourceServerAsyncMethod(printer, service->method(i), vars);
nnobleebebb7e2014-12-10 16:31:01 -0800612 }
613 printer->Print(*vars,
Craig Tillerb5dcec52015-01-13 11:13:42 -0800614 "::grpc::RpcService* $Service$::Service::service() {\n");
nnobleebebb7e2014-12-10 16:31:01 -0800615 printer->Indent();
Craig Tillerb5dcec52015-01-13 11:13:42 -0800616 printer->Print(
617 "if (service_ != nullptr) {\n"
618 " return service_;\n"
619 "}\n");
nnobleebebb7e2014-12-10 16:31:01 -0800620 printer->Print("service_ = new ::grpc::RpcService();\n");
621 for (int i = 0; i < service->method_count(); ++i) {
Craig Tillerecd49342015-01-18 14:36:47 -0800622 const google::protobuf::MethodDescriptor *method = service->method(i);
Craig Tiller8c8d0aa2015-02-12 11:38:36 -0800623 (*vars)["Idx"] = as_string(i);
nnobleebebb7e2014-12-10 16:31:01 -0800624 (*vars)["Method"] = method->name();
625 (*vars)["Request"] =
626 grpc_cpp_generator::ClassName(method->input_type(), true);
627 (*vars)["Response"] =
628 grpc_cpp_generator::ClassName(method->output_type(), true);
629 if (NoStreaming(method)) {
630 printer->Print(
631 *vars,
632 "service_->AddMethod(new ::grpc::RpcServiceMethod(\n"
Craig Tiller8c8d0aa2015-02-12 11:38:36 -0800633 " $Service$_method_names[$Idx$],\n"
yangg5bcea0d2015-01-06 10:35:03 -0800634 " ::grpc::RpcMethod::NORMAL_RPC,\n"
Yang Gao1ff11f62015-01-14 11:45:32 -0800635 " new ::grpc::RpcMethodHandler< $Service$::Service, $Request$, "
nnobleebebb7e2014-12-10 16:31:01 -0800636 "$Response$>(\n"
Yang Gao1ff11f62015-01-14 11:45:32 -0800637 " std::function< ::grpc::Status($Service$::Service*, "
yangga4b6f5d2014-12-17 15:53:12 -0800638 "::grpc::ServerContext*, const $Request$*, $Response$*)>("
nnobleebebb7e2014-12-10 16:31:01 -0800639 "&$Service$::Service::$Method$), this),\n"
640 " new $Request$, new $Response$));\n");
641 } else if (ClientOnlyStreaming(method)) {
642 printer->Print(
643 *vars,
644 "service_->AddMethod(new ::grpc::RpcServiceMethod(\n"
Craig Tiller8c8d0aa2015-02-12 11:38:36 -0800645 " $Service$_method_names[$Idx$],\n"
yangg5bcea0d2015-01-06 10:35:03 -0800646 " ::grpc::RpcMethod::CLIENT_STREAMING,\n"
Yang Gao1ff11f62015-01-14 11:45:32 -0800647 " new ::grpc::ClientStreamingHandler< "
nnobleebebb7e2014-12-10 16:31:01 -0800648 "$Service$::Service, $Request$, $Response$>(\n"
Yang Gao1ff11f62015-01-14 11:45:32 -0800649 " std::function< ::grpc::Status($Service$::Service*, "
yangga4b6f5d2014-12-17 15:53:12 -0800650 "::grpc::ServerContext*, "
Yang Gao1ff11f62015-01-14 11:45:32 -0800651 "::grpc::ServerReader< $Request$>*, $Response$*)>("
nnobleebebb7e2014-12-10 16:31:01 -0800652 "&$Service$::Service::$Method$), this),\n"
653 " new $Request$, new $Response$));\n");
654 } else if (ServerOnlyStreaming(method)) {
655 printer->Print(
656 *vars,
657 "service_->AddMethod(new ::grpc::RpcServiceMethod(\n"
Craig Tiller8c8d0aa2015-02-12 11:38:36 -0800658 " $Service$_method_names[$Idx$],\n"
yangg5bcea0d2015-01-06 10:35:03 -0800659 " ::grpc::RpcMethod::SERVER_STREAMING,\n"
Yang Gao1ff11f62015-01-14 11:45:32 -0800660 " new ::grpc::ServerStreamingHandler< "
nnobleebebb7e2014-12-10 16:31:01 -0800661 "$Service$::Service, $Request$, $Response$>(\n"
Yang Gao1ff11f62015-01-14 11:45:32 -0800662 " std::function< ::grpc::Status($Service$::Service*, "
yangga4b6f5d2014-12-17 15:53:12 -0800663 "::grpc::ServerContext*, "
Yang Gao1ff11f62015-01-14 11:45:32 -0800664 "const $Request$*, ::grpc::ServerWriter< $Response$>*)>("
nnobleebebb7e2014-12-10 16:31:01 -0800665 "&$Service$::Service::$Method$), this),\n"
666 " new $Request$, new $Response$));\n");
667 } else if (BidiStreaming(method)) {
668 printer->Print(
669 *vars,
670 "service_->AddMethod(new ::grpc::RpcServiceMethod(\n"
Craig Tiller8c8d0aa2015-02-12 11:38:36 -0800671 " $Service$_method_names[$Idx$],\n"
yangg5bcea0d2015-01-06 10:35:03 -0800672 " ::grpc::RpcMethod::BIDI_STREAMING,\n"
Yang Gao1ff11f62015-01-14 11:45:32 -0800673 " new ::grpc::BidiStreamingHandler< "
nnobleebebb7e2014-12-10 16:31:01 -0800674 "$Service$::Service, $Request$, $Response$>(\n"
Yang Gao1ff11f62015-01-14 11:45:32 -0800675 " std::function< ::grpc::Status($Service$::Service*, "
yangga4b6f5d2014-12-17 15:53:12 -0800676 "::grpc::ServerContext*, "
Yang Gao1ff11f62015-01-14 11:45:32 -0800677 "::grpc::ServerReaderWriter< $Response$, $Request$>*)>("
nnobleebebb7e2014-12-10 16:31:01 -0800678 "&$Service$::Service::$Method$), this),\n"
679 " new $Request$, new $Response$));\n");
680 }
681 }
682 printer->Print("return service_;\n");
683 printer->Outdent();
684 printer->Print("}\n\n");
685}
686
Craig Tillerecd49342015-01-18 14:36:47 -0800687std::string GetSourceServices(const google::protobuf::FileDescriptor *file) {
Nicolas Noblef5c5d802015-01-15 16:36:13 -0800688 std::string output;
nnobleebebb7e2014-12-10 16:31:01 -0800689 google::protobuf::io::StringOutputStream output_stream(&output);
690 google::protobuf::io::Printer printer(&output_stream, '$');
Nicolas Noblef5c5d802015-01-15 16:36:13 -0800691 std::map<std::string, std::string> vars;
yangg5bcea0d2015-01-06 10:35:03 -0800692 // Package string is empty or ends with a dot. It is used to fully qualify
693 // method names.
694 vars["Package"] = file->package();
695 if (!file->package().empty()) {
696 vars["Package"].append(".");
697 }
nnobleebebb7e2014-12-10 16:31:01 -0800698
699 for (int i = 0; i < file->service_count(); ++i) {
samuelwca9f3592014-12-15 14:22:04 -0800700 PrintSourceService(&printer, file->service(i), &vars);
nnobleebebb7e2014-12-10 16:31:01 -0800701 printer.Print("\n");
702 }
703 return output;
704}
705
706} // namespace grpc_cpp_generator