1/*
2 *
3 * Copyright 2015, 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
34#include <map>
35
36#include "src/compiler/cpp_generator.h"
37#include "flatbuffers/util.h"
38
39#include <sstream>
40
41namespace grpc_cpp_generator {
42namespace {
43
44grpc::string message_header_ext() { return "_generated.h"; }
45grpc::string service_header_ext() { return ".grpc.fb.h"; }
46
47template <class T>
48grpc::string as_string(T x) {
49 std::ostringstream out;
50 out << x;
51 return out.str();
52}
53
54inline bool ClientOnlyStreaming(const grpc_generator::Method *method) {
55 return method->ClientStreaming() && !method->ServerStreaming();
56}
57
58inline bool ServerOnlyStreaming(const grpc_generator::Method *method) {
59 return !method->ClientStreaming() && method->ServerStreaming();
60}
61
62grpc::string FilenameIdentifier(const grpc::string &filename) {
63 grpc::string result;
64 for (unsigned i = 0; i < filename.size(); i++) {
65 char c = filename[i];
66 if (isalnum(c)) {
67 result.push_back(c);
68 } else {
69 static char hex[] = "0123456789abcdef";
70 result.push_back('_');
71 result.push_back(hex[(c >> 4) & 0xf]);
72 result.push_back(hex[c & 0xf]);
73 }
74 }
75 return result;
76}
77} // namespace
78
79template <class T, size_t N>
80T *array_end(T (&array)[N]) {
81 return array + N;
82}
83
84void PrintIncludes(grpc_generator::Printer *printer,
85 const std::vector<grpc::string> &headers,
86 const Parameters &params) {
87 std::map<grpc::string, grpc::string> vars;
88
89 vars["l"] = params.use_system_headers ? '<' : '"';
90 vars["r"] = params.use_system_headers ? '>' : '"';
91
92 auto &s = params.grpc_search_path;
93 if (!s.empty()) {
94 vars["l"] += s;
95 if (s[s.size() - 1] != '/') {
96 vars["l"] += '/';
97 }
98 }
99
100 for (auto i = headers.begin(); i != headers.end(); i++) {
101 vars["h"] = *i;
102 printer->Print(vars, "#include $l$$h$$r$\n");
103 }
104}
105
106grpc::string GetHeaderPrologue(grpc_generator::File *file,
107 const Parameters & /*params*/) {
108 grpc::string output;
109 {
110 // Scope the output stream so it closes and finalizes output to the string.
111 auto printer = file->CreatePrinter(&output);
112 std::map<grpc::string, grpc::string> vars;
113
114 vars["filename"] = file->filename();
115 vars["filename_identifier"] = FilenameIdentifier(file->filename());
116 vars["filename_base"] = file->filename_without_ext();
117 vars["message_header_ext"] = message_header_ext();
118
119 printer->Print(vars, "// Generated by the gRPC C++ plugin.\n");
120 printer->Print(vars,
121 "// If you make any local change, they will be lost.\n");
122 printer->Print(vars, "// source: $filename$\n");
123 grpc::string leading_comments = file->GetLeadingComments("//");
124 if (!leading_comments.empty()) {
125 printer->Print(vars, "// Original file comments:\n");
126 printer->Print(leading_comments.c_str());
127 }
128 printer->Print(vars, "#ifndef GRPC_$filename_identifier$__INCLUDED\n");
129 printer->Print(vars, "#define GRPC_$filename_identifier$__INCLUDED\n");
130 printer->Print(vars, "\n");
131 printer->Print(vars, "#include \"$filename_base$$message_header_ext$\"\n");
132 printer->Print(vars, file->additional_headers().c_str());
133 printer->Print(vars, "\n");
134 }
135 return output;
136}
137
138grpc::string GetHeaderIncludes(grpc_generator::File *file,
139 const Parameters &params) {
140 grpc::string output;
141 {
142 // Scope the output stream so it closes and finalizes output to the string.
143 auto printer = file->CreatePrinter(&output);
144 std::map<grpc::string, grpc::string> vars;
145
146 static const char *headers_strs[] = {
147 "grpc++/impl/codegen/async_stream.h",
148 "grpc++/impl/codegen/async_unary_call.h",
149 "grpc++/impl/codegen/method_handler_impl.h",
150 "grpc++/impl/codegen/proto_utils.h",
151 "grpc++/impl/codegen/rpc_method.h",
152 "grpc++/impl/codegen/service_type.h",
153 "grpc++/impl/codegen/status.h",
154 "grpc++/impl/codegen/stub_options.h",
155 "grpc++/impl/codegen/sync_stream.h"};
156 std::vector<grpc::string> headers(headers_strs, array_end(headers_strs));
157 PrintIncludes(printer.get(), headers, params);
158 printer->Print(vars, "\n");
159 printer->Print(vars, "namespace grpc {\n");
160 printer->Print(vars, "class CompletionQueue;\n");
161 printer->Print(vars, "class Channel;\n");
162 printer->Print(vars, "class ServerCompletionQueue;\n");
163 printer->Print(vars, "class ServerContext;\n");
164 printer->Print(vars, "} // namespace grpc\n\n");
165
166 if (!file->package().empty()) {
167 std::vector<grpc::string> parts = file->package_parts();
168
169 for (auto part = parts.begin(); part != parts.end(); part++) {
170 vars["part"] = *part;
171 printer->Print(vars, "namespace $part$ {\n");
172 }
173 printer->Print(vars, "\n");
174 }
175 }
176 return output;
177}
178
179void PrintHeaderClientMethodInterfaces(
180 grpc_generator::Printer *printer, const grpc_generator::Method *method,
181 std::map<grpc::string, grpc::string> *vars, bool is_public) {
182 (*vars)["Method"] = method->name();
183 (*vars)["Request"] = method->input_type_name();
184 (*vars)["Response"] = method->output_type_name();
185
186 struct {
187 grpc::string prefix;
188 grpc::string method_params; // extra arguments to method
189 grpc::string raw_args; // extra arguments to raw version of method
190 } async_prefixes[] = {{"Async", ", void* tag", ", tag"},
191 {"PrepareAsync", "", ""}};
192
193 if (is_public) {
194 if (method->NoStreaming()) {
195 printer->Print(
196 *vars,
197 "virtual ::grpc::Status $Method$(::grpc::ClientContext* context, "
198 "const $Request$& request, $Response$* response) = 0;\n");
199 for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
200 auto& async_prefix = async_prefixes[i];
201 (*vars)["AsyncPrefix"] = async_prefix.prefix;
202 printer->Print(
203 *vars,
204 "std::unique_ptr< "
205 "::grpc::ClientAsyncResponseReaderInterface< $Response$>> "
206 "$AsyncPrefix$$Method$(::grpc::ClientContext* context, "
207 "const $Request$& request, "
208 "::grpc::CompletionQueue* cq) {\n");
209 printer->Indent();
210 printer->Print(
211 *vars,
212 "return std::unique_ptr< "
213 "::grpc::ClientAsyncResponseReaderInterface< $Response$>>("
214 "$AsyncPrefix$$Method$Raw(context, request, cq));\n");
215 printer->Outdent();
216 printer->Print("}\n");
217 }
218 } else if (ClientOnlyStreaming(method)) {
219 printer->Print(
220 *vars,
221 "std::unique_ptr< ::grpc::ClientWriterInterface< $Request$>>"
222 " $Method$("
223 "::grpc::ClientContext* context, $Response$* response) {\n");
224 printer->Indent();
225 printer->Print(
226 *vars,
227 "return std::unique_ptr< ::grpc::ClientWriterInterface< $Request$>>"
228 "($Method$Raw(context, response));\n");
229 printer->Outdent();
230 printer->Print("}\n");
231 for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
232 auto& async_prefix = async_prefixes[i];
233 (*vars)["AsyncPrefix"] = async_prefix.prefix;
234 (*vars)["AsyncMethodParams"] = async_prefix.method_params;
235 (*vars)["AsyncRawArgs"] = async_prefix.raw_args;
236 printer->Print(
237 *vars,
238 "std::unique_ptr< ::grpc::ClientAsyncWriterInterface< $Request$>>"
239 " $AsyncPrefix$$Method$(::grpc::ClientContext* context, "
240 "$Response$* "
241 "response, "
242 "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
243 printer->Indent();
244 printer->Print(*vars,
245 "return std::unique_ptr< "
246 "::grpc::ClientAsyncWriterInterface< $Request$>>("
247 "$AsyncPrefix$$Method$Raw(context, response, "
248 "cq$AsyncRawArgs$));\n");
249 printer->Outdent();
250 printer->Print("}\n");
251 }
252 } else if (ServerOnlyStreaming(method)) {
253 printer->Print(
254 *vars,
255 "std::unique_ptr< ::grpc::ClientReaderInterface< $Response$>>"
256 " $Method$(::grpc::ClientContext* context, const $Request$& request)"
257 " {\n");
258 printer->Indent();
259 printer->Print(
260 *vars,
261 "return std::unique_ptr< ::grpc::ClientReaderInterface< $Response$>>"
262 "($Method$Raw(context, request));\n");
263 printer->Outdent();
264 printer->Print("}\n");
265 for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
266 auto& async_prefix = async_prefixes[i];
267 (*vars)["AsyncPrefix"] = async_prefix.prefix;
268 (*vars)["AsyncMethodParams"] = async_prefix.method_params;
269 (*vars)["AsyncRawArgs"] = async_prefix.raw_args;
270 printer->Print(
271 *vars,
272 "std::unique_ptr< ::grpc::ClientAsyncReaderInterface< $Response$>> "
273 "$AsyncPrefix$$Method$("
274 "::grpc::ClientContext* context, const $Request$& request, "
275 "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
276 printer->Indent();
277 printer->Print(
278 *vars,
279 "return std::unique_ptr< "
280 "::grpc::ClientAsyncReaderInterface< $Response$>>("
281 "$AsyncPrefix$$Method$Raw(context, request, cq$AsyncRawArgs$));\n");
282 printer->Outdent();
283 printer->Print("}\n");
284 }
285 } else if (method->BidiStreaming()) {
286 printer->Print(*vars,
287 "std::unique_ptr< ::grpc::ClientReaderWriterInterface< "
288 "$Request$, $Response$>> "
289 "$Method$(::grpc::ClientContext* context) {\n");
290 printer->Indent();
291 printer->Print(
292 *vars,
293 "return std::unique_ptr< "
294 "::grpc::ClientReaderWriterInterface< $Request$, $Response$>>("
295 "$Method$Raw(context));\n");
296 printer->Outdent();
297 printer->Print("}\n");
298 for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
299 auto& async_prefix = async_prefixes[i];
300 (*vars)["AsyncPrefix"] = async_prefix.prefix;
301 (*vars)["AsyncMethodParams"] = async_prefix.method_params;
302 (*vars)["AsyncRawArgs"] = async_prefix.raw_args;
303 printer->Print(
304 *vars,
305 "std::unique_ptr< "
306 "::grpc::ClientAsyncReaderWriterInterface< $Request$, $Response$>> "
307 "$AsyncPrefix$$Method$(::grpc::ClientContext* context, "
308 "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
309 printer->Indent();
310 printer->Print(
311 *vars,
312 "return std::unique_ptr< "
313 "::grpc::ClientAsyncReaderWriterInterface< $Request$, $Response$>>("
314 "$AsyncPrefix$$Method$Raw(context, cq$AsyncRawArgs$));\n");
315 printer->Outdent();
316 printer->Print("}\n");
317 }
318 }
319 } else {
320 if (method->NoStreaming()) {
321 for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
322 auto& async_prefix = async_prefixes[i];
323 (*vars)["AsyncPrefix"] = async_prefix.prefix;
324 printer->Print(
325 *vars,
326 "virtual ::grpc::ClientAsyncResponseReaderInterface< $Response$>* "
327 "$AsyncPrefix$$Method$Raw(::grpc::ClientContext* context, "
328 "const $Request$& request, "
329 "::grpc::CompletionQueue* cq) = 0;\n");
330 }
331 } else if (ClientOnlyStreaming(method)) {
332 printer->Print(
333 *vars,
334 "virtual ::grpc::ClientWriterInterface< $Request$>*"
335 " $Method$Raw("
336 "::grpc::ClientContext* context, $Response$* response) = 0;\n");
337 for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
338 auto& async_prefix = async_prefixes[i];
339 (*vars)["AsyncPrefix"] = async_prefix.prefix;
340 (*vars)["AsyncMethodParams"] = async_prefix.method_params;
341 printer->Print(
342 *vars,
343 "virtual ::grpc::ClientAsyncWriterInterface< $Request$>*"
344 " $AsyncPrefix$$Method$Raw(::grpc::ClientContext* context, "
345 "$Response$* response, "
346 "::grpc::CompletionQueue* cq$AsyncMethodParams$) = 0;\n");
347 }
348 } else if (ServerOnlyStreaming(method)) {
349 printer->Print(
350 *vars,
351 "virtual ::grpc::ClientReaderInterface< $Response$>* "
352 "$Method$Raw("
353 "::grpc::ClientContext* context, const $Request$& request) = 0;\n");
354 for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
355 auto& async_prefix = async_prefixes[i];
356 (*vars)["AsyncPrefix"] = async_prefix.prefix;
357 (*vars)["AsyncMethodParams"] = async_prefix.method_params;
358 printer->Print(
359 *vars,
360 "virtual ::grpc::ClientAsyncReaderInterface< $Response$>* "
361 "$AsyncPrefix$$Method$Raw("
362 "::grpc::ClientContext* context, const $Request$& request, "
363 "::grpc::CompletionQueue* cq$AsyncMethodParams$) = 0;\n");
364 }
365 } else if (method->BidiStreaming()) {
366 printer->Print(*vars,
367 "virtual ::grpc::ClientReaderWriterInterface< $Request$, "
368 "$Response$>* "
369 "$Method$Raw(::grpc::ClientContext* context) = 0;\n");
370 for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
371 auto& async_prefix = async_prefixes[i];
372 (*vars)["AsyncPrefix"] = async_prefix.prefix;
373 (*vars)["AsyncMethodParams"] = async_prefix.method_params;
374 printer->Print(
375 *vars,
376 "virtual ::grpc::ClientAsyncReaderWriterInterface< "
377 "$Request$, $Response$>* "
378 "$AsyncPrefix$$Method$Raw(::grpc::ClientContext* context, "
379 "::grpc::CompletionQueue* cq$AsyncMethodParams$) = 0;\n");
380 }
381 }
382 }
383}
384
385void PrintHeaderClientMethod(grpc_generator::Printer *printer,
386 const grpc_generator::Method *method,
387 std::map<grpc::string, grpc::string> *vars,
388 bool is_public) {
389 (*vars)["Method"] = method->name();
390 (*vars)["Request"] = method->input_type_name();
391 (*vars)["Response"] = method->output_type_name();
392 struct {
393 grpc::string prefix;
394 grpc::string method_params; // extra arguments to method
395 grpc::string raw_args; // extra arguments to raw version of method
396 } async_prefixes[] = {{"Async", ", void* tag", ", tag"},
397 {"PrepareAsync", "", ""}};
398
399 if (is_public) {
400 if (method->NoStreaming()) {
401 printer->Print(
402 *vars,
403 "::grpc::Status $Method$(::grpc::ClientContext* context, "
404 "const $Request$& request, $Response$* response) override;\n");
405 for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
406 auto& async_prefix = async_prefixes[i];
407 (*vars)["AsyncPrefix"] = async_prefix.prefix;
408 printer->Print(
409 *vars,
410 "std::unique_ptr< ::grpc::ClientAsyncResponseReader< $Response$>> "
411 "$AsyncPrefix$$Method$(::grpc::ClientContext* context, "
412 "const $Request$& request, "
413 "::grpc::CompletionQueue* cq) {\n");
414 printer->Indent();
415 printer->Print(*vars,
416 "return std::unique_ptr< "
417 "::grpc::ClientAsyncResponseReader< $Response$>>("
418 "$AsyncPrefix$$Method$Raw(context, request, cq));\n");
419 printer->Outdent();
420 printer->Print("}\n");
421 }
422 } else if (ClientOnlyStreaming(method)) {
423 printer->Print(
424 *vars,
425 "std::unique_ptr< ::grpc::ClientWriter< $Request$>>"
426 " $Method$("
427 "::grpc::ClientContext* context, $Response$* response) {\n");
428 printer->Indent();
429 printer->Print(*vars,
430 "return std::unique_ptr< ::grpc::ClientWriter< $Request$>>"
431 "($Method$Raw(context, response));\n");
432 printer->Outdent();
433 printer->Print("}\n");
434 for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
435 auto& async_prefix = async_prefixes[i];
436 (*vars)["AsyncPrefix"] = async_prefix.prefix;
437 (*vars)["AsyncMethodParams"] = async_prefix.method_params;
438 (*vars)["AsyncRawArgs"] = async_prefix.raw_args;
439 printer->Print(*vars,
440 "std::unique_ptr< ::grpc::ClientAsyncWriter< $Request$>>"
441 " $AsyncPrefix$$Method$(::grpc::ClientContext* context, "
442 "$Response$* response, "
443 "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
444 printer->Indent();
445 printer->Print(
446 *vars,
447 "return std::unique_ptr< ::grpc::ClientAsyncWriter< $Request$>>("
448 "$AsyncPrefix$$Method$Raw(context, response, "
449 "cq$AsyncRawArgs$));\n");
450 printer->Outdent();
451 printer->Print("}\n");
452 }
453 } else if (ServerOnlyStreaming(method)) {
454 printer->Print(
455 *vars,
456 "std::unique_ptr< ::grpc::ClientReader< $Response$>>"
457 " $Method$(::grpc::ClientContext* context, const $Request$& request)"
458 " {\n");
459 printer->Indent();
460 printer->Print(
461 *vars,
462 "return std::unique_ptr< ::grpc::ClientReader< $Response$>>"
463 "($Method$Raw(context, request));\n");
464 printer->Outdent();
465 printer->Print("}\n");
466 for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
467 auto& async_prefix = async_prefixes[i];
468 (*vars)["AsyncPrefix"] = async_prefix.prefix;
469 (*vars)["AsyncMethodParams"] = async_prefix.method_params;
470 (*vars)["AsyncRawArgs"] = async_prefix.raw_args;
471 printer->Print(
472 *vars,
473 "std::unique_ptr< ::grpc::ClientAsyncReader< $Response$>> "
474 "$AsyncPrefix$$Method$("
475 "::grpc::ClientContext* context, const $Request$& request, "
476 "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
477 printer->Indent();
478 printer->Print(
479 *vars,
480 "return std::unique_ptr< ::grpc::ClientAsyncReader< $Response$>>("
481 "$AsyncPrefix$$Method$Raw(context, request, cq$AsyncRawArgs$));\n");
482 printer->Outdent();
483 printer->Print("}\n");
484 }
485 } else if (method->BidiStreaming()) {
486 printer->Print(
487 *vars,
488 "std::unique_ptr< ::grpc::ClientReaderWriter< $Request$, $Response$>>"
489 " $Method$(::grpc::ClientContext* context) {\n");
490 printer->Indent();
491 printer->Print(*vars,
492 "return std::unique_ptr< "
493 "::grpc::ClientReaderWriter< $Request$, $Response$>>("
494 "$Method$Raw(context));\n");
495 printer->Outdent();
496 printer->Print("}\n");
497 for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
498 auto& async_prefix = async_prefixes[i];
499 (*vars)["AsyncPrefix"] = async_prefix.prefix;
500 (*vars)["AsyncMethodParams"] = async_prefix.method_params;
501 (*vars)["AsyncRawArgs"] = async_prefix.raw_args;
502 printer->Print(*vars,
503 "std::unique_ptr< ::grpc::ClientAsyncReaderWriter< "
504 "$Request$, $Response$>> "
505 "$AsyncPrefix$$Method$(::grpc::ClientContext* context, "
506 "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
507 printer->Indent();
508 printer->Print(
509 *vars,
510 "return std::unique_ptr< "
511 "::grpc::ClientAsyncReaderWriter< $Request$, $Response$>>("
512 "$AsyncPrefix$$Method$Raw(context, cq$AsyncRawArgs$));\n");
513 printer->Outdent();
514 printer->Print("}\n");
515 }
516 }
517 } else {
518 if (method->NoStreaming()) {
519 for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
520 auto& async_prefix = async_prefixes[i];
521 (*vars)["AsyncPrefix"] = async_prefix.prefix;
522 printer->Print(
523 *vars,
524 "::grpc::ClientAsyncResponseReader< $Response$>* "
525 "$AsyncPrefix$$Method$Raw(::grpc::ClientContext* context, "
526 "const $Request$& request, "
527 "::grpc::CompletionQueue* cq) override;\n");
528 }
529 } else if (ClientOnlyStreaming(method)) {
530 printer->Print(*vars,
531 "::grpc::ClientWriter< $Request$>* $Method$Raw("
532 "::grpc::ClientContext* context, $Response$* response) "
533 "override;\n");
534 for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
535 auto& async_prefix = async_prefixes[i];
536 (*vars)["AsyncPrefix"] = async_prefix.prefix;
537 (*vars)["AsyncMethodParams"] = async_prefix.method_params;
538 (*vars)["AsyncRawArgs"] = async_prefix.raw_args;
539 printer->Print(
540 *vars,
541 "::grpc::ClientAsyncWriter< $Request$>* $AsyncPrefix$$Method$Raw("
542 "::grpc::ClientContext* context, $Response$* response, "
543 "::grpc::CompletionQueue* cq$AsyncMethodParams$) override;\n");
544 }
545 } else if (ServerOnlyStreaming(method)) {
546 printer->Print(*vars,
547 "::grpc::ClientReader< $Response$>* $Method$Raw("
548 "::grpc::ClientContext* context, const $Request$& request)"
549 " override;\n");
550 for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
551 auto& async_prefix = async_prefixes[i];
552 (*vars)["AsyncPrefix"] = async_prefix.prefix;
553 (*vars)["AsyncMethodParams"] = async_prefix.method_params;
554 (*vars)["AsyncRawArgs"] = async_prefix.raw_args;
555 printer->Print(
556 *vars,
557 "::grpc::ClientAsyncReader< $Response$>* $AsyncPrefix$$Method$Raw("
558 "::grpc::ClientContext* context, const $Request$& request, "
559 "::grpc::CompletionQueue* cq$AsyncMethodParams$) override;\n");
560 }
561 } else if (method->BidiStreaming()) {
562 printer->Print(*vars,
563 "::grpc::ClientReaderWriter< $Request$, $Response$>* "
564 "$Method$Raw(::grpc::ClientContext* context) override;\n");
565 for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
566 auto& async_prefix = async_prefixes[i];
567 (*vars)["AsyncPrefix"] = async_prefix.prefix;
568 (*vars)["AsyncMethodParams"] = async_prefix.method_params;
569 (*vars)["AsyncRawArgs"] = async_prefix.raw_args;
570 printer->Print(
571 *vars,
572 "::grpc::ClientAsyncReaderWriter< $Request$, $Response$>* "
573 "$AsyncPrefix$$Method$Raw(::grpc::ClientContext* context, "
574 "::grpc::CompletionQueue* cq$AsyncMethodParams$) override;\n");
575 }
576 }
577 }
578}
579
580void PrintHeaderClientMethodData(grpc_generator::Printer *printer,
581 const grpc_generator::Method *method,
582 std::map<grpc::string, grpc::string> *vars) {
583 (*vars)["Method"] = method->name();
584 printer->Print(*vars,
585 "const ::grpc::internal::RpcMethod rpcmethod_$Method$_;\n");
586}
587
588void PrintHeaderServerMethodSync(grpc_generator::Printer *printer,
589 const grpc_generator::Method *method,
590 std::map<grpc::string, grpc::string> *vars) {
591 (*vars)["Method"] = method->name();
592 (*vars)["Request"] = method->input_type_name();
593 (*vars)["Response"] = method->output_type_name();
594 printer->Print(method->GetLeadingComments("//").c_str());
595 if (method->NoStreaming()) {
596 printer->Print(*vars,
597 "virtual ::grpc::Status $Method$("
598 "::grpc::ServerContext* context, const $Request$* request, "
599 "$Response$* response);\n");
600 } else if (ClientOnlyStreaming(method)) {
601 printer->Print(*vars,
602 "virtual ::grpc::Status $Method$("
603 "::grpc::ServerContext* context, "
604 "::grpc::ServerReader< $Request$>* reader, "
605 "$Response$* response);\n");
606 } else if (ServerOnlyStreaming(method)) {
607 printer->Print(*vars,
608 "virtual ::grpc::Status $Method$("
609 "::grpc::ServerContext* context, const $Request$* request, "
610 "::grpc::ServerWriter< $Response$>* writer);\n");
611 } else if (method->BidiStreaming()) {
612 printer->Print(
613 *vars,
614 "virtual ::grpc::Status $Method$("
615 "::grpc::ServerContext* context, "
616 "::grpc::ServerReaderWriter< $Response$, $Request$>* stream);"
617 "\n");
618 }
619 printer->Print(method->GetTrailingComments("//").c_str());
620}
621
622void PrintHeaderServerMethodAsync(grpc_generator::Printer *printer,
623 const grpc_generator::Method *method,
624 std::map<grpc::string, grpc::string> *vars) {
625 (*vars)["Method"] = method->name();
626 (*vars)["Request"] = method->input_type_name();
627 (*vars)["Response"] = method->output_type_name();
628 printer->Print(*vars, "template <class BaseClass>\n");
629 printer->Print(*vars,
630 "class WithAsyncMethod_$Method$ : public BaseClass {\n");
631 printer->Print(
632 " private:\n"
633 " void BaseClassMustBeDerivedFromService(const Service *service) {}\n");
634 printer->Print(" public:\n");
635 printer->Indent();
636 printer->Print(*vars,
637 "WithAsyncMethod_$Method$() {\n"
638 " ::grpc::Service::MarkMethodAsync($Idx$);\n"
639 "}\n");
640 printer->Print(*vars,
641 "~WithAsyncMethod_$Method$() override {\n"
642 " BaseClassMustBeDerivedFromService(this);\n"
643 "}\n");
644 if (method->NoStreaming()) {
645 printer->Print(
646 *vars,
647 "// disable synchronous version of this method\n"
648 "::grpc::Status $Method$("
649 "::grpc::ServerContext* context, const $Request$* request, "
650 "$Response$* response) final override {\n"
651 " abort();\n"
652 " return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
653 "}\n");
654 printer->Print(
655 *vars,
656 "void Request$Method$("
657 "::grpc::ServerContext* context, $Request$* request, "
658 "::grpc::ServerAsyncResponseWriter< $Response$>* response, "
659 "::grpc::CompletionQueue* new_call_cq, "
660 "::grpc::ServerCompletionQueue* notification_cq, void *tag) {\n");
661 printer->Print(*vars,
662 " ::grpc::Service::RequestAsyncUnary($Idx$, context, "
663 "request, response, new_call_cq, notification_cq, tag);\n");
664 printer->Print("}\n");
665 } else if (ClientOnlyStreaming(method)) {
666 printer->Print(
667 *vars,
668 "// disable synchronous version of this method\n"
669 "::grpc::Status $Method$("
670 "::grpc::ServerContext* context, "
671 "::grpc::ServerReader< $Request$>* reader, "
672 "$Response$* response) final override {\n"
673 " abort();\n"
674 " return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
675 "}\n");
676 printer->Print(
677 *vars,
678 "void Request$Method$("
679 "::grpc::ServerContext* context, "
680 "::grpc::ServerAsyncReader< $Response$, $Request$>* reader, "
681 "::grpc::CompletionQueue* new_call_cq, "
682 "::grpc::ServerCompletionQueue* notification_cq, void *tag) {\n");
683 printer->Print(*vars,
684 " ::grpc::Service::RequestAsyncClientStreaming($Idx$, "
685 "context, reader, new_call_cq, notification_cq, tag);\n");
686 printer->Print("}\n");
687 } else if (ServerOnlyStreaming(method)) {
688 printer->Print(
689 *vars,
690 "// disable synchronous version of this method\n"
691 "::grpc::Status $Method$("
692 "::grpc::ServerContext* context, const $Request$* request, "
693 "::grpc::ServerWriter< $Response$>* writer) final override "
694 "{\n"
695 " abort();\n"
696 " return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
697 "}\n");
698 printer->Print(
699 *vars,
700 "void Request$Method$("
701 "::grpc::ServerContext* context, $Request$* request, "
702 "::grpc::ServerAsyncWriter< $Response$>* writer, "
703 "::grpc::CompletionQueue* new_call_cq, "
704 "::grpc::ServerCompletionQueue* notification_cq, void *tag) {\n");
705 printer->Print(
706 *vars,
707 " ::grpc::Service::RequestAsyncServerStreaming($Idx$, "
708 "context, request, writer, new_call_cq, notification_cq, tag);\n");
709 printer->Print("}\n");
710 } else if (method->BidiStreaming()) {
711 printer->Print(
712 *vars,
713 "// disable synchronous version of this method\n"
714 "::grpc::Status $Method$("
715 "::grpc::ServerContext* context, "
716 "::grpc::ServerReaderWriter< $Response$, $Request$>* stream) "
717 "final override {\n"
718 " abort();\n"
719 " return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
720 "}\n");
721 printer->Print(
722 *vars,
723 "void Request$Method$("
724 "::grpc::ServerContext* context, "
725 "::grpc::ServerAsyncReaderWriter< $Response$, $Request$>* stream, "
726 "::grpc::CompletionQueue* new_call_cq, "
727 "::grpc::ServerCompletionQueue* notification_cq, void *tag) {\n");
728 printer->Print(*vars,
729 " ::grpc::Service::RequestAsyncBidiStreaming($Idx$, "
730 "context, stream, new_call_cq, notification_cq, tag);\n");
731 printer->Print("}\n");
732 }
733 printer->Outdent();
734 printer->Print(*vars, "};\n");
735}
736
737void PrintHeaderServerMethodStreamedUnary(
738 grpc_generator::Printer *printer, const grpc_generator::Method *method,
739 std::map<grpc::string, grpc::string> *vars) {
740 (*vars)["Method"] = method->name();
741 (*vars)["Request"] = method->input_type_name();
742 (*vars)["Response"] = method->output_type_name();
743 if (method->NoStreaming()) {
744 printer->Print(*vars, "template <class BaseClass>\n");
745 printer->Print(*vars,
746 "class WithStreamedUnaryMethod_$Method$ : "
747 "public BaseClass {\n");
748 printer->Print(
749 " private:\n"
750 " void BaseClassMustBeDerivedFromService(const Service *service) "
751 "{}\n");
752 printer->Print(" public:\n");
753 printer->Indent();
754 printer->Print(*vars,
755 "WithStreamedUnaryMethod_$Method$() {\n"
756 " ::grpc::Service::MarkMethodStreamed($Idx$,\n"
757 " new ::grpc::internal::StreamedUnaryHandler< $Request$, "
758 "$Response$>(std::bind"
759 "(&WithStreamedUnaryMethod_$Method$<BaseClass>::"
760 "Streamed$Method$, this, std::placeholders::_1, "
761 "std::placeholders::_2)));\n"
762 "}\n");
763 printer->Print(*vars,
764 "~WithStreamedUnaryMethod_$Method$() override {\n"
765 " BaseClassMustBeDerivedFromService(this);\n"
766 "}\n");
767 printer->Print(
768 *vars,
769 "// disable regular version of this method\n"
770 "::grpc::Status $Method$("
771 "::grpc::ServerContext* context, const $Request$* request, "
772 "$Response$* response) final override {\n"
773 " abort();\n"
774 " return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
775 "}\n");
776 printer->Print(*vars,
777 "// replace default version of method with streamed unary\n"
778 "virtual ::grpc::Status Streamed$Method$("
779 "::grpc::ServerContext* context, "
780 "::grpc::ServerUnaryStreamer< "
781 "$Request$,$Response$>* server_unary_streamer)"
782 " = 0;\n");
783 printer->Outdent();
784 printer->Print(*vars, "};\n");
785 }
786}
787
788void PrintHeaderServerMethodSplitStreaming(
789 grpc_generator::Printer *printer, const grpc_generator::Method *method,
790 std::map<grpc::string, grpc::string> *vars) {
791 (*vars)["Method"] = method->name();
792 (*vars)["Request"] = method->input_type_name();
793 (*vars)["Response"] = method->output_type_name();
794 if (ServerOnlyStreaming(method)) {
795 printer->Print(*vars, "template <class BaseClass>\n");
796 printer->Print(*vars,
797 "class WithSplitStreamingMethod_$Method$ : "
798 "public BaseClass {\n");
799 printer->Print(
800 " private:\n"
801 " void BaseClassMustBeDerivedFromService(const Service *service) "
802 "{}\n");
803 printer->Print(" public:\n");
804 printer->Indent();
805 printer->Print(
806 *vars,
807 "WithSplitStreamingMethod_$Method$() {\n"
808 " ::grpc::Service::MarkMethodStreamed($Idx$,\n"
809 " new ::grpc::internal::SplitServerStreamingHandler< $Request$, "
810 "$Response$>(std::bind"
811 "(&WithSplitStreamingMethod_$Method$<BaseClass>::"
812 "Streamed$Method$, this, std::placeholders::_1, "
813 "std::placeholders::_2)));\n"
814 "}\n");
815 printer->Print(*vars,
816 "~WithSplitStreamingMethod_$Method$() override {\n"
817 " BaseClassMustBeDerivedFromService(this);\n"
818 "}\n");
819 printer->Print(
820 *vars,
821 "// disable regular version of this method\n"
822 "::grpc::Status $Method$("
823 "::grpc::ServerContext* context, const $Request$* request, "
824 "::grpc::ServerWriter< $Response$>* writer) final override "
825 "{\n"
826 " abort();\n"
827 " return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
828 "}\n");
829 printer->Print(*vars,
830 "// replace default version of method with split streamed\n"
831 "virtual ::grpc::Status Streamed$Method$("
832 "::grpc::ServerContext* context, "
833 "::grpc::ServerSplitStreamer< "
834 "$Request$,$Response$>* server_split_streamer)"
835 " = 0;\n");
836 printer->Outdent();
837 printer->Print(*vars, "};\n");
838 }
839}
840
841void PrintHeaderServerMethodGeneric(
842 grpc_generator::Printer *printer, const grpc_generator::Method *method,
843 std::map<grpc::string, grpc::string> *vars) {
844 (*vars)["Method"] = method->name();
845 (*vars)["Request"] = method->input_type_name();
846 (*vars)["Response"] = method->output_type_name();
847 printer->Print(*vars, "template <class BaseClass>\n");
848 printer->Print(*vars,
849 "class WithGenericMethod_$Method$ : public BaseClass {\n");
850 printer->Print(
851 " private:\n"
852 " void BaseClassMustBeDerivedFromService(const Service *service) {}\n");
853 printer->Print(" public:\n");
854 printer->Indent();
855 printer->Print(*vars,
856 "WithGenericMethod_$Method$() {\n"
857 " ::grpc::Service::MarkMethodGeneric($Idx$);\n"
858 "}\n");
859 printer->Print(*vars,
860 "~WithGenericMethod_$Method$() override {\n"
861 " BaseClassMustBeDerivedFromService(this);\n"
862 "}\n");
863 if (method->NoStreaming()) {
864 printer->Print(
865 *vars,
866 "// disable synchronous version of this method\n"
867 "::grpc::Status $Method$("
868 "::grpc::ServerContext* context, const $Request$* request, "
869 "$Response$* response) final override {\n"
870 " abort();\n"
871 " return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
872 "}\n");
873 } else if (ClientOnlyStreaming(method)) {
874 printer->Print(
875 *vars,
876 "// disable synchronous version of this method\n"
877 "::grpc::Status $Method$("
878 "::grpc::ServerContext* context, "
879 "::grpc::ServerReader< $Request$>* reader, "
880 "$Response$* response) final override {\n"
881 " abort();\n"
882 " return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
883 "}\n");
884 } else if (ServerOnlyStreaming(method)) {
885 printer->Print(
886 *vars,
887 "// disable synchronous version of this method\n"
888 "::grpc::Status $Method$("
889 "::grpc::ServerContext* context, const $Request$* request, "
890 "::grpc::ServerWriter< $Response$>* writer) final override "
891 "{\n"
892 " abort();\n"
893 " return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
894 "}\n");
895 } else if (method->BidiStreaming()) {
896 printer->Print(
897 *vars,
898 "// disable synchronous version of this method\n"
899 "::grpc::Status $Method$("
900 "::grpc::ServerContext* context, "
901 "::grpc::ServerReaderWriter< $Response$, $Request$>* stream) "
902 "final override {\n"
903 " abort();\n"
904 " return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
905 "}\n");
906 }
907 printer->Outdent();
908 printer->Print(*vars, "};\n");
909}
910
911void PrintHeaderService(grpc_generator::Printer *printer,
912 const grpc_generator::Service *service,
913 std::map<grpc::string, grpc::string> *vars) {
914 (*vars)["Service"] = service->name();
915
916 printer->Print(service->GetLeadingComments("//").c_str());
917 printer->Print(*vars,
918 "class $Service$ final {\n"
919 " public:\n");
920 printer->Indent();
921
922 // Service metadata
923 printer->Print(*vars,
924 "static constexpr char const* service_full_name() {\n"
925 " return \"$Package$$Service$\";\n"
926 "}\n");
927
928 // Client side
929 printer->Print(
930 "class StubInterface {\n"
931 " public:\n");
932 printer->Indent();
933 printer->Print("virtual ~StubInterface() {}\n");
934 for (int i = 0; i < service->method_count(); ++i) {
935 printer->Print(service->method(i)->GetLeadingComments("//").c_str());
936 PrintHeaderClientMethodInterfaces(printer, service->method(i).get(), vars,
937 true);
938 printer->Print(service->method(i)->GetTrailingComments("//").c_str());
939 }
940 printer->Outdent();
941 printer->Print("private:\n");
942 printer->Indent();
943 for (int i = 0; i < service->method_count(); ++i) {
944 PrintHeaderClientMethodInterfaces(printer, service->method(i).get(), vars,
945 false);
946 }
947 printer->Outdent();
948 printer->Print("};\n");
949 printer->Print(
950 "class Stub final : public StubInterface"
951 " {\n public:\n");
952 printer->Indent();
953 printer->Print(
954 "Stub(const std::shared_ptr< ::grpc::ChannelInterface>& "
955 "channel);\n");
956 for (int i = 0; i < service->method_count(); ++i) {
957 PrintHeaderClientMethod(printer, service->method(i).get(), vars, true);
958 }
959 printer->Outdent();
960 printer->Print("\n private:\n");
961 printer->Indent();
962 printer->Print("std::shared_ptr< ::grpc::ChannelInterface> channel_;\n");
963 for (int i = 0; i < service->method_count(); ++i) {
964 PrintHeaderClientMethod(printer, service->method(i).get(), vars, false);
965 }
966 for (int i = 0; i < service->method_count(); ++i) {
967 PrintHeaderClientMethodData(printer, service->method(i).get(), vars);
968 }
969 printer->Outdent();
970 printer->Print("};\n");
971 printer->Print(
972 "static std::unique_ptr<Stub> NewStub(const std::shared_ptr< "
973 "::grpc::ChannelInterface>& channel, "
974 "const ::grpc::StubOptions& options = ::grpc::StubOptions());\n");
975
976 printer->Print("\n");
977
978 // Server side - base
979 printer->Print(
980 "class Service : public ::grpc::Service {\n"
981 " public:\n");
982 printer->Indent();
983 printer->Print("Service();\n");
984 printer->Print("virtual ~Service();\n");
985 for (int i = 0; i < service->method_count(); ++i) {
986 PrintHeaderServerMethodSync(printer, service->method(i).get(), vars);
987 }
988 printer->Outdent();
989 printer->Print("};\n");
990
991 // Server side - Asynchronous
992 for (int i = 0; i < service->method_count(); ++i) {
993 (*vars)["Idx"] = as_string(i);
994 PrintHeaderServerMethodAsync(printer, service->method(i).get(), vars);
995 }
996
997 printer->Print("typedef ");
998
999 for (int i = 0; i < service->method_count(); ++i) {
1000 (*vars)["method_name"] = service->method(i).get()->name();
1001 printer->Print(*vars, "WithAsyncMethod_$method_name$<");
1002 }
1003 printer->Print("Service");
1004 for (int i = 0; i < service->method_count(); ++i) {
1005 printer->Print(" >");
1006 }
1007 printer->Print(" AsyncService;\n");
1008
1009 // Server side - Generic
1010 for (int i = 0; i < service->method_count(); ++i) {
1011 (*vars)["Idx"] = as_string(i);
1012 PrintHeaderServerMethodGeneric(printer, service->method(i).get(), vars);
1013 }
1014
1015 // Server side - Streamed Unary
1016 for (int i = 0; i < service->method_count(); ++i) {
1017 (*vars)["Idx"] = as_string(i);
1018 PrintHeaderServerMethodStreamedUnary(printer, service->method(i).get(),
1019 vars);
1020 }
1021
1022 printer->Print("typedef ");
1023 for (int i = 0; i < service->method_count(); ++i) {
1024 (*vars)["method_name"] = service->method(i).get()->name();
1025 if (service->method(i)->NoStreaming()) {
1026 printer->Print(*vars, "WithStreamedUnaryMethod_$method_name$<");
1027 }
1028 }
1029 printer->Print("Service");
1030 for (int i = 0; i < service->method_count(); ++i) {
1031 if (service->method(i)->NoStreaming()) {
1032 printer->Print(" >");
1033 }
1034 }
1035 printer->Print(" StreamedUnaryService;\n");
1036
1037 // Server side - controlled server-side streaming
1038 for (int i = 0; i < service->method_count(); ++i) {
1039 (*vars)["Idx"] = as_string(i);
1040 PrintHeaderServerMethodSplitStreaming(printer, service->method(i).get(),
1041 vars);
1042 }
1043
1044 printer->Print("typedef ");
1045 for (int i = 0; i < service->method_count(); ++i) {
1046 (*vars)["method_name"] = service->method(i).get()->name();
1047 auto method = service->method(i);
1048 if (ServerOnlyStreaming(method.get())) {
1049 printer->Print(*vars, "WithSplitStreamingMethod_$method_name$<");
1050 }
1051 }
1052 printer->Print("Service");
1053 for (int i = 0; i < service->method_count(); ++i) {
1054 auto method = service->method(i);
1055 if (ServerOnlyStreaming(method.get())) {
1056 printer->Print(" >");
1057 }
1058 }
1059 printer->Print(" SplitStreamedService;\n");
1060
1061 // Server side - typedef for controlled both unary and server-side streaming
1062 printer->Print("typedef ");
1063 for (int i = 0; i < service->method_count(); ++i) {
1064 (*vars)["method_name"] = service->method(i).get()->name();
1065 auto method = service->method(i);
1066 if (ServerOnlyStreaming(method.get())) {
1067 printer->Print(*vars, "WithSplitStreamingMethod_$method_name$<");
1068 }
1069 if (service->method(i)->NoStreaming()) {
1070 printer->Print(*vars, "WithStreamedUnaryMethod_$method_name$<");
1071 }
1072 }
1073 printer->Print("Service");
1074 for (int i = 0; i < service->method_count(); ++i) {
1075 auto method = service->method(i);
1076 if (service->method(i)->NoStreaming() ||
1077 ServerOnlyStreaming(method.get())) {
1078 printer->Print(" >");
1079 }
1080 }
1081 printer->Print(" StreamedService;\n");
1082
1083 printer->Outdent();
1084 printer->Print("};\n");
1085 printer->Print(service->GetTrailingComments("//").c_str());
1086}
1087
1088grpc::string GetHeaderServices(grpc_generator::File *file,
1089 const Parameters &params) {
1090 grpc::string output;
1091 {
1092 // Scope the output stream so it closes and finalizes output to the string.
1093 auto printer = file->CreatePrinter(&output);
1094 std::map<grpc::string, grpc::string> vars;
1095 // Package string is empty or ends with a dot. It is used to fully qualify
1096 // method names.
1097 vars["Package"] = file->package();
1098 if (!file->package().empty()) {
1099 vars["Package"].append(".");
1100 }
1101
1102 if (!params.services_namespace.empty()) {
1103 vars["services_namespace"] = params.services_namespace;
1104 printer->Print(vars, "\nnamespace $services_namespace$ {\n\n");
1105 }
1106
1107 for (int i = 0; i < file->service_count(); ++i) {
1108 PrintHeaderService(printer.get(), file->service(i).get(), &vars);
1109 printer->Print("\n");
1110 }
1111
1112 if (!params.services_namespace.empty()) {
1113 printer->Print(vars, "} // namespace $services_namespace$\n\n");
1114 }
1115 }
1116 return output;
1117}
1118
1119grpc::string GetHeaderEpilogue(grpc_generator::File *file,
1120 const Parameters & /*params*/) {
1121 grpc::string output;
1122 {
1123 // Scope the output stream so it closes and finalizes output to the string.
1124 auto printer = file->CreatePrinter(&output);
1125 std::map<grpc::string, grpc::string> vars;
1126
1127 vars["filename"] = file->filename();
1128 vars["filename_identifier"] = FilenameIdentifier(file->filename());
1129
1130 if (!file->package().empty()) {
1131 std::vector<grpc::string> parts = file->package_parts();
1132
1133 for (auto part = parts.rbegin(); part != parts.rend(); part++) {
1134 vars["part"] = *part;
1135 printer->Print(vars, "} // namespace $part$\n");
1136 }
1137 printer->Print(vars, "\n");
1138 }
1139
1140 printer->Print(vars, "\n");
1141 printer->Print(vars, "#endif // GRPC_$filename_identifier$__INCLUDED\n");
1142
1143 printer->Print(file->GetTrailingComments("//").c_str());
1144 }
1145 return output;
1146}
1147
1148grpc::string GetSourcePrologue(grpc_generator::File *file,
1149 const Parameters & /*params*/) {
1150 grpc::string output;
1151 {
1152 // Scope the output stream so it closes and finalizes output to the string.
1153 auto printer = file->CreatePrinter(&output);
1154 std::map<grpc::string, grpc::string> vars;
1155
1156 vars["filename"] = file->filename();
1157 vars["filename_base"] = file->filename_without_ext();
1158 vars["message_header_ext"] = message_header_ext();
1159 vars["service_header_ext"] = service_header_ext();
1160
1161 printer->Print(vars, "// Generated by the gRPC C++ plugin.\n");
1162 printer->Print(vars,
1163 "// If you make any local change, they will be lost.\n");
1164 printer->Print(vars, "// source: $filename$\n\n");
1165
1166 printer->Print(vars, "#include \"$filename_base$$message_header_ext$\"\n");
1167 printer->Print(vars, "#include \"$filename_base$$service_header_ext$\"\n");
1168 printer->Print(vars, "\n");
1169 }
1170 return output;
1171}
1172
1173grpc::string GetSourceIncludes(grpc_generator::File *file,
1174 const Parameters &params) {
1175 grpc::string output;
1176 {
1177 // Scope the output stream so it closes and finalizes output to the string.
1178 auto printer = file->CreatePrinter(&output);
1179 std::map<grpc::string, grpc::string> vars;
1180
1181 static const char *headers_strs[] = {
1182 "grpc++/impl/codegen/async_stream.h",
1183 "grpc++/impl/codegen/async_unary_call.h",
1184 "grpc++/impl/codegen/channel_interface.h",
1185 "grpc++/impl/codegen/client_unary_call.h",
1186 "grpc++/impl/codegen/method_handler_impl.h",
1187 "grpc++/impl/codegen/rpc_service_method.h",
1188 "grpc++/impl/codegen/service_type.h",
1189 "grpc++/impl/codegen/sync_stream.h"};
1190 std::vector<grpc::string> headers(headers_strs, array_end(headers_strs));
1191 PrintIncludes(printer.get(), headers, params);
1192
1193 if (!file->package().empty()) {
1194 std::vector<grpc::string> parts = file->package_parts();
1195
1196 for (auto part = parts.begin(); part != parts.end(); part++) {
1197 vars["part"] = *part;
1198 printer->Print(vars, "namespace $part$ {\n");
1199 }
1200 }
1201
1202 printer->Print(vars, "\n");
1203 }
1204 return output;
1205}
1206
1207void PrintSourceClientMethod(grpc_generator::Printer *printer,
1208 const grpc_generator::Method *method,
1209 std::map<grpc::string, grpc::string> *vars) {
1210 (*vars)["Method"] = method->name();
1211 (*vars)["Request"] = method->input_type_name();
1212 (*vars)["Response"] = method->output_type_name();
1213 struct {
1214 grpc::string prefix;
1215 grpc::string start; // bool literal expressed as string
1216 grpc::string method_params; // extra arguments to method
1217 grpc::string create_args; // extra arguments to creator
1218 } async_prefixes[] = {{"Async", "true", ", void* tag", ", tag"},
1219 {"PrepareAsync", "false", "", ", nullptr"}};
1220 if (method->NoStreaming()) {
1221 printer->Print(*vars,
1222 "::grpc::Status $ns$$Service$::Stub::$Method$("
1223 "::grpc::ClientContext* context, "
1224 "const $Request$& request, $Response$* response) {\n");
1225 printer->Print(*vars,
1226 " return ::grpc::internal::BlockingUnaryCall"
1227 "(channel_.get(), rpcmethod_$Method$_, "
1228 "context, request, response);\n}\n\n");
1229 for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
1230 auto& async_prefix = async_prefixes[i];
1231 (*vars)["AsyncPrefix"] = async_prefix.prefix;
1232 (*vars)["AsyncStart"] = async_prefix.start;
1233 printer->Print(*vars,
1234 "::grpc::ClientAsyncResponseReader< $Response$>* "
1235 "$ns$$Service$::Stub::$AsyncPrefix$$Method$Raw(::grpc::"
1236 "ClientContext* context, "
1237 "const $Request$& request, "
1238 "::grpc::CompletionQueue* cq) {\n");
1239 printer->Print(
1240 *vars,
1241 " return "
1242 "::grpc::internal::ClientAsyncResponseReaderFactory< $Response$>"
1243 "::Create(channel_.get(), cq, "
1244 "rpcmethod_$Method$_, "
1245 "context, request, $AsyncStart$);\n"
1246 "}\n\n");
1247 }
1248 } else if (ClientOnlyStreaming(method)) {
1249 printer->Print(*vars,
1250 "::grpc::ClientWriter< $Request$>* "
1251 "$ns$$Service$::Stub::$Method$Raw("
1252 "::grpc::ClientContext* context, $Response$* response) {\n");
1253 printer->Print(
1254 *vars,
1255 " return ::grpc::internal::ClientWriterFactory< $Request$>::Create("
1256 "channel_.get(), "
1257 "rpcmethod_$Method$_, "
1258 "context, response);\n"
1259 "}\n\n");
1260 for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
1261 auto& async_prefix = async_prefixes[i];
1262 (*vars)["AsyncPrefix"] = async_prefix.prefix;
1263 (*vars)["AsyncStart"] = async_prefix.start;
1264 (*vars)["AsyncMethodParams"] = async_prefix.method_params;
1265 (*vars)["AsyncCreateArgs"] = async_prefix.create_args;
1266 printer->Print(*vars,
1267 "::grpc::ClientAsyncWriter< $Request$>* "
1268 "$ns$$Service$::Stub::$AsyncPrefix$$Method$Raw("
1269 "::grpc::ClientContext* context, $Response$* response, "
1270 "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
1271 printer->Print(
1272 *vars,
1273 " return ::grpc::internal::ClientAsyncWriterFactory< $Request$>"
1274 "::Create(channel_.get(), cq, "
1275 "rpcmethod_$Method$_, "
1276 "context, response, $AsyncStart$$AsyncCreateArgs$);\n"
1277 "}\n\n");
1278 }
1279 } else if (ServerOnlyStreaming(method)) {
1280 printer->Print(
1281 *vars,
1282 "::grpc::ClientReader< $Response$>* "
1283 "$ns$$Service$::Stub::$Method$Raw("
1284 "::grpc::ClientContext* context, const $Request$& request) {\n");
1285 printer->Print(
1286 *vars,
1287 " return ::grpc::internal::ClientReaderFactory< $Response$>::Create("
1288 "channel_.get(), "
1289 "rpcmethod_$Method$_, "
1290 "context, request);\n"
1291 "}\n\n");
1292 for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
1293 auto& async_prefix = async_prefixes[i];
1294 (*vars)["AsyncPrefix"] = async_prefix.prefix;
1295 (*vars)["AsyncStart"] = async_prefix.start;
1296 (*vars)["AsyncMethodParams"] = async_prefix.method_params;
1297 (*vars)["AsyncCreateArgs"] = async_prefix.create_args;
1298 printer->Print(
1299 *vars,
1300 "::grpc::ClientAsyncReader< $Response$>* "
1301 "$ns$$Service$::Stub::$AsyncPrefix$$Method$Raw("
1302 "::grpc::ClientContext* context, const $Request$& request, "
1303 "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
1304 printer->Print(
1305 *vars,
1306 " return ::grpc::internal::ClientAsyncReaderFactory< $Response$>"
1307 "::Create(channel_.get(), cq, "
1308 "rpcmethod_$Method$_, "
1309 "context, request, $AsyncStart$$AsyncCreateArgs$);\n"
1310 "}\n\n");
1311 }
1312 } else if (method->BidiStreaming()) {
1313 printer->Print(
1314 *vars,
1315 "::grpc::ClientReaderWriter< $Request$, $Response$>* "
1316 "$ns$$Service$::Stub::$Method$Raw(::grpc::ClientContext* context) {\n");
1317 printer->Print(*vars,
1318 " return ::grpc::internal::ClientReaderWriterFactory< "
1319 "$Request$, $Response$>::Create("
1320 "channel_.get(), "
1321 "rpcmethod_$Method$_, "
1322 "context);\n"
1323 "}\n\n");
1324 for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
1325 auto& async_prefix = async_prefixes[i];
1326 (*vars)["AsyncPrefix"] = async_prefix.prefix;
1327 (*vars)["AsyncStart"] = async_prefix.start;
1328 (*vars)["AsyncMethodParams"] = async_prefix.method_params;
1329 (*vars)["AsyncCreateArgs"] = async_prefix.create_args;
1330 printer->Print(*vars,
1331 "::grpc::ClientAsyncReaderWriter< $Request$, $Response$>* "
1332 "$ns$$Service$::Stub::$AsyncPrefix$$Method$Raw(::grpc::"
1333 "ClientContext* context, "
1334 "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
1335 printer->Print(*vars,
1336 " return "
1337 "::grpc::internal::ClientAsyncReaderWriterFactory< "
1338 "$Request$, $Response$>::Create("
1339 "channel_.get(), cq, "
1340 "rpcmethod_$Method$_, "
1341 "context, $AsyncStart$$AsyncCreateArgs$);\n"
1342 "}\n\n");
1343 }
1344 }
1345}
1346
1347void PrintSourceServerMethod(grpc_generator::Printer *printer,
1348 const grpc_generator::Method *method,
1349 std::map<grpc::string, grpc::string> *vars) {
1350 (*vars)["Method"] = method->name();
1351 (*vars)["Request"] = method->input_type_name();
1352 (*vars)["Response"] = method->output_type_name();
1353 if (method->NoStreaming()) {
1354 printer->Print(*vars,
1355 "::grpc::Status $ns$$Service$::Service::$Method$("
1356 "::grpc::ServerContext* context, "
1357 "const $Request$* request, $Response$* response) {\n");
1358 printer->Print(" (void) context;\n");
1359 printer->Print(" (void) request;\n");
1360 printer->Print(" (void) response;\n");
1361 printer->Print(
1362 " return ::grpc::Status("
1363 "::grpc::StatusCode::UNIMPLEMENTED, \"\");\n");
1364 printer->Print("}\n\n");
1365 } else if (ClientOnlyStreaming(method)) {
1366 printer->Print(*vars,
1367 "::grpc::Status $ns$$Service$::Service::$Method$("
1368 "::grpc::ServerContext* context, "
1369 "::grpc::ServerReader< $Request$>* reader, "
1370 "$Response$* response) {\n");
1371 printer->Print(" (void) context;\n");
1372 printer->Print(" (void) reader;\n");
1373 printer->Print(" (void) response;\n");
1374 printer->Print(
1375 " return ::grpc::Status("
1376 "::grpc::StatusCode::UNIMPLEMENTED, \"\");\n");
1377 printer->Print("}\n\n");
1378 } else if (ServerOnlyStreaming(method)) {
1379 printer->Print(*vars,
1380 "::grpc::Status $ns$$Service$::Service::$Method$("
1381 "::grpc::ServerContext* context, "
1382 "const $Request$* request, "
1383 "::grpc::ServerWriter< $Response$>* writer) {\n");
1384 printer->Print(" (void) context;\n");
1385 printer->Print(" (void) request;\n");
1386 printer->Print(" (void) writer;\n");
1387 printer->Print(
1388 " return ::grpc::Status("
1389 "::grpc::StatusCode::UNIMPLEMENTED, \"\");\n");
1390 printer->Print("}\n\n");
1391 } else if (method->BidiStreaming()) {
1392 printer->Print(*vars,
1393 "::grpc::Status $ns$$Service$::Service::$Method$("
1394 "::grpc::ServerContext* context, "
1395 "::grpc::ServerReaderWriter< $Response$, $Request$>* "
1396 "stream) {\n");
1397 printer->Print(" (void) context;\n");
1398 printer->Print(" (void) stream;\n");
1399 printer->Print(
1400 " return ::grpc::Status("
1401 "::grpc::StatusCode::UNIMPLEMENTED, \"\");\n");
1402 printer->Print("}\n\n");
1403 }
1404}
1405
1406void PrintSourceService(grpc_generator::Printer *printer,
1407 const grpc_generator::Service *service,
1408 std::map<grpc::string, grpc::string> *vars) {
1409 (*vars)["Service"] = service->name();
1410
1411 if (service->method_count() > 0) {
1412 printer->Print(*vars,
1413 "static const char* $prefix$$Service$_method_names[] = {\n");
1414 for (int i = 0; i < service->method_count(); ++i) {
1415 (*vars)["Method"] = service->method(i).get()->name();
1416 printer->Print(*vars, " \"/$Package$$Service$/$Method$\",\n");
1417 }
1418 printer->Print(*vars, "};\n\n");
1419 }
1420
1421 printer->Print(*vars,
1422 "std::unique_ptr< $ns$$Service$::Stub> $ns$$Service$::NewStub("
1423 "const std::shared_ptr< ::grpc::ChannelInterface>& channel, "
1424 "const ::grpc::StubOptions& options) {\n"
1425 " std::unique_ptr< $ns$$Service$::Stub> stub(new "
1426 "$ns$$Service$::Stub(channel));\n"
1427 " return stub;\n"
1428 "}\n\n");
1429 printer->Print(*vars,
1430 "$ns$$Service$::Stub::Stub(const std::shared_ptr< "
1431 "::grpc::ChannelInterface>& channel)\n");
1432 printer->Indent();
1433 printer->Print(": channel_(channel)");
1434 for (int i = 0; i < service->method_count(); ++i) {
1435 auto method = service->method(i);
1436 (*vars)["Method"] = method->name();
1437 (*vars)["Idx"] = as_string(i);
1438 if (method->NoStreaming()) {
1439 (*vars)["StreamingType"] = "NORMAL_RPC";
1440 // NOTE: There is no reason to consider streamed-unary as a separate
1441 // category here since this part is setting up the client-side stub
1442 // and this appears as a NORMAL_RPC from the client-side.
1443 } else if (ClientOnlyStreaming(method.get())) {
1444 (*vars)["StreamingType"] = "CLIENT_STREAMING";
1445 } else if (ServerOnlyStreaming(method.get())) {
1446 (*vars)["StreamingType"] = "SERVER_STREAMING";
1447 } else {
1448 (*vars)["StreamingType"] = "BIDI_STREAMING";
1449 }
1450 printer->Print(*vars,
1451 ", rpcmethod_$Method$_("
1452 "$prefix$$Service$_method_names[$Idx$], "
1453 "::grpc::internal::RpcMethod::$StreamingType$, "
1454 "channel"
1455 ")\n");
1456 }
1457 printer->Print("{}\n\n");
1458 printer->Outdent();
1459
1460 for (int i = 0; i < service->method_count(); ++i) {
1461 (*vars)["Idx"] = as_string(i);
1462 PrintSourceClientMethod(printer, service->method(i).get(), vars);
1463 }
1464
1465 printer->Print(*vars, "$ns$$Service$::Service::Service() {\n");
1466 printer->Indent();
1467 for (int i = 0; i < service->method_count(); ++i) {
1468 auto method = service->method(i);
1469 (*vars)["Idx"] = as_string(i);
1470 (*vars)["Method"] = method->name();
1471 (*vars)["Request"] = method->input_type_name();
1472 (*vars)["Response"] = method->output_type_name();
1473 if (method->NoStreaming()) {
1474 printer->Print(
1475 *vars,
1476 "AddMethod(new ::grpc::internal::RpcServiceMethod(\n"
1477 " $prefix$$Service$_method_names[$Idx$],\n"
1478 " ::grpc::internal::RpcMethod::NORMAL_RPC,\n"
1479 " new ::grpc::internal::RpcMethodHandler< $ns$$Service$::Service, "
1480 "$Request$, "
1481 "$Response$>(\n"
1482 " std::mem_fn(&$ns$$Service$::Service::$Method$), this)));\n");
1483 } else if (ClientOnlyStreaming(method.get())) {
1484 printer->Print(
1485 *vars,
1486 "AddMethod(new ::grpc::internal::RpcServiceMethod(\n"
1487 " $prefix$$Service$_method_names[$Idx$],\n"
1488 " ::grpc::internal::RpcMethod::CLIENT_STREAMING,\n"
1489 " new ::grpc::internal::ClientStreamingHandler< "
1490 "$ns$$Service$::Service, $Request$, $Response$>(\n"
1491 " std::mem_fn(&$ns$$Service$::Service::$Method$), this)));\n");
1492 } else if (ServerOnlyStreaming(method.get())) {
1493 printer->Print(
1494 *vars,
1495 "AddMethod(new ::grpc::internal::RpcServiceMethod(\n"
1496 " $prefix$$Service$_method_names[$Idx$],\n"
1497 " ::grpc::internal::RpcMethod::SERVER_STREAMING,\n"
1498 " new ::grpc::internal::ServerStreamingHandler< "
1499 "$ns$$Service$::Service, $Request$, $Response$>(\n"
1500 " std::mem_fn(&$ns$$Service$::Service::$Method$), this)));\n");
1501 } else if (method->BidiStreaming()) {
1502 printer->Print(
1503 *vars,
1504 "AddMethod(new ::grpc::internal::RpcServiceMethod(\n"
1505 " $prefix$$Service$_method_names[$Idx$],\n"
1506 " ::grpc::internal::RpcMethod::BIDI_STREAMING,\n"
1507 " new ::grpc::internal::BidiStreamingHandler< "
1508 "$ns$$Service$::Service, $Request$, $Response$>(\n"
1509 " std::mem_fn(&$ns$$Service$::Service::$Method$), this)));\n");
1510 }
1511 }
1512 printer->Outdent();
1513 printer->Print(*vars, "}\n\n");
1514 printer->Print(*vars,
1515 "$ns$$Service$::Service::~Service() {\n"
1516 "}\n\n");
1517 for (int i = 0; i < service->method_count(); ++i) {
1518 (*vars)["Idx"] = as_string(i);
1519 PrintSourceServerMethod(printer, service->method(i).get(), vars);
1520 }
1521}
1522
1523grpc::string GetSourceServices(grpc_generator::File *file,
1524 const Parameters &params) {
1525 grpc::string output;
1526 {
1527 // Scope the output stream so it closes and finalizes output to the string.
1528 auto printer = file->CreatePrinter(&output);
1529 std::map<grpc::string, grpc::string> vars;
1530 // Package string is empty or ends with a dot. It is used to fully qualify
1531 // method names.
1532 vars["Package"] = file->package();
1533 if (!file->package().empty()) {
1534 vars["Package"].append(".");
1535 }
1536 if (!params.services_namespace.empty()) {
1537 vars["ns"] = params.services_namespace + "::";
1538 vars["prefix"] = params.services_namespace;
1539 } else {
1540 vars["ns"] = "";
1541 vars["prefix"] = "";
1542 }
1543
1544 for (int i = 0; i < file->service_count(); ++i) {
1545 PrintSourceService(printer.get(), file->service(i).get(), &vars);
1546 printer->Print("\n");
1547 }
1548 }
1549 return output;
1550}
1551
1552grpc::string GetSourceEpilogue(grpc_generator::File *file,
1553 const Parameters & /*params*/) {
1554 grpc::string temp;
1555
1556 if (!file->package().empty()) {
1557 std::vector<grpc::string> parts = file->package_parts();
1558
1559 for (auto part = parts.begin(); part != parts.end(); part++) {
1560 temp.append("} // namespace ");
1561 temp.append(*part);
1562 temp.append("\n");
1563 }
1564 temp.append("\n");
1565 }
1566
1567 return temp;
1568}
1569
1570// TODO(mmukhi): Make sure we need parameters or not.
1571grpc::string GetMockPrologue(grpc_generator::File *file,
1572 const Parameters & /*params*/) {
1573 grpc::string output;
1574 {
1575 // Scope the output stream so it closes and finalizes output to the string.
1576 auto printer = file->CreatePrinter(&output);
1577 std::map<grpc::string, grpc::string> vars;
1578
1579 vars["filename"] = file->filename();
1580 vars["filename_base"] = file->filename_without_ext();
1581 vars["message_header_ext"] = message_header_ext();
1582 vars["service_header_ext"] = service_header_ext();
1583
1584 printer->Print(vars, "// Generated by the gRPC C++ plugin.\n");
1585 printer->Print(vars,
1586 "// If you make any local change, they will be lost.\n");
1587 printer->Print(vars, "// source: $filename$\n\n");
1588
1589 printer->Print(vars, "#include \"$filename_base$$message_header_ext$\"\n");
1590 printer->Print(vars, "#include \"$filename_base$$service_header_ext$\"\n");
1591 printer->Print(vars, file->additional_headers().c_str());
1592 printer->Print(vars, "\n");
1593 }
1594 return output;
1595}
1596
1597// TODO(mmukhi): Add client-stream and completion-queue headers.
1598grpc::string GetMockIncludes(grpc_generator::File *file,
1599 const Parameters &params) {
1600 grpc::string output;
1601 {
1602 // Scope the output stream so it closes and finalizes output to the string.
1603 auto printer = file->CreatePrinter(&output);
1604 std::map<grpc::string, grpc::string> vars;
1605
1606 static const char *headers_strs[] = {
1607 "grpc++/impl/codegen/async_stream.h",
1608 "grpc++/impl/codegen/sync_stream.h",
1609 "gmock/gmock.h",
1610 };
1611 std::vector<grpc::string> headers(headers_strs, array_end(headers_strs));
1612 PrintIncludes(printer.get(), headers, params);
1613
1614 if (!file->package().empty()) {
1615 std::vector<grpc::string> parts = file->package_parts();
1616
1617 for (auto part = parts.begin(); part != parts.end(); part++) {
1618 vars["part"] = *part;
1619 printer->Print(vars, "namespace $part$ {\n");
1620 }
1621 }
1622
1623 printer->Print(vars, "\n");
1624 }
1625 return output;
1626}
1627
1628void PrintMockClientMethods(grpc_generator::Printer *printer,
1629 const grpc_generator::Method *method,
1630 std::map<grpc::string, grpc::string> *vars) {
1631 (*vars)["Method"] = method->name();
1632 (*vars)["Request"] = method->input_type_name();
1633 (*vars)["Response"] = method->output_type_name();
1634
1635 struct {
1636 grpc::string prefix;
1637 grpc::string method_params; // extra arguments to method
1638 int extra_method_param_count;
1639 } async_prefixes[] = {{"Async", ", void* tag", 1}, {"PrepareAsync", "", 0}};
1640
1641 if (method->NoStreaming()) {
1642 printer->Print(
1643 *vars,
1644 "MOCK_METHOD3($Method$, ::grpc::Status(::grpc::ClientContext* context, "
1645 "const $Request$& request, $Response$* response));\n");
1646 for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
1647 auto& async_prefix = async_prefixes[i];
1648 (*vars)["AsyncPrefix"] = async_prefix.prefix;
1649 printer->Print(
1650 *vars,
1651 "MOCK_METHOD3($AsyncPrefix$$Method$Raw, "
1652 "::grpc::ClientAsyncResponseReaderInterface< $Response$>*"
1653 "(::grpc::ClientContext* context, const $Request$& request, "
1654 "::grpc::CompletionQueue* cq));\n");
1655 }
1656 } else if (ClientOnlyStreaming(method)) {
1657 printer->Print(
1658 *vars,
1659 "MOCK_METHOD2($Method$Raw, "
1660 "::grpc::ClientWriterInterface< $Request$>*"
1661 "(::grpc::ClientContext* context, $Response$* response));\n");
1662 for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
1663 auto& async_prefix = async_prefixes[i];
1664 (*vars)["AsyncPrefix"] = async_prefix.prefix;
1665 (*vars)["AsyncMethodParams"] = async_prefix.method_params;
1666 (*vars)["MockArgs"] =
1667 flatbuffers::NumToString(3 + async_prefix.extra_method_param_count);
1668 printer->Print(*vars,
1669 "MOCK_METHOD$MockArgs$($AsyncPrefix$$Method$Raw, "
1670 "::grpc::ClientAsyncWriterInterface< $Request$>*"
1671 "(::grpc::ClientContext* context, $Response$* response, "
1672 "::grpc::CompletionQueue* cq$AsyncMethodParams$));\n");
1673 }
1674 } else if (ServerOnlyStreaming(method)) {
1675 printer->Print(
1676 *vars,
1677 "MOCK_METHOD2($Method$Raw, "
1678 "::grpc::ClientReaderInterface< $Response$>*"
1679 "(::grpc::ClientContext* context, const $Request$& request));\n");
1680 for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
1681 auto& async_prefix = async_prefixes[i];
1682 (*vars)["AsyncPrefix"] = async_prefix.prefix;
1683 (*vars)["AsyncMethodParams"] = async_prefix.method_params;
1684 (*vars)["MockArgs"] =
1685 flatbuffers::NumToString(3 + async_prefix.extra_method_param_count);
1686 printer->Print(
1687 *vars,
1688 "MOCK_METHOD$MockArgs$($AsyncPrefix$$Method$Raw, "
1689 "::grpc::ClientAsyncReaderInterface< $Response$>*"
1690 "(::grpc::ClientContext* context, const $Request$& request, "
1691 "::grpc::CompletionQueue* cq$AsyncMethodParams$));\n");
1692 }
1693 } else if (method->BidiStreaming()) {
1694 printer->Print(
1695 *vars,
1696 "MOCK_METHOD1($Method$Raw, "
1697 "::grpc::ClientReaderWriterInterface< $Request$, $Response$>*"
1698 "(::grpc::ClientContext* context));\n");
1699 for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
1700 auto& async_prefix = async_prefixes[i];
1701 (*vars)["AsyncPrefix"] = async_prefix.prefix;
1702 (*vars)["AsyncMethodParams"] = async_prefix.method_params;
1703 (*vars)["MockArgs"] =
1704 flatbuffers::NumToString(2 + async_prefix.extra_method_param_count);
1705 printer->Print(
1706 *vars,
1707 "MOCK_METHOD$MockArgs$($AsyncPrefix$$Method$Raw, "
1708 "::grpc::ClientAsyncReaderWriterInterface<$Request$, $Response$>*"
1709 "(::grpc::ClientContext* context, ::grpc::CompletionQueue* cq"
1710 "$AsyncMethodParams$));\n");
1711 }
1712 }
1713}
1714
1715void PrintMockService(grpc_generator::Printer *printer,
1716 const grpc_generator::Service *service,
1717 std::map<grpc::string, grpc::string> *vars) {
1718 (*vars)["Service"] = service->name();
1719
1720 printer->Print(*vars,
1721 "class Mock$Service$Stub : public $Service$::StubInterface {\n"
1722 " public:\n");
1723 printer->Indent();
1724 for (int i = 0; i < service->method_count(); ++i) {
1725 PrintMockClientMethods(printer, service->method(i).get(), vars);
1726 }
1727 printer->Outdent();
1728 printer->Print("};\n");
1729}
1730
1731grpc::string GetMockServices(grpc_generator::File *file,
1732 const Parameters &params) {
1733 grpc::string output;
1734 {
1735 // Scope the output stream so it closes and finalizes output to the string.
1736 auto printer = file->CreatePrinter(&output);
1737 std::map<grpc::string, grpc::string> vars;
1738 // Package string is empty or ends with a dot. It is used to fully qualify
1739 // method names.
1740 vars["Package"] = file->package();
1741 if (!file->package().empty()) {
1742 vars["Package"].append(".");
1743 }
1744
1745 if (!params.services_namespace.empty()) {
1746 vars["services_namespace"] = params.services_namespace;
1747 printer->Print(vars, "\nnamespace $services_namespace$ {\n\n");
1748 }
1749
1750 for (int i = 0; i < file->service_count(); i++) {
1751 PrintMockService(printer.get(), file->service(i).get(), &vars);
1752 printer->Print("\n");
1753 }
1754
1755 if (!params.services_namespace.empty()) {
1756 printer->Print(vars, "} // namespace $services_namespace$\n\n");
1757 }
1758 }
1759 return output;
1760}
1761
1762grpc::string GetMockEpilogue(grpc_generator::File *file,
1763 const Parameters & /*params*/) {
1764 grpc::string temp;
1765
1766 if (!file->package().empty()) {
1767 std::vector<grpc::string> parts = file->package_parts();
1768
1769 for (auto part = parts.begin(); part != parts.end(); part++) {
1770 temp.append("} // namespace ");
1771 temp.append(*part);
1772 temp.append("\n");
1773 }
1774 temp.append("\n");
1775 }
1776
1777 return temp;
1778}
1779
1780} // namespace grpc_cpp_generator
1781