blob: 6229170c2a8817b6720d0e376d1821d9527f8a60 [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(
Yang Gao3a5e5492015-02-18 14:32:38 -0800130 "template <class OutMessage> class ClientAsyncResponseReader;\n");
131 temp.append(
Craig Tiller5ef5db12015-02-09 12:47:21 -0800132 "template <class OutMessage> class ServerAsyncResponseWriter;\n");
Craig Tiller2dff17d2015-02-09 12:42:23 -0800133 }
nnobleebebb7e2014-12-10 16:31:01 -0800134 if (HasClientOnlyStreaming(file)) {
135 temp.append("template <class OutMessage> class ClientWriter;\n");
136 temp.append("template <class InMessage> class ServerReader;\n");
Craig Tiller2dff17d2015-02-09 12:42:23 -0800137 temp.append("template <class OutMessage> class ClientAsyncWriter;\n");
Yang Gao005f18a2015-02-13 10:22:33 -0800138 temp.append("template <class OutMessage, class InMessage> class ServerAsyncReader;\n");
nnobleebebb7e2014-12-10 16:31:01 -0800139 }
140 if (HasServerOnlyStreaming(file)) {
141 temp.append("template <class InMessage> class ClientReader;\n");
142 temp.append("template <class OutMessage> class ServerWriter;\n");
Craig Tiller2dff17d2015-02-09 12:42:23 -0800143 temp.append("template <class OutMessage> class ClientAsyncReader;\n");
144 temp.append("template <class InMessage> class ServerAsyncWriter;\n");
nnobleebebb7e2014-12-10 16:31:01 -0800145 }
146 if (HasBidiStreaming(file)) {
147 temp.append(
148 "template <class OutMessage, class InMessage>\n"
149 "class ClientReaderWriter;\n");
150 temp.append(
151 "template <class OutMessage, class InMessage>\n"
152 "class ServerReaderWriter;\n");
Craig Tiller225f7be2015-02-09 22:32:37 -0800153 temp.append(
154 "template <class OutMessage, class InMessage>\n"
155 "class ClientAsyncReaderWriter;\n");
156 temp.append(
157 "template <class OutMessage, class InMessage>\n"
158 "class ServerAsyncReaderWriter;\n");
nnobleebebb7e2014-12-10 16:31:01 -0800159 }
160 temp.append("} // namespace grpc\n");
161 return temp;
162}
163
Nicolas Noblef5c5d802015-01-15 16:36:13 -0800164std::string GetSourceIncludes() {
Yang Gao3a5e5492015-02-18 14:32:38 -0800165 return "#include <grpc++/async_unary_call.h>\n"
166 "#include <grpc++/channel_interface.h>\n"
Craig Tiller80e00a82015-02-09 20:54:25 -0800167 "#include <grpc++/impl/client_unary_call.h>\n"
Craig Tiller2dff17d2015-02-09 12:42:23 -0800168 "#include <grpc++/impl/rpc_method.h>\n"
169 "#include <grpc++/impl/rpc_service_method.h>\n"
Craig Tiller14a65f92015-02-09 13:13:14 -0800170 "#include <grpc++/impl/service_type.h>\n"
Craig Tiller2dff17d2015-02-09 12:42:23 -0800171 "#include <grpc++/stream.h>\n";
nnobleebebb7e2014-12-10 16:31:01 -0800172}
173
Craig Tillerecd49342015-01-18 14:36:47 -0800174void PrintHeaderClientMethod(google::protobuf::io::Printer *printer,
175 const google::protobuf::MethodDescriptor *method,
176 std::map<std::string, std::string> *vars) {
nnobleebebb7e2014-12-10 16:31:01 -0800177 (*vars)["Method"] = method->name();
178 (*vars)["Request"] =
179 grpc_cpp_generator::ClassName(method->input_type(), true);
180 (*vars)["Response"] =
181 grpc_cpp_generator::ClassName(method->output_type(), true);
182 if (NoStreaming(method)) {
183 printer->Print(*vars,
184 "::grpc::Status $Method$(::grpc::ClientContext* context, "
Craig Tiller5ef5db12015-02-09 12:47:21 -0800185 "const $Request$& request, $Response$* response);\n");
186 printer->Print(*vars,
Yang Gao3a5e5492015-02-18 14:32:38 -0800187 "::grpc::ClientAsyncResponseReader< $Response$>* "
188 "$Method$(::grpc::ClientContext* context, "
189 "const $Request$& request, "
Yang Gao068c85b2015-02-12 15:21:24 -0800190 "::grpc::CompletionQueue* cq, void* tag);\n");
nnobleebebb7e2014-12-10 16:31:01 -0800191 } else if (ClientOnlyStreaming(method)) {
Craig Tiller5ef5db12015-02-09 12:47:21 -0800192 printer->Print(*vars,
193 "::grpc::ClientWriter< $Request$>* $Method$("
194 "::grpc::ClientContext* context, $Response$* response);\n");
195 printer->Print(*vars,
Yang Gaoe0b73fd2015-02-12 14:05:47 -0800196 "::grpc::ClientAsyncWriter< $Request$>* $Method$("
Craig Tiller5ef5db12015-02-09 12:47:21 -0800197 "::grpc::ClientContext* context, $Response$* response, "
Yang Gao068c85b2015-02-12 15:21:24 -0800198 "::grpc::CompletionQueue* cq, void* tag);\n");
nnobleebebb7e2014-12-10 16:31:01 -0800199 } else if (ServerOnlyStreaming(method)) {
200 printer->Print(
201 *vars,
Yang Gao1ff11f62015-01-14 11:45:32 -0800202 "::grpc::ClientReader< $Response$>* $Method$("
Yang Gao07d83042015-02-13 14:11:31 -0800203 "::grpc::ClientContext* context, const $Request$& request);\n");
Craig Tiller5ef5db12015-02-09 12:47:21 -0800204 printer->Print(*vars,
Yang Gaoe0b73fd2015-02-12 14:05:47 -0800205 "::grpc::ClientAsyncReader< $Response$>* $Method$("
Yang Gao07d83042015-02-13 14:11:31 -0800206 "::grpc::ClientContext* context, const $Request$& request, "
Yang Gao068c85b2015-02-12 15:21:24 -0800207 "::grpc::CompletionQueue* cq, void* tag);\n");
nnobleebebb7e2014-12-10 16:31:01 -0800208 } else if (BidiStreaming(method)) {
209 printer->Print(*vars,
Yang Gao1ff11f62015-01-14 11:45:32 -0800210 "::grpc::ClientReaderWriter< $Request$, $Response$>* "
Craig Tiller5ef5db12015-02-09 12:47:21 -0800211 "$Method$(::grpc::ClientContext* context);\n");
212 printer->Print(*vars,
Craig Tiller225f7be2015-02-09 22:32:37 -0800213 "::grpc::ClientAsyncReaderWriter< $Request$, $Response$>* "
Craig Tiller5ef5db12015-02-09 12:47:21 -0800214 "$Method$(::grpc::ClientContext* context, "
Yang Gao068c85b2015-02-12 15:21:24 -0800215 "::grpc::CompletionQueue* cq, void* tag);\n");
nnobleebebb7e2014-12-10 16:31:01 -0800216 }
217}
218
Craig Tiller5ef5db12015-02-09 12:47:21 -0800219void PrintHeaderServerMethodSync(
220 google::protobuf::io::Printer *printer,
221 const google::protobuf::MethodDescriptor *method,
222 std::map<std::string, std::string> *vars) {
nnobleebebb7e2014-12-10 16:31:01 -0800223 (*vars)["Method"] = method->name();
224 (*vars)["Request"] =
225 grpc_cpp_generator::ClassName(method->input_type(), true);
226 (*vars)["Response"] =
227 grpc_cpp_generator::ClassName(method->output_type(), true);
228 if (NoStreaming(method)) {
229 printer->Print(*vars,
yangga4b6f5d2014-12-17 15:53:12 -0800230 "virtual ::grpc::Status $Method$("
231 "::grpc::ServerContext* context, const $Request$* request, "
nnobleebebb7e2014-12-10 16:31:01 -0800232 "$Response$* response);\n");
233 } else if (ClientOnlyStreaming(method)) {
234 printer->Print(*vars,
235 "virtual ::grpc::Status $Method$("
yangga4b6f5d2014-12-17 15:53:12 -0800236 "::grpc::ServerContext* context, "
Yang Gao1ff11f62015-01-14 11:45:32 -0800237 "::grpc::ServerReader< $Request$>* reader, "
nnobleebebb7e2014-12-10 16:31:01 -0800238 "$Response$* response);\n");
239 } else if (ServerOnlyStreaming(method)) {
240 printer->Print(*vars,
yangga4b6f5d2014-12-17 15:53:12 -0800241 "virtual ::grpc::Status $Method$("
242 "::grpc::ServerContext* context, const $Request$* request, "
Yang Gao1ff11f62015-01-14 11:45:32 -0800243 "::grpc::ServerWriter< $Response$>* writer);\n");
nnobleebebb7e2014-12-10 16:31:01 -0800244 } else if (BidiStreaming(method)) {
Yang Gao5680ff42015-01-14 12:14:21 -0800245 printer->Print(
246 *vars,
247 "virtual ::grpc::Status $Method$("
248 "::grpc::ServerContext* context, "
249 "::grpc::ServerReaderWriter< $Response$, $Request$>* stream);"
250 "\n");
nnobleebebb7e2014-12-10 16:31:01 -0800251 }
252}
253
Craig Tiller5ef5db12015-02-09 12:47:21 -0800254void PrintHeaderServerMethodAsync(
255 google::protobuf::io::Printer *printer,
256 const google::protobuf::MethodDescriptor *method,
257 std::map<std::string, std::string> *vars) {
Craig Tiller2dff17d2015-02-09 12:42:23 -0800258 (*vars)["Method"] = method->name();
259 (*vars)["Request"] =
260 grpc_cpp_generator::ClassName(method->input_type(), true);
261 (*vars)["Response"] =
262 grpc_cpp_generator::ClassName(method->output_type(), true);
263 if (NoStreaming(method)) {
264 printer->Print(*vars,
Yang Gaoca3cb3e2015-02-12 00:05:11 -0800265 "void Request$Method$("
Craig Tiller2dff17d2015-02-09 12:42:23 -0800266 "::grpc::ServerContext* context, $Request$* request, "
267 "::grpc::ServerAsyncResponseWriter< $Response$>* response, "
268 "::grpc::CompletionQueue* cq, void *tag);\n");
269 } else if (ClientOnlyStreaming(method)) {
270 printer->Print(*vars,
Yang Gaoca3cb3e2015-02-12 00:05:11 -0800271 "void Request$Method$("
Craig Tiller2dff17d2015-02-09 12:42:23 -0800272 "::grpc::ServerContext* context, "
Yang Gao005f18a2015-02-13 10:22:33 -0800273 "::grpc::ServerAsyncReader< $Response$, $Request$>* reader, "
Craig Tiller2dff17d2015-02-09 12:42:23 -0800274 "::grpc::CompletionQueue* cq, void *tag);\n");
275 } else if (ServerOnlyStreaming(method)) {
276 printer->Print(*vars,
Yang Gaoca3cb3e2015-02-12 00:05:11 -0800277 "void Request$Method$("
Craig Tiller2dff17d2015-02-09 12:42:23 -0800278 "::grpc::ServerContext* context, $Request$* request, "
279 "::grpc::ServerAsyncWriter< $Response$>* writer, "
280 "::grpc::CompletionQueue* cq, void *tag);\n");
281 } else if (BidiStreaming(method)) {
282 printer->Print(
283 *vars,
Yang Gaoca3cb3e2015-02-12 00:05:11 -0800284 "void Request$Method$("
Craig Tiller2dff17d2015-02-09 12:42:23 -0800285 "::grpc::ServerContext* context, "
Craig Tiller225f7be2015-02-09 22:32:37 -0800286 "::grpc::ServerAsyncReaderWriter< $Response$, $Request$>* stream, "
Craig Tiller5ef5db12015-02-09 12:47:21 -0800287 "::grpc::CompletionQueue* cq, void *tag);\n");
Craig Tiller2dff17d2015-02-09 12:42:23 -0800288 }
289}
290
Craig Tillerecd49342015-01-18 14:36:47 -0800291void PrintHeaderService(google::protobuf::io::Printer *printer,
292 const google::protobuf::ServiceDescriptor *service,
293 std::map<std::string, std::string> *vars) {
nnobleebebb7e2014-12-10 16:31:01 -0800294 (*vars)["Service"] = service->name();
295
296 printer->Print(*vars,
Craig Tiller2dff17d2015-02-09 12:42:23 -0800297 "class $Service$ final {\n"
nnobleebebb7e2014-12-10 16:31:01 -0800298 " public:\n");
299 printer->Indent();
300
301 // Client side
Craig Tillerb5dcec52015-01-13 11:13:42 -0800302 printer->Print(
Craig Tiller2dff17d2015-02-09 12:42:23 -0800303 "class Stub final : public ::grpc::InternalStub {\n"
Craig Tillerb5dcec52015-01-13 11:13:42 -0800304 " public:\n");
nnobleebebb7e2014-12-10 16:31:01 -0800305 printer->Indent();
306 for (int i = 0; i < service->method_count(); ++i) {
307 PrintHeaderClientMethod(printer, service->method(i), vars);
308 }
309 printer->Outdent();
310 printer->Print("};\n");
311 printer->Print(
Yang Gao1ff11f62015-01-14 11:45:32 -0800312 "static Stub* NewStub(const std::shared_ptr< ::grpc::ChannelInterface>& "
nnobleebebb7e2014-12-10 16:31:01 -0800313 "channel);\n");
314
315 printer->Print("\n");
316
Craig Tiller2dff17d2015-02-09 12:42:23 -0800317 // Server side - Synchronous
Craig Tillerb5dcec52015-01-13 11:13:42 -0800318 printer->Print(
Craig Tiller14a65f92015-02-09 13:13:14 -0800319 "class Service : public ::grpc::SynchronousService {\n"
Craig Tillerb5dcec52015-01-13 11:13:42 -0800320 " public:\n");
nnobleebebb7e2014-12-10 16:31:01 -0800321 printer->Indent();
322 printer->Print("Service() : service_(nullptr) {}\n");
323 printer->Print("virtual ~Service();\n");
324 for (int i = 0; i < service->method_count(); ++i) {
Craig Tiller2dff17d2015-02-09 12:42:23 -0800325 PrintHeaderServerMethodSync(printer, service->method(i), vars);
326 }
Craig Tiller40fcdaf2015-02-09 15:43:34 -0800327 printer->Print("::grpc::RpcService* service() override final;\n");
Craig Tiller2dff17d2015-02-09 12:42:23 -0800328 printer->Outdent();
329 printer->Print(
330 " private:\n"
331 " ::grpc::RpcService* service_;\n");
332 printer->Print("};\n");
333
334 // Server side - Asynchronous
335 printer->Print(
Craig Tiller14a65f92015-02-09 13:13:14 -0800336 "class AsyncService final : public ::grpc::AsynchronousService {\n"
Craig Tiller2dff17d2015-02-09 12:42:23 -0800337 " public:\n");
338 printer->Indent();
Craig Tiller8c8d0aa2015-02-12 11:38:36 -0800339 (*vars)["MethodCount"] = as_string(service->method_count());
340 printer->Print("explicit AsyncService(::grpc::CompletionQueue* cq);\n");
Craig Tiller0220cf12015-02-12 17:39:26 -0800341 printer->Print("~AsyncService() {};\n");
Craig Tiller2dff17d2015-02-09 12:42:23 -0800342 for (int i = 0; i < service->method_count(); ++i) {
343 PrintHeaderServerMethodAsync(printer, service->method(i), vars);
nnobleebebb7e2014-12-10 16:31:01 -0800344 }
nnobleebebb7e2014-12-10 16:31:01 -0800345 printer->Outdent();
nnobleebebb7e2014-12-10 16:31:01 -0800346 printer->Print("};\n");
347
348 printer->Outdent();
349 printer->Print("};\n");
350}
351
Craig Tillerecd49342015-01-18 14:36:47 -0800352std::string GetHeaderServices(const google::protobuf::FileDescriptor *file) {
Nicolas Noblef5c5d802015-01-15 16:36:13 -0800353 std::string output;
nnobleebebb7e2014-12-10 16:31:01 -0800354 google::protobuf::io::StringOutputStream output_stream(&output);
355 google::protobuf::io::Printer printer(&output_stream, '$');
Nicolas Noblef5c5d802015-01-15 16:36:13 -0800356 std::map<std::string, std::string> vars;
nnobleebebb7e2014-12-10 16:31:01 -0800357
358 for (int i = 0; i < file->service_count(); ++i) {
samuelwca9f3592014-12-15 14:22:04 -0800359 PrintHeaderService(&printer, file->service(i), &vars);
nnobleebebb7e2014-12-10 16:31:01 -0800360 printer.Print("\n");
361 }
362 return output;
363}
364
Craig Tillerecd49342015-01-18 14:36:47 -0800365void PrintSourceClientMethod(google::protobuf::io::Printer *printer,
366 const google::protobuf::MethodDescriptor *method,
367 std::map<std::string, std::string> *vars) {
nnobleebebb7e2014-12-10 16:31:01 -0800368 (*vars)["Method"] = method->name();
369 (*vars)["Request"] =
370 grpc_cpp_generator::ClassName(method->input_type(), true);
371 (*vars)["Response"] =
372 grpc_cpp_generator::ClassName(method->output_type(), true);
373 if (NoStreaming(method)) {
374 printer->Print(*vars,
375 "::grpc::Status $Service$::Stub::$Method$("
376 "::grpc::ClientContext* context, "
377 "const $Request$& request, $Response$* response) {\n");
378 printer->Print(*vars,
Craig Tiller1c9a2a92015-02-12 14:10:25 -0800379 " return ::grpc::BlockingUnaryCall(channel(),"
Craig Tiller8c8d0aa2015-02-12 11:38:36 -0800380 "::grpc::RpcMethod($Service$_method_names[$Idx$]), "
nnobleebebb7e2014-12-10 16:31:01 -0800381 "context, request, response);\n"
382 "}\n\n");
Yang Gao068c85b2015-02-12 15:21:24 -0800383 printer->Print(*vars,
Yang Gao3a5e5492015-02-18 14:32:38 -0800384 "::grpc::ClientAsyncResponseReader< $Response$>* "
385 "$Service$::Stub::$Method$(::grpc::ClientContext* context, "
386 "const $Request$& request, "
Yang Gao068c85b2015-02-12 15:21:24 -0800387 "::grpc::CompletionQueue* cq, void* tag) {\n");
388 printer->Print(*vars,
Yang Gao3a5e5492015-02-18 14:32:38 -0800389 " return new ClientAsyncResponseReader< $Response$>("
390 "channel(), cq, "
Yang Gao068c85b2015-02-12 15:21:24 -0800391 "::grpc::RpcMethod($Service$_method_names[$Idx$]), "
Yang Gao3a5e5492015-02-18 14:32:38 -0800392 "context, request, tag);\n"
Yang Gao068c85b2015-02-12 15:21:24 -0800393 "}\n\n");
nnobleebebb7e2014-12-10 16:31:01 -0800394 } else if (ClientOnlyStreaming(method)) {
Yang Gao5680ff42015-01-14 12:14:21 -0800395 printer->Print(
396 *vars,
397 "::grpc::ClientWriter< $Request$>* $Service$::Stub::$Method$("
398 "::grpc::ClientContext* context, $Response$* response) {\n");
yangg5bcea0d2015-01-06 10:35:03 -0800399 printer->Print(*vars,
Yang Gao1ff11f62015-01-14 11:45:32 -0800400 " return new ::grpc::ClientWriter< $Request$>("
Craig Tillerc4965752015-02-09 09:51:00 -0800401 "channel(),"
Craig Tiller8c8d0aa2015-02-12 11:38:36 -0800402 "::grpc::RpcMethod($Service$_method_names[$Idx$], "
yangg5bcea0d2015-01-06 10:35:03 -0800403 "::grpc::RpcMethod::RpcType::CLIENT_STREAMING), "
Craig Tillerc4965752015-02-09 09:51:00 -0800404 "context, response);\n"
yangg5bcea0d2015-01-06 10:35:03 -0800405 "}\n\n");
Yang Gao068c85b2015-02-12 15:21:24 -0800406 printer->Print(
407 *vars,
408 "::grpc::ClientAsyncWriter< $Request$>* $Service$::Stub::$Method$("
409 "::grpc::ClientContext* context, $Response$* response, "
410 "::grpc::CompletionQueue* cq, void* tag) {\n");
411 printer->Print(*vars,
412 " return new ::grpc::ClientAsyncWriter< $Request$>("
413 "channel(), cq, "
414 "::grpc::RpcMethod($Service$_method_names[$Idx$], "
415 "::grpc::RpcMethod::RpcType::CLIENT_STREAMING), "
416 "context, response, tag);\n"
417 "}\n\n");
nnobleebebb7e2014-12-10 16:31:01 -0800418 } else if (ServerOnlyStreaming(method)) {
419 printer->Print(
420 *vars,
Yang Gao1ff11f62015-01-14 11:45:32 -0800421 "::grpc::ClientReader< $Response$>* $Service$::Stub::$Method$("
Yang Gao07d83042015-02-13 14:11:31 -0800422 "::grpc::ClientContext* context, const $Request$& request) {\n");
yangg5bcea0d2015-01-06 10:35:03 -0800423 printer->Print(*vars,
Yang Gao1ff11f62015-01-14 11:45:32 -0800424 " return new ::grpc::ClientReader< $Response$>("
Craig Tillerc4965752015-02-09 09:51:00 -0800425 "channel(),"
Craig Tiller8c8d0aa2015-02-12 11:38:36 -0800426 "::grpc::RpcMethod($Service$_method_names[$Idx$], "
yangg5bcea0d2015-01-06 10:35:03 -0800427 "::grpc::RpcMethod::RpcType::SERVER_STREAMING), "
Yang Gao07d83042015-02-13 14:11:31 -0800428 "context, request);\n"
yangg5bcea0d2015-01-06 10:35:03 -0800429 "}\n\n");
Yang Gao068c85b2015-02-12 15:21:24 -0800430 printer->Print(
431 *vars,
432 "::grpc::ClientAsyncReader< $Response$>* $Service$::Stub::$Method$("
Yang Gao07d83042015-02-13 14:11:31 -0800433 "::grpc::ClientContext* context, const $Request$& request, "
Yang Gao068c85b2015-02-12 15:21:24 -0800434 "::grpc::CompletionQueue* cq, void* tag) {\n");
435 printer->Print(*vars,
436 " return new ::grpc::ClientAsyncReader< $Response$>("
437 "channel(), cq, "
438 "::grpc::RpcMethod($Service$_method_names[$Idx$], "
439 "::grpc::RpcMethod::RpcType::SERVER_STREAMING), "
Yang Gao07d83042015-02-13 14:11:31 -0800440 "context, request, tag);\n"
Yang Gao068c85b2015-02-12 15:21:24 -0800441 "}\n\n");
nnobleebebb7e2014-12-10 16:31:01 -0800442 } else if (BidiStreaming(method)) {
443 printer->Print(
444 *vars,
Yang Gao1ff11f62015-01-14 11:45:32 -0800445 "::grpc::ClientReaderWriter< $Request$, $Response$>* "
nnobleebebb7e2014-12-10 16:31:01 -0800446 "$Service$::Stub::$Method$(::grpc::ClientContext* context) {\n");
447 printer->Print(
448 *vars,
Yang Gao1ff11f62015-01-14 11:45:32 -0800449 " return new ::grpc::ClientReaderWriter< $Request$, $Response$>("
Craig Tillerc4965752015-02-09 09:51:00 -0800450 "channel(),"
Craig Tiller8c8d0aa2015-02-12 11:38:36 -0800451 "::grpc::RpcMethod($Service$_method_names[$Idx$], "
nnobleebebb7e2014-12-10 16:31:01 -0800452 "::grpc::RpcMethod::RpcType::BIDI_STREAMING), "
Craig Tillerc4965752015-02-09 09:51:00 -0800453 "context);\n"
nnobleebebb7e2014-12-10 16:31:01 -0800454 "}\n\n");
Yang Gao068c85b2015-02-12 15:21:24 -0800455 printer->Print(
456 *vars,
457 "::grpc::ClientAsyncReaderWriter< $Request$, $Response$>* "
458 "$Service$::Stub::$Method$(::grpc::ClientContext* context, "
459 "::grpc::CompletionQueue* cq, void* tag) {\n");
460 printer->Print(
461 *vars,
462 " return new ::grpc::ClientAsyncReaderWriter< $Request$, $Response$>("
463 "channel(), cq, "
464 "::grpc::RpcMethod($Service$_method_names[$Idx$], "
465 "::grpc::RpcMethod::RpcType::BIDI_STREAMING), "
466 "context, tag);\n"
467 "}\n\n");
nnobleebebb7e2014-12-10 16:31:01 -0800468 }
469}
470
Craig Tillerecd49342015-01-18 14:36:47 -0800471void PrintSourceServerMethod(google::protobuf::io::Printer *printer,
472 const google::protobuf::MethodDescriptor *method,
473 std::map<std::string, std::string> *vars) {
nnobleebebb7e2014-12-10 16:31:01 -0800474 (*vars)["Method"] = method->name();
475 (*vars)["Request"] =
476 grpc_cpp_generator::ClassName(method->input_type(), true);
477 (*vars)["Response"] =
478 grpc_cpp_generator::ClassName(method->output_type(), true);
479 if (NoStreaming(method)) {
480 printer->Print(*vars,
481 "::grpc::Status $Service$::Service::$Method$("
yangga4b6f5d2014-12-17 15:53:12 -0800482 "::grpc::ServerContext* context, "
nnobleebebb7e2014-12-10 16:31:01 -0800483 "const $Request$* request, $Response$* response) {\n");
484 printer->Print(
485 " return ::grpc::Status("
486 "::grpc::StatusCode::UNIMPLEMENTED);\n");
487 printer->Print("}\n\n");
488 } else if (ClientOnlyStreaming(method)) {
489 printer->Print(*vars,
490 "::grpc::Status $Service$::Service::$Method$("
yangga4b6f5d2014-12-17 15:53:12 -0800491 "::grpc::ServerContext* context, "
Yang Gao1ff11f62015-01-14 11:45:32 -0800492 "::grpc::ServerReader< $Request$>* reader, "
nnobleebebb7e2014-12-10 16:31:01 -0800493 "$Response$* response) {\n");
494 printer->Print(
495 " return ::grpc::Status("
496 "::grpc::StatusCode::UNIMPLEMENTED);\n");
497 printer->Print("}\n\n");
498 } else if (ServerOnlyStreaming(method)) {
499 printer->Print(*vars,
500 "::grpc::Status $Service$::Service::$Method$("
yangga4b6f5d2014-12-17 15:53:12 -0800501 "::grpc::ServerContext* context, "
nnobleebebb7e2014-12-10 16:31:01 -0800502 "const $Request$* request, "
Yang Gao1ff11f62015-01-14 11:45:32 -0800503 "::grpc::ServerWriter< $Response$>* writer) {\n");
nnobleebebb7e2014-12-10 16:31:01 -0800504 printer->Print(
505 " return ::grpc::Status("
506 "::grpc::StatusCode::UNIMPLEMENTED);\n");
507 printer->Print("}\n\n");
508 } else if (BidiStreaming(method)) {
509 printer->Print(*vars,
510 "::grpc::Status $Service$::Service::$Method$("
yangga4b6f5d2014-12-17 15:53:12 -0800511 "::grpc::ServerContext* context, "
Yang Gao1ff11f62015-01-14 11:45:32 -0800512 "::grpc::ServerReaderWriter< $Response$, $Request$>* "
nnobleebebb7e2014-12-10 16:31:01 -0800513 "stream) {\n");
514 printer->Print(
515 " return ::grpc::Status("
516 "::grpc::StatusCode::UNIMPLEMENTED);\n");
517 printer->Print("}\n\n");
518 }
519}
520
Craig Tiller8c8d0aa2015-02-12 11:38:36 -0800521void PrintSourceServerAsyncMethod(
522 google::protobuf::io::Printer *printer,
523 const google::protobuf::MethodDescriptor *method,
524 std::map<std::string, std::string> *vars) {
Craig Tiller225f7be2015-02-09 22:32:37 -0800525 (*vars)["Method"] = method->name();
526 (*vars)["Request"] =
527 grpc_cpp_generator::ClassName(method->input_type(), true);
528 (*vars)["Response"] =
529 grpc_cpp_generator::ClassName(method->output_type(), true);
530 if (NoStreaming(method)) {
531 printer->Print(*vars,
Yang Gaoca3cb3e2015-02-12 00:05:11 -0800532 "void $Service$::AsyncService::Request$Method$("
Craig Tiller225f7be2015-02-09 22:32:37 -0800533 "::grpc::ServerContext* context, "
534 "$Request$* request, "
535 "::grpc::ServerAsyncResponseWriter< $Response$>* response, "
536 "::grpc::CompletionQueue* cq, void* tag) {\n");
Craig Tiller1c9a2a92015-02-12 14:10:25 -0800537 printer->Print(
538 *vars,
539 " AsynchronousService::RequestAsyncUnary($Idx$, context, request, response, cq, tag);\n");
Craig Tiller225f7be2015-02-09 22:32:37 -0800540 printer->Print("}\n\n");
541 } else if (ClientOnlyStreaming(method)) {
542 printer->Print(*vars,
Yang Gaoca3cb3e2015-02-12 00:05:11 -0800543 "void $Service$::AsyncService::Request$Method$("
Craig Tiller225f7be2015-02-09 22:32:37 -0800544 "::grpc::ServerContext* context, "
Yang Gao005f18a2015-02-13 10:22:33 -0800545 "::grpc::ServerAsyncReader< $Response$, $Request$>* reader, "
Craig Tiller225f7be2015-02-09 22:32:37 -0800546 "::grpc::CompletionQueue* cq, void* tag) {\n");
Craig Tiller1c9a2a92015-02-12 14:10:25 -0800547 printer->Print(
548 *vars,
549 " AsynchronousService::RequestClientStreaming($Idx$, context, reader, cq, tag);\n");
Craig Tiller225f7be2015-02-09 22:32:37 -0800550 printer->Print("}\n\n");
551 } else if (ServerOnlyStreaming(method)) {
552 printer->Print(*vars,
Yang Gaoca3cb3e2015-02-12 00:05:11 -0800553 "void $Service$::AsyncService::Request$Method$("
Craig Tiller225f7be2015-02-09 22:32:37 -0800554 "::grpc::ServerContext* context, "
555 "$Request$* request, "
556 "::grpc::ServerAsyncWriter< $Response$>* writer, "
557 "::grpc::CompletionQueue* cq, void* tag) {\n");
Craig Tiller1c9a2a92015-02-12 14:10:25 -0800558 printer->Print(
559 *vars,
560 " AsynchronousService::RequestServerStreaming($Idx$, context, request, writer, cq, tag);\n");
Craig Tiller225f7be2015-02-09 22:32:37 -0800561 printer->Print("}\n\n");
562 } else if (BidiStreaming(method)) {
Craig Tiller8c8d0aa2015-02-12 11:38:36 -0800563 printer->Print(
564 *vars,
565 "void $Service$::AsyncService::Request$Method$("
566 "::grpc::ServerContext* context, "
567 "::grpc::ServerAsyncReaderWriter< $Response$, $Request$>* stream, "
568 "::grpc::CompletionQueue* cq, void *tag) {\n");
Craig Tiller1c9a2a92015-02-12 14:10:25 -0800569 printer->Print(
570 *vars,
571 " AsynchronousService::RequestBidiStreaming($Idx$, context, stream, cq, tag);\n");
Craig Tiller225f7be2015-02-09 22:32:37 -0800572 printer->Print("}\n\n");
573 }
574}
575
Craig Tillerecd49342015-01-18 14:36:47 -0800576void PrintSourceService(google::protobuf::io::Printer *printer,
577 const google::protobuf::ServiceDescriptor *service,
578 std::map<std::string, std::string> *vars) {
nnobleebebb7e2014-12-10 16:31:01 -0800579 (*vars)["Service"] = service->name();
Craig Tiller8c8d0aa2015-02-12 11:38:36 -0800580
581 printer->Print(*vars, "static const char* $Service$_method_names[] = {\n");
582 for (int i = 0; i < service->method_count(); ++i) {
583 (*vars)["Method"] = service->method(i)->name();
584 printer->Print(*vars, " \"/$Package$$Service$/$Method$\",\n");
585 }
586 printer->Print(*vars, "};\n\n");
587
Yang Gao5680ff42015-01-14 12:14:21 -0800588 printer->Print(
589 *vars,
590 "$Service$::Stub* $Service$::NewStub("
591 "const std::shared_ptr< ::grpc::ChannelInterface>& channel) {\n"
592 " $Service$::Stub* stub = new $Service$::Stub();\n"
593 " stub->set_channel(channel);\n"
594 " return stub;\n"
595 "};\n\n");
nnobleebebb7e2014-12-10 16:31:01 -0800596 for (int i = 0; i < service->method_count(); ++i) {
Craig Tiller8c8d0aa2015-02-12 11:38:36 -0800597 (*vars)["Idx"] = as_string(i);
nnobleebebb7e2014-12-10 16:31:01 -0800598 PrintSourceClientMethod(printer, service->method(i), vars);
599 }
600
Craig Tiller8c8d0aa2015-02-12 11:38:36 -0800601 (*vars)["MethodCount"] = as_string(service->method_count());
602 printer->Print(
603 *vars,
604 "$Service$::AsyncService::AsyncService(::grpc::CompletionQueue* cq) : "
605 "::grpc::AsynchronousService(cq, $Service$_method_names, $MethodCount$) "
606 "{}\n\n");
607
nnobleebebb7e2014-12-10 16:31:01 -0800608 printer->Print(*vars,
609 "$Service$::Service::~Service() {\n"
610 " delete service_;\n"
611 "}\n\n");
612 for (int i = 0; i < service->method_count(); ++i) {
Craig Tiller1c9a2a92015-02-12 14:10:25 -0800613 (*vars)["Idx"] = as_string(i);
nnobleebebb7e2014-12-10 16:31:01 -0800614 PrintSourceServerMethod(printer, service->method(i), vars);
Craig Tiller225f7be2015-02-09 22:32:37 -0800615 PrintSourceServerAsyncMethod(printer, service->method(i), vars);
nnobleebebb7e2014-12-10 16:31:01 -0800616 }
617 printer->Print(*vars,
Craig Tillerb5dcec52015-01-13 11:13:42 -0800618 "::grpc::RpcService* $Service$::Service::service() {\n");
nnobleebebb7e2014-12-10 16:31:01 -0800619 printer->Indent();
Craig Tillerb5dcec52015-01-13 11:13:42 -0800620 printer->Print(
621 "if (service_ != nullptr) {\n"
622 " return service_;\n"
623 "}\n");
nnobleebebb7e2014-12-10 16:31:01 -0800624 printer->Print("service_ = new ::grpc::RpcService();\n");
625 for (int i = 0; i < service->method_count(); ++i) {
Craig Tillerecd49342015-01-18 14:36:47 -0800626 const google::protobuf::MethodDescriptor *method = service->method(i);
Craig Tiller8c8d0aa2015-02-12 11:38:36 -0800627 (*vars)["Idx"] = as_string(i);
nnobleebebb7e2014-12-10 16:31:01 -0800628 (*vars)["Method"] = method->name();
629 (*vars)["Request"] =
630 grpc_cpp_generator::ClassName(method->input_type(), true);
631 (*vars)["Response"] =
632 grpc_cpp_generator::ClassName(method->output_type(), true);
633 if (NoStreaming(method)) {
634 printer->Print(
635 *vars,
636 "service_->AddMethod(new ::grpc::RpcServiceMethod(\n"
Craig Tiller8c8d0aa2015-02-12 11:38:36 -0800637 " $Service$_method_names[$Idx$],\n"
yangg5bcea0d2015-01-06 10:35:03 -0800638 " ::grpc::RpcMethod::NORMAL_RPC,\n"
Yang Gao1ff11f62015-01-14 11:45:32 -0800639 " new ::grpc::RpcMethodHandler< $Service$::Service, $Request$, "
nnobleebebb7e2014-12-10 16:31:01 -0800640 "$Response$>(\n"
Yang Gao1ff11f62015-01-14 11:45:32 -0800641 " std::function< ::grpc::Status($Service$::Service*, "
yangga4b6f5d2014-12-17 15:53:12 -0800642 "::grpc::ServerContext*, const $Request$*, $Response$*)>("
nnobleebebb7e2014-12-10 16:31:01 -0800643 "&$Service$::Service::$Method$), this),\n"
644 " new $Request$, new $Response$));\n");
645 } else if (ClientOnlyStreaming(method)) {
646 printer->Print(
647 *vars,
648 "service_->AddMethod(new ::grpc::RpcServiceMethod(\n"
Craig Tiller8c8d0aa2015-02-12 11:38:36 -0800649 " $Service$_method_names[$Idx$],\n"
yangg5bcea0d2015-01-06 10:35:03 -0800650 " ::grpc::RpcMethod::CLIENT_STREAMING,\n"
Yang Gao1ff11f62015-01-14 11:45:32 -0800651 " new ::grpc::ClientStreamingHandler< "
nnobleebebb7e2014-12-10 16:31:01 -0800652 "$Service$::Service, $Request$, $Response$>(\n"
Yang Gao1ff11f62015-01-14 11:45:32 -0800653 " std::function< ::grpc::Status($Service$::Service*, "
yangga4b6f5d2014-12-17 15:53:12 -0800654 "::grpc::ServerContext*, "
Yang Gao1ff11f62015-01-14 11:45:32 -0800655 "::grpc::ServerReader< $Request$>*, $Response$*)>("
nnobleebebb7e2014-12-10 16:31:01 -0800656 "&$Service$::Service::$Method$), this),\n"
657 " new $Request$, new $Response$));\n");
658 } else if (ServerOnlyStreaming(method)) {
659 printer->Print(
660 *vars,
661 "service_->AddMethod(new ::grpc::RpcServiceMethod(\n"
Craig Tiller8c8d0aa2015-02-12 11:38:36 -0800662 " $Service$_method_names[$Idx$],\n"
yangg5bcea0d2015-01-06 10:35:03 -0800663 " ::grpc::RpcMethod::SERVER_STREAMING,\n"
Yang Gao1ff11f62015-01-14 11:45:32 -0800664 " new ::grpc::ServerStreamingHandler< "
nnobleebebb7e2014-12-10 16:31:01 -0800665 "$Service$::Service, $Request$, $Response$>(\n"
Yang Gao1ff11f62015-01-14 11:45:32 -0800666 " std::function< ::grpc::Status($Service$::Service*, "
yangga4b6f5d2014-12-17 15:53:12 -0800667 "::grpc::ServerContext*, "
Yang Gao1ff11f62015-01-14 11:45:32 -0800668 "const $Request$*, ::grpc::ServerWriter< $Response$>*)>("
nnobleebebb7e2014-12-10 16:31:01 -0800669 "&$Service$::Service::$Method$), this),\n"
670 " new $Request$, new $Response$));\n");
671 } else if (BidiStreaming(method)) {
672 printer->Print(
673 *vars,
674 "service_->AddMethod(new ::grpc::RpcServiceMethod(\n"
Craig Tiller8c8d0aa2015-02-12 11:38:36 -0800675 " $Service$_method_names[$Idx$],\n"
yangg5bcea0d2015-01-06 10:35:03 -0800676 " ::grpc::RpcMethod::BIDI_STREAMING,\n"
Yang Gao1ff11f62015-01-14 11:45:32 -0800677 " new ::grpc::BidiStreamingHandler< "
nnobleebebb7e2014-12-10 16:31:01 -0800678 "$Service$::Service, $Request$, $Response$>(\n"
Yang Gao1ff11f62015-01-14 11:45:32 -0800679 " std::function< ::grpc::Status($Service$::Service*, "
yangga4b6f5d2014-12-17 15:53:12 -0800680 "::grpc::ServerContext*, "
Yang Gao1ff11f62015-01-14 11:45:32 -0800681 "::grpc::ServerReaderWriter< $Response$, $Request$>*)>("
nnobleebebb7e2014-12-10 16:31:01 -0800682 "&$Service$::Service::$Method$), this),\n"
683 " new $Request$, new $Response$));\n");
684 }
685 }
686 printer->Print("return service_;\n");
687 printer->Outdent();
688 printer->Print("}\n\n");
689}
690
Craig Tillerecd49342015-01-18 14:36:47 -0800691std::string GetSourceServices(const google::protobuf::FileDescriptor *file) {
Nicolas Noblef5c5d802015-01-15 16:36:13 -0800692 std::string output;
nnobleebebb7e2014-12-10 16:31:01 -0800693 google::protobuf::io::StringOutputStream output_stream(&output);
694 google::protobuf::io::Printer printer(&output_stream, '$');
Nicolas Noblef5c5d802015-01-15 16:36:13 -0800695 std::map<std::string, std::string> vars;
yangg5bcea0d2015-01-06 10:35:03 -0800696 // Package string is empty or ends with a dot. It is used to fully qualify
697 // method names.
698 vars["Package"] = file->package();
699 if (!file->package().empty()) {
700 vars["Package"].append(".");
701 }
nnobleebebb7e2014-12-10 16:31:01 -0800702
703 for (int i = 0; i < file->service_count(); ++i) {
samuelwca9f3592014-12-15 14:22:04 -0800704 PrintSourceService(&printer, file->service(i), &vars);
nnobleebebb7e2014-12-10 16:31:01 -0800705 printer.Print("\n");
706 }
707 return output;
708}
709
710} // namespace grpc_cpp_generator