blob: 6ef2128afd23860396e7054e5eeec10ee8c1c826 [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");
136 temp.append("template <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, "
Craig Tiller14a65f92015-02-09 13:13:14 -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, "
Craig Tiller14a65f92015-02-09 13:13:14 -0800195 "::grpc::Status *status, "
196 "::grpc::CompletionQueue *cq, void *tag);\n");
nnobleebebb7e2014-12-10 16:31:01 -0800197 } else if (ServerOnlyStreaming(method)) {
198 printer->Print(
199 *vars,
Yang Gao1ff11f62015-01-14 11:45:32 -0800200 "::grpc::ClientReader< $Response$>* $Method$("
Craig Tiller5ef5db12015-02-09 12:47:21 -0800201 "::grpc::ClientContext* context, const $Request$* request);\n");
202 printer->Print(*vars,
Yang Gaoe0b73fd2015-02-12 14:05:47 -0800203 "::grpc::ClientAsyncReader< $Response$>* $Method$("
Craig Tiller5ef5db12015-02-09 12:47:21 -0800204 "::grpc::ClientContext* context, const $Request$* request, "
Craig Tiller14a65f92015-02-09 13:13:14 -0800205 "::grpc::CompletionQueue *cq, void *tag);\n");
nnobleebebb7e2014-12-10 16:31:01 -0800206 } else if (BidiStreaming(method)) {
207 printer->Print(*vars,
Yang Gao1ff11f62015-01-14 11:45:32 -0800208 "::grpc::ClientReaderWriter< $Request$, $Response$>* "
Craig Tiller5ef5db12015-02-09 12:47:21 -0800209 "$Method$(::grpc::ClientContext* context);\n");
210 printer->Print(*vars,
Craig Tiller225f7be2015-02-09 22:32:37 -0800211 "::grpc::ClientAsyncReaderWriter< $Request$, $Response$>* "
Craig Tiller5ef5db12015-02-09 12:47:21 -0800212 "$Method$(::grpc::ClientContext* context, "
Craig Tiller14a65f92015-02-09 13:13:14 -0800213 "::grpc::CompletionQueue *cq, void *tag);\n");
nnobleebebb7e2014-12-10 16:31:01 -0800214 }
215}
216
Craig Tiller5ef5db12015-02-09 12:47:21 -0800217void PrintHeaderServerMethodSync(
218 google::protobuf::io::Printer *printer,
219 const google::protobuf::MethodDescriptor *method,
220 std::map<std::string, std::string> *vars) {
nnobleebebb7e2014-12-10 16:31:01 -0800221 (*vars)["Method"] = method->name();
222 (*vars)["Request"] =
223 grpc_cpp_generator::ClassName(method->input_type(), true);
224 (*vars)["Response"] =
225 grpc_cpp_generator::ClassName(method->output_type(), true);
226 if (NoStreaming(method)) {
227 printer->Print(*vars,
yangga4b6f5d2014-12-17 15:53:12 -0800228 "virtual ::grpc::Status $Method$("
229 "::grpc::ServerContext* context, const $Request$* request, "
nnobleebebb7e2014-12-10 16:31:01 -0800230 "$Response$* response);\n");
231 } else if (ClientOnlyStreaming(method)) {
232 printer->Print(*vars,
233 "virtual ::grpc::Status $Method$("
yangga4b6f5d2014-12-17 15:53:12 -0800234 "::grpc::ServerContext* context, "
Yang Gao1ff11f62015-01-14 11:45:32 -0800235 "::grpc::ServerReader< $Request$>* reader, "
nnobleebebb7e2014-12-10 16:31:01 -0800236 "$Response$* response);\n");
237 } else if (ServerOnlyStreaming(method)) {
238 printer->Print(*vars,
yangga4b6f5d2014-12-17 15:53:12 -0800239 "virtual ::grpc::Status $Method$("
240 "::grpc::ServerContext* context, const $Request$* request, "
Yang Gao1ff11f62015-01-14 11:45:32 -0800241 "::grpc::ServerWriter< $Response$>* writer);\n");
nnobleebebb7e2014-12-10 16:31:01 -0800242 } else if (BidiStreaming(method)) {
Yang Gao5680ff42015-01-14 12:14:21 -0800243 printer->Print(
244 *vars,
245 "virtual ::grpc::Status $Method$("
246 "::grpc::ServerContext* context, "
247 "::grpc::ServerReaderWriter< $Response$, $Request$>* stream);"
248 "\n");
nnobleebebb7e2014-12-10 16:31:01 -0800249 }
250}
251
Craig Tiller5ef5db12015-02-09 12:47:21 -0800252void PrintHeaderServerMethodAsync(
253 google::protobuf::io::Printer *printer,
254 const google::protobuf::MethodDescriptor *method,
255 std::map<std::string, std::string> *vars) {
Craig Tiller2dff17d2015-02-09 12:42:23 -0800256 (*vars)["Method"] = method->name();
257 (*vars)["Request"] =
258 grpc_cpp_generator::ClassName(method->input_type(), true);
259 (*vars)["Response"] =
260 grpc_cpp_generator::ClassName(method->output_type(), true);
261 if (NoStreaming(method)) {
262 printer->Print(*vars,
Yang Gaoca3cb3e2015-02-12 00:05:11 -0800263 "void Request$Method$("
Craig Tiller2dff17d2015-02-09 12:42:23 -0800264 "::grpc::ServerContext* context, $Request$* request, "
265 "::grpc::ServerAsyncResponseWriter< $Response$>* response, "
266 "::grpc::CompletionQueue* cq, void *tag);\n");
267 } else if (ClientOnlyStreaming(method)) {
268 printer->Print(*vars,
Yang Gaoca3cb3e2015-02-12 00:05:11 -0800269 "void Request$Method$("
Craig Tiller2dff17d2015-02-09 12:42:23 -0800270 "::grpc::ServerContext* context, "
271 "::grpc::ServerAsyncReader< $Request$>* reader, "
Craig Tiller2dff17d2015-02-09 12:42:23 -0800272 "::grpc::CompletionQueue* cq, void *tag);\n");
273 } else if (ServerOnlyStreaming(method)) {
274 printer->Print(*vars,
Yang Gaoca3cb3e2015-02-12 00:05:11 -0800275 "void Request$Method$("
Craig Tiller2dff17d2015-02-09 12:42:23 -0800276 "::grpc::ServerContext* context, $Request$* request, "
277 "::grpc::ServerAsyncWriter< $Response$>* writer, "
278 "::grpc::CompletionQueue* cq, void *tag);\n");
279 } else if (BidiStreaming(method)) {
280 printer->Print(
281 *vars,
Yang Gaoca3cb3e2015-02-12 00:05:11 -0800282 "void Request$Method$("
Craig Tiller2dff17d2015-02-09 12:42:23 -0800283 "::grpc::ServerContext* context, "
Craig Tiller225f7be2015-02-09 22:32:37 -0800284 "::grpc::ServerAsyncReaderWriter< $Response$, $Request$>* stream, "
Craig Tiller5ef5db12015-02-09 12:47:21 -0800285 "::grpc::CompletionQueue* cq, void *tag);\n");
Craig Tiller2dff17d2015-02-09 12:42:23 -0800286 }
287}
288
Craig Tillerecd49342015-01-18 14:36:47 -0800289void PrintHeaderService(google::protobuf::io::Printer *printer,
290 const google::protobuf::ServiceDescriptor *service,
291 std::map<std::string, std::string> *vars) {
nnobleebebb7e2014-12-10 16:31:01 -0800292 (*vars)["Service"] = service->name();
293
294 printer->Print(*vars,
Craig Tiller2dff17d2015-02-09 12:42:23 -0800295 "class $Service$ final {\n"
nnobleebebb7e2014-12-10 16:31:01 -0800296 " public:\n");
297 printer->Indent();
298
299 // Client side
Craig Tillerb5dcec52015-01-13 11:13:42 -0800300 printer->Print(
Craig Tiller2dff17d2015-02-09 12:42:23 -0800301 "class Stub final : public ::grpc::InternalStub {\n"
Craig Tillerb5dcec52015-01-13 11:13:42 -0800302 " public:\n");
nnobleebebb7e2014-12-10 16:31:01 -0800303 printer->Indent();
304 for (int i = 0; i < service->method_count(); ++i) {
305 PrintHeaderClientMethod(printer, service->method(i), vars);
306 }
307 printer->Outdent();
308 printer->Print("};\n");
309 printer->Print(
Yang Gao1ff11f62015-01-14 11:45:32 -0800310 "static Stub* NewStub(const std::shared_ptr< ::grpc::ChannelInterface>& "
nnobleebebb7e2014-12-10 16:31:01 -0800311 "channel);\n");
312
313 printer->Print("\n");
314
Craig Tiller2dff17d2015-02-09 12:42:23 -0800315 // Server side - Synchronous
Craig Tillerb5dcec52015-01-13 11:13:42 -0800316 printer->Print(
Craig Tiller14a65f92015-02-09 13:13:14 -0800317 "class Service : public ::grpc::SynchronousService {\n"
Craig Tillerb5dcec52015-01-13 11:13:42 -0800318 " public:\n");
nnobleebebb7e2014-12-10 16:31:01 -0800319 printer->Indent();
320 printer->Print("Service() : service_(nullptr) {}\n");
321 printer->Print("virtual ~Service();\n");
322 for (int i = 0; i < service->method_count(); ++i) {
Craig Tiller2dff17d2015-02-09 12:42:23 -0800323 PrintHeaderServerMethodSync(printer, service->method(i), vars);
324 }
Craig Tiller40fcdaf2015-02-09 15:43:34 -0800325 printer->Print("::grpc::RpcService* service() override final;\n");
Craig Tiller2dff17d2015-02-09 12:42:23 -0800326 printer->Outdent();
327 printer->Print(
328 " private:\n"
329 " ::grpc::RpcService* service_;\n");
330 printer->Print("};\n");
331
332 // Server side - Asynchronous
333 printer->Print(
Craig Tiller14a65f92015-02-09 13:13:14 -0800334 "class AsyncService final : public ::grpc::AsynchronousService {\n"
Craig Tiller2dff17d2015-02-09 12:42:23 -0800335 " public:\n");
336 printer->Indent();
Craig Tiller8c8d0aa2015-02-12 11:38:36 -0800337 (*vars)["MethodCount"] = as_string(service->method_count());
338 printer->Print("explicit AsyncService(::grpc::CompletionQueue* cq);\n");
Craig Tiller2dff17d2015-02-09 12:42:23 -0800339 printer->Print("~AsyncService();\n");
340 for (int i = 0; i < service->method_count(); ++i) {
341 PrintHeaderServerMethodAsync(printer, service->method(i), vars);
nnobleebebb7e2014-12-10 16:31:01 -0800342 }
nnobleebebb7e2014-12-10 16:31:01 -0800343 printer->Outdent();
nnobleebebb7e2014-12-10 16:31:01 -0800344 printer->Print("};\n");
345
346 printer->Outdent();
347 printer->Print("};\n");
348}
349
Craig Tillerecd49342015-01-18 14:36:47 -0800350std::string GetHeaderServices(const google::protobuf::FileDescriptor *file) {
Nicolas Noblef5c5d802015-01-15 16:36:13 -0800351 std::string output;
nnobleebebb7e2014-12-10 16:31:01 -0800352 google::protobuf::io::StringOutputStream output_stream(&output);
353 google::protobuf::io::Printer printer(&output_stream, '$');
Nicolas Noblef5c5d802015-01-15 16:36:13 -0800354 std::map<std::string, std::string> vars;
nnobleebebb7e2014-12-10 16:31:01 -0800355
356 for (int i = 0; i < file->service_count(); ++i) {
samuelwca9f3592014-12-15 14:22:04 -0800357 PrintHeaderService(&printer, file->service(i), &vars);
nnobleebebb7e2014-12-10 16:31:01 -0800358 printer.Print("\n");
359 }
360 return output;
361}
362
Craig Tillerecd49342015-01-18 14:36:47 -0800363void PrintSourceClientMethod(google::protobuf::io::Printer *printer,
364 const google::protobuf::MethodDescriptor *method,
365 std::map<std::string, std::string> *vars) {
nnobleebebb7e2014-12-10 16:31:01 -0800366 (*vars)["Method"] = method->name();
367 (*vars)["Request"] =
368 grpc_cpp_generator::ClassName(method->input_type(), true);
369 (*vars)["Response"] =
370 grpc_cpp_generator::ClassName(method->output_type(), true);
371 if (NoStreaming(method)) {
372 printer->Print(*vars,
373 "::grpc::Status $Service$::Stub::$Method$("
374 "::grpc::ClientContext* context, "
375 "const $Request$& request, $Response$* response) {\n");
376 printer->Print(*vars,
Craig Tillerc4965752015-02-09 09:51:00 -0800377 "return ::grpc::BlockingUnaryCall(channel(),"
Craig Tiller8c8d0aa2015-02-12 11:38:36 -0800378 "::grpc::RpcMethod($Service$_method_names[$Idx$]), "
nnobleebebb7e2014-12-10 16:31:01 -0800379 "context, request, response);\n"
380 "}\n\n");
381 } else if (ClientOnlyStreaming(method)) {
Yang Gao5680ff42015-01-14 12:14:21 -0800382 printer->Print(
383 *vars,
384 "::grpc::ClientWriter< $Request$>* $Service$::Stub::$Method$("
385 "::grpc::ClientContext* context, $Response$* response) {\n");
yangg5bcea0d2015-01-06 10:35:03 -0800386 printer->Print(*vars,
Yang Gao1ff11f62015-01-14 11:45:32 -0800387 " return new ::grpc::ClientWriter< $Request$>("
Craig Tillerc4965752015-02-09 09:51:00 -0800388 "channel(),"
Craig Tiller8c8d0aa2015-02-12 11:38:36 -0800389 "::grpc::RpcMethod($Service$_method_names[$Idx$], "
yangg5bcea0d2015-01-06 10:35:03 -0800390 "::grpc::RpcMethod::RpcType::CLIENT_STREAMING), "
Craig Tillerc4965752015-02-09 09:51:00 -0800391 "context, response);\n"
yangg5bcea0d2015-01-06 10:35:03 -0800392 "}\n\n");
nnobleebebb7e2014-12-10 16:31:01 -0800393 } else if (ServerOnlyStreaming(method)) {
394 printer->Print(
395 *vars,
Yang Gao1ff11f62015-01-14 11:45:32 -0800396 "::grpc::ClientReader< $Response$>* $Service$::Stub::$Method$("
nnobleebebb7e2014-12-10 16:31:01 -0800397 "::grpc::ClientContext* context, const $Request$* request) {\n");
yangg5bcea0d2015-01-06 10:35:03 -0800398 printer->Print(*vars,
Yang Gao1ff11f62015-01-14 11:45:32 -0800399 " return new ::grpc::ClientReader< $Response$>("
Craig Tillerc4965752015-02-09 09:51:00 -0800400 "channel(),"
Craig Tiller8c8d0aa2015-02-12 11:38:36 -0800401 "::grpc::RpcMethod($Service$_method_names[$Idx$], "
yangg5bcea0d2015-01-06 10:35:03 -0800402 "::grpc::RpcMethod::RpcType::SERVER_STREAMING), "
Craig Tillerc4965752015-02-09 09:51:00 -0800403 "context, *request);\n"
yangg5bcea0d2015-01-06 10:35:03 -0800404 "}\n\n");
nnobleebebb7e2014-12-10 16:31:01 -0800405 } else if (BidiStreaming(method)) {
406 printer->Print(
407 *vars,
Yang Gao1ff11f62015-01-14 11:45:32 -0800408 "::grpc::ClientReaderWriter< $Request$, $Response$>* "
nnobleebebb7e2014-12-10 16:31:01 -0800409 "$Service$::Stub::$Method$(::grpc::ClientContext* context) {\n");
410 printer->Print(
411 *vars,
Yang Gao1ff11f62015-01-14 11:45:32 -0800412 " return new ::grpc::ClientReaderWriter< $Request$, $Response$>("
Craig Tillerc4965752015-02-09 09:51:00 -0800413 "channel(),"
Craig Tiller8c8d0aa2015-02-12 11:38:36 -0800414 "::grpc::RpcMethod($Service$_method_names[$Idx$], "
nnobleebebb7e2014-12-10 16:31:01 -0800415 "::grpc::RpcMethod::RpcType::BIDI_STREAMING), "
Craig Tillerc4965752015-02-09 09:51:00 -0800416 "context);\n"
nnobleebebb7e2014-12-10 16:31:01 -0800417 "}\n\n");
418 }
419}
420
Craig Tillerecd49342015-01-18 14:36:47 -0800421void PrintSourceServerMethod(google::protobuf::io::Printer *printer,
422 const google::protobuf::MethodDescriptor *method,
423 std::map<std::string, std::string> *vars) {
nnobleebebb7e2014-12-10 16:31:01 -0800424 (*vars)["Method"] = method->name();
425 (*vars)["Request"] =
426 grpc_cpp_generator::ClassName(method->input_type(), true);
427 (*vars)["Response"] =
428 grpc_cpp_generator::ClassName(method->output_type(), true);
429 if (NoStreaming(method)) {
430 printer->Print(*vars,
431 "::grpc::Status $Service$::Service::$Method$("
yangga4b6f5d2014-12-17 15:53:12 -0800432 "::grpc::ServerContext* context, "
nnobleebebb7e2014-12-10 16:31:01 -0800433 "const $Request$* request, $Response$* response) {\n");
434 printer->Print(
435 " return ::grpc::Status("
436 "::grpc::StatusCode::UNIMPLEMENTED);\n");
437 printer->Print("}\n\n");
438 } else if (ClientOnlyStreaming(method)) {
439 printer->Print(*vars,
440 "::grpc::Status $Service$::Service::$Method$("
yangga4b6f5d2014-12-17 15:53:12 -0800441 "::grpc::ServerContext* context, "
Yang Gao1ff11f62015-01-14 11:45:32 -0800442 "::grpc::ServerReader< $Request$>* reader, "
nnobleebebb7e2014-12-10 16:31:01 -0800443 "$Response$* response) {\n");
444 printer->Print(
445 " return ::grpc::Status("
446 "::grpc::StatusCode::UNIMPLEMENTED);\n");
447 printer->Print("}\n\n");
448 } else if (ServerOnlyStreaming(method)) {
449 printer->Print(*vars,
450 "::grpc::Status $Service$::Service::$Method$("
yangga4b6f5d2014-12-17 15:53:12 -0800451 "::grpc::ServerContext* context, "
nnobleebebb7e2014-12-10 16:31:01 -0800452 "const $Request$* request, "
Yang Gao1ff11f62015-01-14 11:45:32 -0800453 "::grpc::ServerWriter< $Response$>* writer) {\n");
nnobleebebb7e2014-12-10 16:31:01 -0800454 printer->Print(
455 " return ::grpc::Status("
456 "::grpc::StatusCode::UNIMPLEMENTED);\n");
457 printer->Print("}\n\n");
458 } else if (BidiStreaming(method)) {
459 printer->Print(*vars,
460 "::grpc::Status $Service$::Service::$Method$("
yangga4b6f5d2014-12-17 15:53:12 -0800461 "::grpc::ServerContext* context, "
Yang Gao1ff11f62015-01-14 11:45:32 -0800462 "::grpc::ServerReaderWriter< $Response$, $Request$>* "
nnobleebebb7e2014-12-10 16:31:01 -0800463 "stream) {\n");
464 printer->Print(
465 " return ::grpc::Status("
466 "::grpc::StatusCode::UNIMPLEMENTED);\n");
467 printer->Print("}\n\n");
468 }
469}
470
Craig Tiller8c8d0aa2015-02-12 11:38:36 -0800471void PrintSourceServerAsyncMethod(
472 google::protobuf::io::Printer *printer,
473 const google::protobuf::MethodDescriptor *method,
474 std::map<std::string, std::string> *vars) {
Craig Tiller225f7be2015-02-09 22:32:37 -0800475 (*vars)["Method"] = method->name();
476 (*vars)["Request"] =
477 grpc_cpp_generator::ClassName(method->input_type(), true);
478 (*vars)["Response"] =
479 grpc_cpp_generator::ClassName(method->output_type(), true);
480 if (NoStreaming(method)) {
481 printer->Print(*vars,
Yang Gaoca3cb3e2015-02-12 00:05:11 -0800482 "void $Service$::AsyncService::Request$Method$("
Craig Tiller225f7be2015-02-09 22:32:37 -0800483 "::grpc::ServerContext* context, "
484 "$Request$* request, "
485 "::grpc::ServerAsyncResponseWriter< $Response$>* response, "
486 "::grpc::CompletionQueue* cq, void* tag) {\n");
487 printer->Print("}\n\n");
488 } else if (ClientOnlyStreaming(method)) {
489 printer->Print(*vars,
Yang Gaoca3cb3e2015-02-12 00:05:11 -0800490 "void $Service$::AsyncService::Request$Method$("
Craig Tiller225f7be2015-02-09 22:32:37 -0800491 "::grpc::ServerContext* context, "
492 "::grpc::ServerAsyncReader< $Request$>* reader, "
493 "::grpc::CompletionQueue* cq, void* tag) {\n");
494 printer->Print("}\n\n");
495 } else if (ServerOnlyStreaming(method)) {
496 printer->Print(*vars,
Yang Gaoca3cb3e2015-02-12 00:05:11 -0800497 "void $Service$::AsyncService::Request$Method$("
Craig Tiller225f7be2015-02-09 22:32:37 -0800498 "::grpc::ServerContext* context, "
499 "$Request$* request, "
500 "::grpc::ServerAsyncWriter< $Response$>* writer, "
501 "::grpc::CompletionQueue* cq, void* tag) {\n");
502 printer->Print("}\n\n");
503 } else if (BidiStreaming(method)) {
Craig Tiller8c8d0aa2015-02-12 11:38:36 -0800504 printer->Print(
505 *vars,
506 "void $Service$::AsyncService::Request$Method$("
507 "::grpc::ServerContext* context, "
508 "::grpc::ServerAsyncReaderWriter< $Response$, $Request$>* stream, "
509 "::grpc::CompletionQueue* cq, void *tag) {\n");
Craig Tiller225f7be2015-02-09 22:32:37 -0800510 printer->Print("}\n\n");
511 }
512}
513
Craig Tillerecd49342015-01-18 14:36:47 -0800514void PrintSourceService(google::protobuf::io::Printer *printer,
515 const google::protobuf::ServiceDescriptor *service,
516 std::map<std::string, std::string> *vars) {
nnobleebebb7e2014-12-10 16:31:01 -0800517 (*vars)["Service"] = service->name();
Craig Tiller8c8d0aa2015-02-12 11:38:36 -0800518
519 printer->Print(*vars, "static const char* $Service$_method_names[] = {\n");
520 for (int i = 0; i < service->method_count(); ++i) {
521 (*vars)["Method"] = service->method(i)->name();
522 printer->Print(*vars, " \"/$Package$$Service$/$Method$\",\n");
523 }
524 printer->Print(*vars, "};\n\n");
525
Yang Gao5680ff42015-01-14 12:14:21 -0800526 printer->Print(
527 *vars,
528 "$Service$::Stub* $Service$::NewStub("
529 "const std::shared_ptr< ::grpc::ChannelInterface>& channel) {\n"
530 " $Service$::Stub* stub = new $Service$::Stub();\n"
531 " stub->set_channel(channel);\n"
532 " return stub;\n"
533 "};\n\n");
nnobleebebb7e2014-12-10 16:31:01 -0800534 for (int i = 0; i < service->method_count(); ++i) {
Craig Tiller8c8d0aa2015-02-12 11:38:36 -0800535 (*vars)["Idx"] = as_string(i);
nnobleebebb7e2014-12-10 16:31:01 -0800536 PrintSourceClientMethod(printer, service->method(i), vars);
537 }
538
Craig Tiller8c8d0aa2015-02-12 11:38:36 -0800539 (*vars)["MethodCount"] = as_string(service->method_count());
540 printer->Print(
541 *vars,
542 "$Service$::AsyncService::AsyncService(::grpc::CompletionQueue* cq) : "
543 "::grpc::AsynchronousService(cq, $Service$_method_names, $MethodCount$) "
544 "{}\n\n");
545
nnobleebebb7e2014-12-10 16:31:01 -0800546 printer->Print(*vars,
547 "$Service$::Service::~Service() {\n"
548 " delete service_;\n"
549 "}\n\n");
550 for (int i = 0; i < service->method_count(); ++i) {
551 PrintSourceServerMethod(printer, service->method(i), vars);
Craig Tiller225f7be2015-02-09 22:32:37 -0800552 PrintSourceServerAsyncMethod(printer, service->method(i), vars);
nnobleebebb7e2014-12-10 16:31:01 -0800553 }
554 printer->Print(*vars,
Craig Tillerb5dcec52015-01-13 11:13:42 -0800555 "::grpc::RpcService* $Service$::Service::service() {\n");
nnobleebebb7e2014-12-10 16:31:01 -0800556 printer->Indent();
Craig Tillerb5dcec52015-01-13 11:13:42 -0800557 printer->Print(
558 "if (service_ != nullptr) {\n"
559 " return service_;\n"
560 "}\n");
nnobleebebb7e2014-12-10 16:31:01 -0800561 printer->Print("service_ = new ::grpc::RpcService();\n");
562 for (int i = 0; i < service->method_count(); ++i) {
Craig Tillerecd49342015-01-18 14:36:47 -0800563 const google::protobuf::MethodDescriptor *method = service->method(i);
Craig Tiller8c8d0aa2015-02-12 11:38:36 -0800564 (*vars)["Idx"] = as_string(i);
nnobleebebb7e2014-12-10 16:31:01 -0800565 (*vars)["Method"] = method->name();
566 (*vars)["Request"] =
567 grpc_cpp_generator::ClassName(method->input_type(), true);
568 (*vars)["Response"] =
569 grpc_cpp_generator::ClassName(method->output_type(), true);
570 if (NoStreaming(method)) {
571 printer->Print(
572 *vars,
573 "service_->AddMethod(new ::grpc::RpcServiceMethod(\n"
Craig Tiller8c8d0aa2015-02-12 11:38:36 -0800574 " $Service$_method_names[$Idx$],\n"
yangg5bcea0d2015-01-06 10:35:03 -0800575 " ::grpc::RpcMethod::NORMAL_RPC,\n"
Yang Gao1ff11f62015-01-14 11:45:32 -0800576 " new ::grpc::RpcMethodHandler< $Service$::Service, $Request$, "
nnobleebebb7e2014-12-10 16:31:01 -0800577 "$Response$>(\n"
Yang Gao1ff11f62015-01-14 11:45:32 -0800578 " std::function< ::grpc::Status($Service$::Service*, "
yangga4b6f5d2014-12-17 15:53:12 -0800579 "::grpc::ServerContext*, const $Request$*, $Response$*)>("
nnobleebebb7e2014-12-10 16:31:01 -0800580 "&$Service$::Service::$Method$), this),\n"
581 " new $Request$, new $Response$));\n");
582 } else if (ClientOnlyStreaming(method)) {
583 printer->Print(
584 *vars,
585 "service_->AddMethod(new ::grpc::RpcServiceMethod(\n"
Craig Tiller8c8d0aa2015-02-12 11:38:36 -0800586 " $Service$_method_names[$Idx$],\n"
yangg5bcea0d2015-01-06 10:35:03 -0800587 " ::grpc::RpcMethod::CLIENT_STREAMING,\n"
Yang Gao1ff11f62015-01-14 11:45:32 -0800588 " new ::grpc::ClientStreamingHandler< "
nnobleebebb7e2014-12-10 16:31:01 -0800589 "$Service$::Service, $Request$, $Response$>(\n"
Yang Gao1ff11f62015-01-14 11:45:32 -0800590 " std::function< ::grpc::Status($Service$::Service*, "
yangga4b6f5d2014-12-17 15:53:12 -0800591 "::grpc::ServerContext*, "
Yang Gao1ff11f62015-01-14 11:45:32 -0800592 "::grpc::ServerReader< $Request$>*, $Response$*)>("
nnobleebebb7e2014-12-10 16:31:01 -0800593 "&$Service$::Service::$Method$), this),\n"
594 " new $Request$, new $Response$));\n");
595 } else if (ServerOnlyStreaming(method)) {
596 printer->Print(
597 *vars,
598 "service_->AddMethod(new ::grpc::RpcServiceMethod(\n"
Craig Tiller8c8d0aa2015-02-12 11:38:36 -0800599 " $Service$_method_names[$Idx$],\n"
yangg5bcea0d2015-01-06 10:35:03 -0800600 " ::grpc::RpcMethod::SERVER_STREAMING,\n"
Yang Gao1ff11f62015-01-14 11:45:32 -0800601 " new ::grpc::ServerStreamingHandler< "
nnobleebebb7e2014-12-10 16:31:01 -0800602 "$Service$::Service, $Request$, $Response$>(\n"
Yang Gao1ff11f62015-01-14 11:45:32 -0800603 " std::function< ::grpc::Status($Service$::Service*, "
yangga4b6f5d2014-12-17 15:53:12 -0800604 "::grpc::ServerContext*, "
Yang Gao1ff11f62015-01-14 11:45:32 -0800605 "const $Request$*, ::grpc::ServerWriter< $Response$>*)>("
nnobleebebb7e2014-12-10 16:31:01 -0800606 "&$Service$::Service::$Method$), this),\n"
607 " new $Request$, new $Response$));\n");
608 } else if (BidiStreaming(method)) {
609 printer->Print(
610 *vars,
611 "service_->AddMethod(new ::grpc::RpcServiceMethod(\n"
Craig Tiller8c8d0aa2015-02-12 11:38:36 -0800612 " $Service$_method_names[$Idx$],\n"
yangg5bcea0d2015-01-06 10:35:03 -0800613 " ::grpc::RpcMethod::BIDI_STREAMING,\n"
Yang Gao1ff11f62015-01-14 11:45:32 -0800614 " new ::grpc::BidiStreamingHandler< "
nnobleebebb7e2014-12-10 16:31:01 -0800615 "$Service$::Service, $Request$, $Response$>(\n"
Yang Gao1ff11f62015-01-14 11:45:32 -0800616 " std::function< ::grpc::Status($Service$::Service*, "
yangga4b6f5d2014-12-17 15:53:12 -0800617 "::grpc::ServerContext*, "
Yang Gao1ff11f62015-01-14 11:45:32 -0800618 "::grpc::ServerReaderWriter< $Response$, $Request$>*)>("
nnobleebebb7e2014-12-10 16:31:01 -0800619 "&$Service$::Service::$Method$), this),\n"
620 " new $Request$, new $Response$));\n");
621 }
622 }
623 printer->Print("return service_;\n");
624 printer->Outdent();
625 printer->Print("}\n\n");
626}
627
Craig Tillerecd49342015-01-18 14:36:47 -0800628std::string GetSourceServices(const google::protobuf::FileDescriptor *file) {
Nicolas Noblef5c5d802015-01-15 16:36:13 -0800629 std::string output;
nnobleebebb7e2014-12-10 16:31:01 -0800630 google::protobuf::io::StringOutputStream output_stream(&output);
631 google::protobuf::io::Printer printer(&output_stream, '$');
Nicolas Noblef5c5d802015-01-15 16:36:13 -0800632 std::map<std::string, std::string> vars;
yangg5bcea0d2015-01-06 10:35:03 -0800633 // Package string is empty or ends with a dot. It is used to fully qualify
634 // method names.
635 vars["Package"] = file->package();
636 if (!file->package().empty()) {
637 vars["Package"].append(".");
638 }
nnobleebebb7e2014-12-10 16:31:01 -0800639
640 for (int i = 0; i < file->service_count(); ++i) {
samuelwca9f3592014-12-15 14:22:04 -0800641 PrintSourceService(&printer, file->service(i), &vars);
nnobleebebb7e2014-12-10 16:31:01 -0800642 printer.Print("\n");
643 }
644 return output;
645}
646
647} // namespace grpc_cpp_generator