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
38#include <sstream>
39
40namespace grpc_cpp_generator {
41namespace {
42
43template <class T>
44grpc::string as_string(T x) {
45  std::ostringstream out;
46  out << x;
47  return out.str();
48}
49
50grpc::string FilenameIdentifier(const grpc::string &filename) {
51  grpc::string result;
52  for (unsigned i = 0; i < filename.size(); i++) {
53    char c = filename[i];
54    if (isalnum(c)) {
55      result.push_back(c);
56    } else {
57      static char hex[] = "0123456789abcdef";
58      result.push_back('_');
59      result.push_back(hex[(c >> 4) & 0xf]);
60      result.push_back(hex[c & 0xf]);
61    }
62  }
63  return result;
64}
65}  // namespace
66
67template<class T, size_t N>
68T *array_end(T (&array)[N]) { return array + N; }
69
70void PrintIncludes(grpc_generator::Printer *printer,
71                   const std::vector<grpc::string>& headers, const Parameters &params) {
72  std::map<grpc::string, grpc::string> vars;
73
74  vars["l"] = params.use_system_headers ? '<' : '"';
75  vars["r"] = params.use_system_headers ? '>' : '"';
76
77  if (!params.grpc_search_path.empty()) {
78    vars["l"] += params.grpc_search_path;
79    if (params.grpc_search_path.back() != '/') {
80      vars["l"] += '/';
81    }
82  }
83
84  for (auto i = headers.begin(); i != headers.end(); i++) {
85    vars["h"] = *i;
86    printer->Print(vars, "#include $l$$h$$r$\n");
87  }
88}
89
90grpc::string GetHeaderPrologue(grpc_generator::File *file, const Parameters & /*params*/) {
91  grpc::string output;
92  {
93    // Scope the output stream so it closes and finalizes output to the string.
94    auto printer = file->CreatePrinter(&output);
95    std::map<grpc::string, grpc::string> vars;
96
97    vars["filename"] = file->filename();
98    vars["filename_identifier"] = FilenameIdentifier(file->filename());
99    vars["filename_base"] = file->filename_without_ext();
100    vars["message_header_ext"] = file->message_header_ext();
101
102    printer->Print(vars, "// Generated by the gRPC protobuf plugin.\n");
103    printer->Print(vars,
104                  "// If you make any local change, they will be lost.\n");
105    printer->Print(vars, "// source: $filename$\n");
106    printer->Print(vars, "#ifndef GRPC_$filename_identifier$__INCLUDED\n");
107    printer->Print(vars, "#define GRPC_$filename_identifier$__INCLUDED\n");
108    printer->Print(vars, "\n");
109    printer->Print(vars, "#include \"$filename_base$$message_header_ext$\"\n");
110    printer->Print(vars, file->additional_headers().c_str());
111    printer->Print(vars, "\n");
112  }
113  return output;
114}
115
116grpc::string GetHeaderIncludes(grpc_generator::File *file,
117                               const Parameters &params) {
118  grpc::string output;
119  {
120    // Scope the output stream so it closes and finalizes output to the string.
121    auto printer = file->CreatePrinter(&output);
122    std::map<grpc::string, grpc::string> vars;
123
124    static const char *headers_strs[] = {
125      "grpc++/impl/codegen/async_stream.h",
126      "grpc++/impl/codegen/async_unary_call.h",
127      "grpc++/impl/codegen/rpc_method.h",
128      "grpc++/impl/codegen/service_type.h",
129      "grpc++/impl/codegen/status.h",
130      "grpc++/impl/codegen/stub_options.h",
131      "grpc++/impl/codegen/sync_stream.h"
132    };
133    std::vector<grpc::string> headers(headers_strs, array_end(headers_strs));
134    PrintIncludes(printer.get(), headers, params);
135    printer->Print(vars, "\n");
136    printer->Print(vars, "namespace grpc {\n");
137    printer->Print(vars, "class CompletionQueue;\n");
138    printer->Print(vars, "class Channel;\n");
139    printer->Print(vars, "class RpcService;\n");
140    printer->Print(vars, "class ServerCompletionQueue;\n");
141    printer->Print(vars, "class ServerContext;\n");
142    printer->Print(vars, "}  // namespace grpc\n\n");
143
144    if (!file->package().empty()) {
145      std::vector<grpc::string> parts = file->package_parts();
146
147      for (auto part = parts.begin(); part != parts.end(); part++) {
148        vars["part"] = *part;
149        printer->Print(vars, "namespace $part$ {\n");
150      }
151      printer->Print(vars, "\n");
152    }
153  }
154  return output;
155}
156
157void PrintHeaderClientMethodInterfaces(
158    grpc_generator::Printer *printer, const grpc_generator::Method *method,
159    std::map<grpc::string, grpc::string> *vars, bool is_public) {
160  (*vars)["Method"] = method->name();
161  (*vars)["Request"] = method->input_type_name();
162  (*vars)["Response"] = method->output_type_name();
163
164  if (is_public) {
165    if (method->NoStreaming()) {
166      printer->Print(
167          *vars,
168          "virtual ::grpc::Status $Method$(::grpc::ClientContext* context, "
169          "const $Request$& request, $Response$* response) = 0;\n");
170      printer->Print(*vars,
171                     "std::unique_ptr< "
172                     "::grpc::ClientAsyncResponseReaderInterface< $Response$>> "
173                     "Async$Method$(::grpc::ClientContext* context, "
174                     "const $Request$& request, "
175                     "::grpc::CompletionQueue* cq) {\n");
176      printer->Indent();
177      printer->Print(*vars,
178                     "return std::unique_ptr< "
179                     "::grpc::ClientAsyncResponseReaderInterface< $Response$>>("
180                     "Async$Method$Raw(context, request, cq));\n");
181      printer->Outdent();
182      printer->Print("}\n");
183    } else if (method->ClientOnlyStreaming()) {
184      printer->Print(
185          *vars,
186          "std::unique_ptr< ::grpc::ClientWriterInterface< $Request$>>"
187          " $Method$("
188          "::grpc::ClientContext* context, $Response$* response) {\n");
189      printer->Indent();
190      printer->Print(
191          *vars,
192          "return std::unique_ptr< ::grpc::ClientWriterInterface< $Request$>>"
193          "($Method$Raw(context, response));\n");
194      printer->Outdent();
195      printer->Print("}\n");
196      printer->Print(
197          *vars,
198          "std::unique_ptr< ::grpc::ClientAsyncWriterInterface< $Request$>>"
199          " Async$Method$(::grpc::ClientContext* context, $Response$* "
200          "response, "
201          "::grpc::CompletionQueue* cq, void* tag) {\n");
202      printer->Indent();
203      printer->Print(*vars,
204                     "return std::unique_ptr< "
205                     "::grpc::ClientAsyncWriterInterface< $Request$>>("
206                     "Async$Method$Raw(context, response, cq, tag));\n");
207      printer->Outdent();
208      printer->Print("}\n");
209    } else if (method->ServerOnlyStreaming()) {
210      printer->Print(
211          *vars,
212          "std::unique_ptr< ::grpc::ClientReaderInterface< $Response$>>"
213          " $Method$(::grpc::ClientContext* context, const $Request$& request)"
214          " {\n");
215      printer->Indent();
216      printer->Print(
217          *vars,
218          "return std::unique_ptr< ::grpc::ClientReaderInterface< $Response$>>"
219          "($Method$Raw(context, request));\n");
220      printer->Outdent();
221      printer->Print("}\n");
222      printer->Print(
223          *vars,
224          "std::unique_ptr< ::grpc::ClientAsyncReaderInterface< $Response$>> "
225          "Async$Method$("
226          "::grpc::ClientContext* context, const $Request$& request, "
227          "::grpc::CompletionQueue* cq, void* tag) {\n");
228      printer->Indent();
229      printer->Print(*vars,
230                     "return std::unique_ptr< "
231                     "::grpc::ClientAsyncReaderInterface< $Response$>>("
232                     "Async$Method$Raw(context, request, cq, tag));\n");
233      printer->Outdent();
234      printer->Print("}\n");
235    } else if (method->BidiStreaming()) {
236      printer->Print(*vars,
237                     "std::unique_ptr< ::grpc::ClientReaderWriterInterface< "
238                     "$Request$, $Response$>> "
239                     "$Method$(::grpc::ClientContext* context) {\n");
240      printer->Indent();
241      printer->Print(
242          *vars,
243          "return std::unique_ptr< "
244          "::grpc::ClientReaderWriterInterface< $Request$, $Response$>>("
245          "$Method$Raw(context));\n");
246      printer->Outdent();
247      printer->Print("}\n");
248      printer->Print(
249          *vars,
250          "std::unique_ptr< "
251          "::grpc::ClientAsyncReaderWriterInterface< $Request$, $Response$>> "
252          "Async$Method$(::grpc::ClientContext* context, "
253          "::grpc::CompletionQueue* cq, void* tag) {\n");
254      printer->Indent();
255      printer->Print(
256          *vars,
257          "return std::unique_ptr< "
258          "::grpc::ClientAsyncReaderWriterInterface< $Request$, $Response$>>("
259          "Async$Method$Raw(context, cq, tag));\n");
260      printer->Outdent();
261      printer->Print("}\n");
262    }
263  } else {
264    if (method->NoStreaming()) {
265      printer->Print(
266          *vars,
267          "virtual ::grpc::ClientAsyncResponseReaderInterface< $Response$>* "
268          "Async$Method$Raw(::grpc::ClientContext* context, "
269          "const $Request$& request, "
270          "::grpc::CompletionQueue* cq) = 0;\n");
271    } else if (method->ClientOnlyStreaming()) {
272      printer->Print(
273          *vars,
274          "virtual ::grpc::ClientWriterInterface< $Request$>*"
275          " $Method$Raw("
276          "::grpc::ClientContext* context, $Response$* response) = 0;\n");
277      printer->Print(*vars,
278                     "virtual ::grpc::ClientAsyncWriterInterface< $Request$>*"
279                     " Async$Method$Raw(::grpc::ClientContext* context, "
280                     "$Response$* response, "
281                     "::grpc::CompletionQueue* cq, void* tag) = 0;\n");
282    } else if (method->ServerOnlyStreaming()) {
283      printer->Print(
284          *vars,
285          "virtual ::grpc::ClientReaderInterface< $Response$>* $Method$Raw("
286          "::grpc::ClientContext* context, const $Request$& request) = 0;\n");
287      printer->Print(
288          *vars,
289          "virtual ::grpc::ClientAsyncReaderInterface< $Response$>* "
290          "Async$Method$Raw("
291          "::grpc::ClientContext* context, const $Request$& request, "
292          "::grpc::CompletionQueue* cq, void* tag) = 0;\n");
293    } else if (method->BidiStreaming()) {
294      printer->Print(*vars,
295                     "virtual ::grpc::ClientReaderWriterInterface< $Request$, "
296                     "$Response$>* "
297                     "$Method$Raw(::grpc::ClientContext* context) = 0;\n");
298      printer->Print(*vars,
299                     "virtual ::grpc::ClientAsyncReaderWriterInterface< "
300                     "$Request$, $Response$>* "
301                     "Async$Method$Raw(::grpc::ClientContext* context, "
302                     "::grpc::CompletionQueue* cq, void* tag) = 0;\n");
303    }
304  }
305}
306
307void PrintHeaderClientMethod(grpc_generator::Printer *printer,
308                             const grpc_generator::Method *method,
309                             std::map<grpc::string, grpc::string> *vars,
310                             bool is_public) {
311  (*vars)["Method"] = method->name();
312  (*vars)["Request"] = method->input_type_name();
313  (*vars)["Response"] = method->output_type_name();
314  if (is_public) {
315    if (method->NoStreaming()) {
316      printer->Print(
317          *vars,
318          "::grpc::Status $Method$(::grpc::ClientContext* context, "
319          "const $Request$& request, $Response$* response) GRPC_OVERRIDE;\n");
320      printer->Print(
321          *vars,
322          "std::unique_ptr< ::grpc::ClientAsyncResponseReader< $Response$>> "
323          "Async$Method$(::grpc::ClientContext* context, "
324          "const $Request$& request, "
325          "::grpc::CompletionQueue* cq) {\n");
326      printer->Indent();
327      printer->Print(*vars,
328                     "return std::unique_ptr< "
329                     "::grpc::ClientAsyncResponseReader< $Response$>>("
330                     "Async$Method$Raw(context, request, cq));\n");
331      printer->Outdent();
332      printer->Print("}\n");
333    } else if (method->ClientOnlyStreaming()) {
334      printer->Print(
335          *vars,
336          "std::unique_ptr< ::grpc::ClientWriter< $Request$>>"
337          " $Method$("
338          "::grpc::ClientContext* context, $Response$* response) {\n");
339      printer->Indent();
340      printer->Print(*vars,
341                     "return std::unique_ptr< ::grpc::ClientWriter< $Request$>>"
342                     "($Method$Raw(context, response));\n");
343      printer->Outdent();
344      printer->Print("}\n");
345      printer->Print(*vars,
346                     "std::unique_ptr< ::grpc::ClientAsyncWriter< $Request$>>"
347                     " Async$Method$(::grpc::ClientContext* context, "
348                     "$Response$* response, "
349                     "::grpc::CompletionQueue* cq, void* tag) {\n");
350      printer->Indent();
351      printer->Print(
352          *vars,
353          "return std::unique_ptr< ::grpc::ClientAsyncWriter< $Request$>>("
354          "Async$Method$Raw(context, response, cq, tag));\n");
355      printer->Outdent();
356      printer->Print("}\n");
357    } else if (method->ServerOnlyStreaming()) {
358      printer->Print(
359          *vars,
360          "std::unique_ptr< ::grpc::ClientReader< $Response$>>"
361          " $Method$(::grpc::ClientContext* context, const $Request$& request)"
362          " {\n");
363      printer->Indent();
364      printer->Print(
365          *vars,
366          "return std::unique_ptr< ::grpc::ClientReader< $Response$>>"
367          "($Method$Raw(context, request));\n");
368      printer->Outdent();
369      printer->Print("}\n");
370      printer->Print(
371          *vars,
372          "std::unique_ptr< ::grpc::ClientAsyncReader< $Response$>> "
373          "Async$Method$("
374          "::grpc::ClientContext* context, const $Request$& request, "
375          "::grpc::CompletionQueue* cq, void* tag) {\n");
376      printer->Indent();
377      printer->Print(
378          *vars,
379          "return std::unique_ptr< ::grpc::ClientAsyncReader< $Response$>>("
380          "Async$Method$Raw(context, request, cq, tag));\n");
381      printer->Outdent();
382      printer->Print("}\n");
383    } else if (method->BidiStreaming()) {
384      printer->Print(
385          *vars,
386          "std::unique_ptr< ::grpc::ClientReaderWriter< $Request$, $Response$>>"
387          " $Method$(::grpc::ClientContext* context) {\n");
388      printer->Indent();
389      printer->Print(*vars,
390                     "return std::unique_ptr< "
391                     "::grpc::ClientReaderWriter< $Request$, $Response$>>("
392                     "$Method$Raw(context));\n");
393      printer->Outdent();
394      printer->Print("}\n");
395      printer->Print(*vars,
396                     "std::unique_ptr<  ::grpc::ClientAsyncReaderWriter< "
397                     "$Request$, $Response$>> "
398                     "Async$Method$(::grpc::ClientContext* context, "
399                     "::grpc::CompletionQueue* cq, void* tag) {\n");
400      printer->Indent();
401      printer->Print(*vars,
402                     "return std::unique_ptr< "
403                     "::grpc::ClientAsyncReaderWriter< $Request$, $Response$>>("
404                     "Async$Method$Raw(context, cq, tag));\n");
405      printer->Outdent();
406      printer->Print("}\n");
407    }
408  } else {
409    if (method->NoStreaming()) {
410      printer->Print(*vars,
411                     "::grpc::ClientAsyncResponseReader< $Response$>* "
412                     "Async$Method$Raw(::grpc::ClientContext* context, "
413                     "const $Request$& request, "
414                     "::grpc::CompletionQueue* cq) GRPC_OVERRIDE;\n");
415    } else if (method->ClientOnlyStreaming()) {
416      printer->Print(*vars,
417                     "::grpc::ClientWriter< $Request$>* $Method$Raw("
418                     "::grpc::ClientContext* context, $Response$* response) "
419                     "GRPC_OVERRIDE;\n");
420      printer->Print(
421          *vars,
422          "::grpc::ClientAsyncWriter< $Request$>* Async$Method$Raw("
423          "::grpc::ClientContext* context, $Response$* response, "
424          "::grpc::CompletionQueue* cq, void* tag) GRPC_OVERRIDE;\n");
425    } else if (method->ServerOnlyStreaming()) {
426      printer->Print(*vars,
427                     "::grpc::ClientReader< $Response$>* $Method$Raw("
428                     "::grpc::ClientContext* context, const $Request$& request)"
429                     " GRPC_OVERRIDE;\n");
430      printer->Print(
431          *vars,
432          "::grpc::ClientAsyncReader< $Response$>* Async$Method$Raw("
433          "::grpc::ClientContext* context, const $Request$& request, "
434          "::grpc::CompletionQueue* cq, void* tag) GRPC_OVERRIDE;\n");
435    } else if (method->BidiStreaming()) {
436      printer->Print(
437          *vars,
438          "::grpc::ClientReaderWriter< $Request$, $Response$>* "
439          "$Method$Raw(::grpc::ClientContext* context) GRPC_OVERRIDE;\n");
440      printer->Print(
441          *vars,
442          "::grpc::ClientAsyncReaderWriter< $Request$, $Response$>* "
443          "Async$Method$Raw(::grpc::ClientContext* context, "
444          "::grpc::CompletionQueue* cq, void* tag) GRPC_OVERRIDE;\n");
445    }
446  }
447}
448
449void PrintHeaderClientMethodData(grpc_generator::Printer *printer, const grpc_generator::Method *method,
450                                 std::map<grpc::string, grpc::string> *vars) {
451  (*vars)["Method"] = method->name();
452  printer->Print(*vars, "const ::grpc::RpcMethod rpcmethod_$Method$_;\n");
453}
454
455void PrintHeaderServerMethodSync(grpc_generator::Printer *printer, const grpc_generator::Method *method,
456                                 std::map<grpc::string, grpc::string> *vars) {
457  (*vars)["Method"] = method->name();
458  (*vars)["Request"] = method->input_type_name();
459  (*vars)["Response"] = method->output_type_name();
460  if (method->NoStreaming()) {
461    printer->Print(*vars,
462                   "virtual ::grpc::Status $Method$("
463                   "::grpc::ServerContext* context, const $Request$* request, "
464                   "$Response$* response);\n");
465  } else if (method->ClientOnlyStreaming()) {
466    printer->Print(*vars,
467                   "virtual ::grpc::Status $Method$("
468                   "::grpc::ServerContext* context, "
469                   "::grpc::ServerReader< $Request$>* reader, "
470                   "$Response$* response);\n");
471  } else if (method->ServerOnlyStreaming()) {
472    printer->Print(*vars,
473                   "virtual ::grpc::Status $Method$("
474                   "::grpc::ServerContext* context, const $Request$* request, "
475                   "::grpc::ServerWriter< $Response$>* writer);\n");
476  } else if (method->BidiStreaming()) {
477    printer->Print(
478        *vars,
479        "virtual ::grpc::Status $Method$("
480        "::grpc::ServerContext* context, "
481        "::grpc::ServerReaderWriter< $Response$, $Request$>* stream);"
482        "\n");
483  }
484}
485
486void PrintHeaderServerMethodAsync(
487    grpc_generator::Printer *printer,
488    const grpc_generator::Method *method,
489    std::map<grpc::string, grpc::string> *vars) {
490  (*vars)["Method"] = method->name();
491  (*vars)["Request"] = method->input_type_name();
492  (*vars)["Response"] = method->output_type_name();
493  printer->Print(*vars, "template <class BaseClass>\n");
494  printer->Print(*vars,
495                 "class WithAsyncMethod_$Method$ : public BaseClass {\n");
496  printer->Print(
497      " private:\n"
498      "  void BaseClassMustBeDerivedFromService(const Service *service) {}\n");
499  printer->Print(" public:\n");
500  printer->Indent();
501  printer->Print(*vars,
502                 "WithAsyncMethod_$Method$() {\n"
503                 "  ::grpc::Service::MarkMethodAsync($Idx$);\n"
504                 "}\n");
505  printer->Print(*vars,
506                 "~WithAsyncMethod_$Method$() GRPC_OVERRIDE {\n"
507                 "  BaseClassMustBeDerivedFromService(this);\n"
508                 "}\n");
509  if (method->NoStreaming()) {
510    printer->Print(
511        *vars,
512        "// disable synchronous version of this method\n"
513        "::grpc::Status $Method$("
514        "::grpc::ServerContext* context, const $Request$* request, "
515        "$Response$* response) GRPC_FINAL GRPC_OVERRIDE {\n"
516        "  abort();\n"
517        "  return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
518        "}\n");
519    printer->Print(
520        *vars,
521        "void Request$Method$("
522        "::grpc::ServerContext* context, $Request$* request, "
523        "::grpc::ServerAsyncResponseWriter< $Response$>* response, "
524        "::grpc::CompletionQueue* new_call_cq, "
525        "::grpc::ServerCompletionQueue* notification_cq, void *tag) {\n");
526    printer->Print(*vars,
527                   "  ::grpc::Service::RequestAsyncUnary($Idx$, context, "
528                   "request, response, new_call_cq, notification_cq, tag);\n");
529    printer->Print("}\n");
530  } else if (method->ClientOnlyStreaming()) {
531    printer->Print(
532        *vars,
533        "// disable synchronous version of this method\n"
534        "::grpc::Status $Method$("
535        "::grpc::ServerContext* context, "
536        "::grpc::ServerReader< $Request$>* reader, "
537        "$Response$* response) GRPC_FINAL GRPC_OVERRIDE {\n"
538        "  abort();\n"
539        "  return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
540        "}\n");
541    printer->Print(
542        *vars,
543        "void Request$Method$("
544        "::grpc::ServerContext* context, "
545        "::grpc::ServerAsyncReader< $Response$, $Request$>* reader, "
546        "::grpc::CompletionQueue* new_call_cq, "
547        "::grpc::ServerCompletionQueue* notification_cq, void *tag) {\n");
548    printer->Print(*vars,
549                   "  ::grpc::Service::RequestAsyncClientStreaming($Idx$, "
550                   "context, reader, new_call_cq, notification_cq, tag);\n");
551    printer->Print("}\n");
552  } else if (method->ServerOnlyStreaming()) {
553    printer->Print(
554        *vars,
555        "// disable synchronous version of this method\n"
556        "::grpc::Status $Method$("
557        "::grpc::ServerContext* context, const $Request$* request, "
558        "::grpc::ServerWriter< $Response$>* writer) GRPC_FINAL GRPC_OVERRIDE "
559        "{\n"
560        "  abort();\n"
561        "  return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
562        "}\n");
563    printer->Print(
564        *vars,
565        "void Request$Method$("
566        "::grpc::ServerContext* context, $Request$* request, "
567        "::grpc::ServerAsyncWriter< $Response$>* writer, "
568        "::grpc::CompletionQueue* new_call_cq, "
569        "::grpc::ServerCompletionQueue* notification_cq, void *tag) {\n");
570    printer->Print(
571        *vars,
572        "  ::grpc::Service::RequestAsyncServerStreaming($Idx$, "
573        "context, request, writer, new_call_cq, notification_cq, tag);\n");
574    printer->Print("}\n");
575  } else if (method->BidiStreaming()) {
576    printer->Print(
577        *vars,
578        "// disable synchronous version of this method\n"
579        "::grpc::Status $Method$("
580        "::grpc::ServerContext* context, "
581        "::grpc::ServerReaderWriter< $Response$, $Request$>* stream) "
582        "GRPC_FINAL GRPC_OVERRIDE {\n"
583        "  abort();\n"
584        "  return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
585        "}\n");
586    printer->Print(
587        *vars,
588        "void Request$Method$("
589        "::grpc::ServerContext* context, "
590        "::grpc::ServerAsyncReaderWriter< $Response$, $Request$>* stream, "
591        "::grpc::CompletionQueue* new_call_cq, "
592        "::grpc::ServerCompletionQueue* notification_cq, void *tag) {\n");
593    printer->Print(*vars,
594                   "  ::grpc::Service::RequestAsyncBidiStreaming($Idx$, "
595                   "context, stream, new_call_cq, notification_cq, tag);\n");
596    printer->Print("}\n");
597  }
598  printer->Outdent();
599  printer->Print(*vars, "};\n");
600}
601
602void PrintHeaderServerMethodGeneric(
603    grpc_generator::Printer *printer,
604    const grpc_generator::Method *method,
605    std::map<grpc::string, grpc::string> *vars) {
606  (*vars)["Method"] = method->name();
607  (*vars)["Request"] = method->input_type_name();
608  (*vars)["Response"] = method->output_type_name();
609  printer->Print(*vars, "template <class BaseClass>\n");
610  printer->Print(*vars,
611                 "class WithGenericMethod_$Method$ : public BaseClass {\n");
612  printer->Print(
613      " private:\n"
614      "  void BaseClassMustBeDerivedFromService(const Service *service) {}\n");
615  printer->Print(" public:\n");
616  printer->Indent();
617  printer->Print(*vars,
618                 "WithGenericMethod_$Method$() {\n"
619                 "  ::grpc::Service::MarkMethodGeneric($Idx$);\n"
620                 "}\n");
621  printer->Print(*vars,
622                 "~WithGenericMethod_$Method$() GRPC_OVERRIDE {\n"
623                 "  BaseClassMustBeDerivedFromService(this);\n"
624                 "}\n");
625  if (method->NoStreaming()) {
626    printer->Print(
627        *vars,
628        "// disable synchronous version of this method\n"
629        "::grpc::Status $Method$("
630        "::grpc::ServerContext* context, const $Request$* request, "
631        "$Response$* response) GRPC_FINAL GRPC_OVERRIDE {\n"
632        "  abort();\n"
633        "  return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
634        "}\n");
635  } else if (method->ClientOnlyStreaming()) {
636    printer->Print(
637        *vars,
638        "// disable synchronous version of this method\n"
639        "::grpc::Status $Method$("
640        "::grpc::ServerContext* context, "
641        "::grpc::ServerReader< $Request$>* reader, "
642        "$Response$* response) GRPC_FINAL GRPC_OVERRIDE {\n"
643        "  abort();\n"
644        "  return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
645        "}\n");
646  } else if (method->ServerOnlyStreaming()) {
647    printer->Print(
648        *vars,
649        "// disable synchronous version of this method\n"
650        "::grpc::Status $Method$("
651        "::grpc::ServerContext* context, const $Request$* request, "
652        "::grpc::ServerWriter< $Response$>* writer) GRPC_FINAL GRPC_OVERRIDE "
653        "{\n"
654        "  abort();\n"
655        "  return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
656        "}\n");
657  } else if (method->BidiStreaming()) {
658    printer->Print(
659        *vars,
660        "// disable synchronous version of this method\n"
661        "::grpc::Status $Method$("
662        "::grpc::ServerContext* context, "
663        "::grpc::ServerReaderWriter< $Response$, $Request$>* stream) "
664        "GRPC_FINAL GRPC_OVERRIDE {\n"
665        "  abort();\n"
666        "  return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
667        "}\n");
668  }
669  printer->Outdent();
670  printer->Print(*vars, "};\n");
671}
672
673void PrintHeaderService(grpc_generator::Printer *printer,
674                        const grpc_generator::Service *service,
675                        std::map<grpc::string, grpc::string> *vars) {
676  (*vars)["Service"] = service->name();
677
678  printer->Print(*vars,
679                 "class $Service$ GRPC_FINAL {\n"
680                 " public:\n");
681  printer->Indent();
682
683  // Client side
684  printer->Print(
685      "class StubInterface {\n"
686      " public:\n");
687  printer->Indent();
688  printer->Print("virtual ~StubInterface() {}\n");
689  for (int i = 0; i < service->method_count(); ++i) {
690    PrintHeaderClientMethodInterfaces(printer, service->method(i).get(), vars, true);
691  }
692  printer->Outdent();
693  printer->Print("private:\n");
694  printer->Indent();
695  for (int i = 0; i < service->method_count(); ++i) {
696    PrintHeaderClientMethodInterfaces(printer, service->method(i).get(), vars, false);
697  }
698  printer->Outdent();
699  printer->Print("};\n");
700  printer->Print(
701      "class Stub GRPC_FINAL : public StubInterface"
702      " {\n public:\n");
703  printer->Indent();
704  printer->Print("Stub(const std::shared_ptr< ::grpc::ChannelInterface>& channel);\n");
705  for (int i = 0; i < service->method_count(); ++i) {
706    PrintHeaderClientMethod(printer, service->method(i).get(), vars, true);
707  }
708  printer->Outdent();
709  printer->Print("\n private:\n");
710  printer->Indent();
711  printer->Print("std::shared_ptr< ::grpc::ChannelInterface> channel_;\n");
712  for (int i = 0; i < service->method_count(); ++i) {
713    PrintHeaderClientMethod(printer, service->method(i).get(), vars, false);
714  }
715  for (int i = 0; i < service->method_count(); ++i) {
716    PrintHeaderClientMethodData(printer, service->method(i).get(), vars);
717  }
718  printer->Outdent();
719  printer->Print("};\n");
720  printer->Print(
721      "static std::unique_ptr<Stub> NewStub(const std::shared_ptr< "
722      "::grpc::ChannelInterface>& channel, "
723      "const ::grpc::StubOptions& options = ::grpc::StubOptions());\n");
724
725  printer->Print("\n");
726
727  // Server side - base
728  printer->Print(
729      "class Service : public ::grpc::Service {\n"
730      " public:\n");
731  printer->Indent();
732  printer->Print("Service();\n");
733  printer->Print("virtual ~Service();\n");
734  for (int i = 0; i < service->method_count(); ++i) {
735    PrintHeaderServerMethodSync(printer, service->method(i).get(), vars);
736  }
737  printer->Outdent();
738  printer->Print("};\n");
739
740  // Server side - Asynchronous
741  for (int i = 0; i < service->method_count(); ++i) {
742    (*vars)["Idx"] = as_string(i);
743    PrintHeaderServerMethodAsync(printer, service->method(i).get(), vars);
744  }
745
746  printer->Print("typedef ");
747
748  for (int i = 0; i < service->method_count(); ++i) {
749    (*vars)["method_name"] = service->method(i).get()->name();
750    printer->Print(*vars, "WithAsyncMethod_$method_name$<");
751  }
752  printer->Print("Service");
753  for (int i = 0; i < service->method_count(); ++i) {
754    printer->Print(" >");
755  }
756  printer->Print(" AsyncService;\n");
757
758  // Server side - Generic
759  for (int i = 0; i < service->method_count(); ++i) {
760    (*vars)["Idx"] = as_string(i);
761    PrintHeaderServerMethodGeneric(printer, service->method(i).get(), vars);
762  }
763
764  printer->Outdent();
765  printer->Print("};\n");
766}
767
768grpc::string GetHeaderServices(grpc_generator::File *file,
769                               const Parameters &params) {
770  grpc::string output;
771  {
772    // Scope the output stream so it closes and finalizes output to the string.
773    auto printer = file->CreatePrinter(&output);
774    std::map<grpc::string, grpc::string> vars;
775    // Package string is empty or ends with a dot. It is used to fully qualify
776    // method names.
777    vars["Package"] = file->package();
778    if (!file->package().empty()) {
779      vars["Package"].append(".");
780    }
781
782    if (!params.services_namespace.empty()) {
783      vars["services_namespace"] = params.services_namespace;
784      printer->Print(vars, "\nnamespace $services_namespace$ {\n\n");
785    }
786
787    for (int i = 0; i < file->service_count(); ++i) {
788      PrintHeaderService(printer.get(), file->service(i).get(), &vars);
789      printer->Print("\n");
790    }
791
792    if (!params.services_namespace.empty()) {
793      printer->Print(vars, "}  // namespace $services_namespace$\n\n");
794    }
795  }
796  return output;
797}
798
799grpc::string GetHeaderEpilogue(grpc_generator::File *file, const Parameters & /*params*/) {
800  grpc::string output;
801  {
802    // Scope the output stream so it closes and finalizes output to the string.
803    auto printer = file->CreatePrinter(&output);
804    std::map<grpc::string, grpc::string> vars;
805
806    vars["filename"] = file->filename();
807    vars["filename_identifier"] = FilenameIdentifier(file->filename());
808
809    if (!file->package().empty()) {
810      std::vector<grpc::string> parts = file->package_parts();
811
812      for (auto part = parts.rbegin(); part != parts.rend(); part++) {
813        vars["part"] = *part;
814        printer->Print(vars, "}  // namespace $part$\n");
815      }
816      printer->Print(vars, "\n");
817    }
818
819    printer->Print(vars, "\n");
820    printer->Print(vars, "#endif  // GRPC_$filename_identifier$__INCLUDED\n");
821  }
822  return output;
823}
824
825grpc::string GetSourcePrologue(grpc_generator::File *file, const Parameters & /*params*/) {
826  grpc::string output;
827  {
828    // Scope the output stream so it closes and finalizes output to the string.
829    auto printer = file->CreatePrinter(&output);
830    std::map<grpc::string, grpc::string> vars;
831
832    vars["filename"] = file->filename();
833    vars["filename_base"] = file->filename_without_ext();
834    vars["message_header_ext"] = file->message_header_ext();
835    vars["service_header_ext"] = file->service_header_ext();
836
837    printer->Print(vars, "// Generated by the gRPC protobuf plugin.\n");
838    printer->Print(vars,
839                  "// If you make any local change, they will be lost.\n");
840    printer->Print(vars, "// source: $filename$\n\n");
841    printer->Print(vars, "#include \"$filename_base$$message_header_ext$\"\n");
842    printer->Print(vars, "#include \"$filename_base$$service_header_ext$\"\n");
843    printer->Print("\n");
844  }
845  return output;
846}
847
848grpc::string GetSourceIncludes(grpc_generator::File *file,
849                               const Parameters &params) {
850  grpc::string output;
851  {
852    // Scope the output stream so it closes and finalizes output to the string.
853    auto printer = file->CreatePrinter(&output);
854    std::map<grpc::string, grpc::string> vars;
855
856    static const char *headers_strs[] = {
857      "grpc++/impl/codegen/async_stream.h",
858      "grpc++/impl/codegen/async_unary_call.h",
859      "grpc++/impl/codegen/channel_interface.h",
860      "grpc++/impl/codegen/client_unary_call.h",
861      "grpc++/impl/codegen/method_handler_impl.h",
862      "grpc++/impl/codegen/rpc_service_method.h",
863      "grpc++/impl/codegen/service_type.h",
864      "grpc++/impl/codegen/sync_stream.h"
865    };
866    std::vector<grpc::string> headers(headers_strs, array_end(headers_strs));
867    PrintIncludes(printer.get(), headers, params);
868
869    if (!file->package().empty()) {
870      printer->Print("\n");
871      std::vector<grpc::string> parts = file->package_parts();
872
873      for (auto part = parts.begin(); part != parts.end(); part++) {
874        vars["part"] = *part;
875        printer->Print(vars, "namespace $part$ {\n");
876      }
877    }
878
879    printer->Print(vars, "\n");
880  }
881  return output;
882}
883
884void PrintSourceClientMethod(grpc_generator::Printer *printer,
885                             const grpc_generator::Method *method,
886                             std::map<grpc::string, grpc::string> *vars) {
887  (*vars)["Method"] = method->name();
888  (*vars)["Request"] = method->input_type_name();
889  (*vars)["Response"] = method->output_type_name();
890  if (method->NoStreaming()) {
891    printer->Print(*vars,
892                   "::grpc::Status $ns$$Service$::Stub::$Method$("
893                   "::grpc::ClientContext* context, "
894                   "const $Request$& request, $Response$* response) {\n");
895    printer->Print(*vars,
896                   "  return ::grpc::BlockingUnaryCall(channel_.get(), "
897                   "rpcmethod_$Method$_, "
898                   "context, request, response);\n"
899                   "}\n\n");
900    printer->Print(
901        *vars,
902        "::grpc::ClientAsyncResponseReader< $Response$>* "
903        "$ns$$Service$::Stub::Async$Method$Raw(::grpc::ClientContext* context, "
904        "const $Request$& request, "
905        "::grpc::CompletionQueue* cq) {\n");
906    printer->Print(*vars,
907                   "  return new "
908                   "::grpc::ClientAsyncResponseReader< $Response$>("
909                   "channel_.get(), cq, "
910                   "rpcmethod_$Method$_, "
911                   "context, request);\n"
912                   "}\n\n");
913  } else if (method->ClientOnlyStreaming()) {
914    printer->Print(*vars,
915                   "::grpc::ClientWriter< $Request$>* "
916                   "$ns$$Service$::Stub::$Method$Raw("
917                   "::grpc::ClientContext* context, $Response$* response) {\n");
918    printer->Print(*vars,
919                   "  return new ::grpc::ClientWriter< $Request$>("
920                   "channel_.get(), "
921                   "rpcmethod_$Method$_, "
922                   "context, response);\n"
923                   "}\n\n");
924    printer->Print(*vars,
925                   "::grpc::ClientAsyncWriter< $Request$>* "
926                   "$ns$$Service$::Stub::Async$Method$Raw("
927                   "::grpc::ClientContext* context, $Response$* response, "
928                   "::grpc::CompletionQueue* cq, void* tag) {\n");
929    printer->Print(*vars,
930                   "  return new ::grpc::ClientAsyncWriter< $Request$>("
931                   "channel_.get(), cq, "
932                   "rpcmethod_$Method$_, "
933                   "context, response, tag);\n"
934                   "}\n\n");
935  } else if (method->ServerOnlyStreaming()) {
936    printer->Print(
937        *vars,
938        "::grpc::ClientReader< $Response$>* "
939        "$ns$$Service$::Stub::$Method$Raw("
940        "::grpc::ClientContext* context, const $Request$& request) {\n");
941    printer->Print(*vars,
942                   "  return new ::grpc::ClientReader< $Response$>("
943                   "channel_.get(), "
944                   "rpcmethod_$Method$_, "
945                   "context, request);\n"
946                   "}\n\n");
947    printer->Print(*vars,
948                   "::grpc::ClientAsyncReader< $Response$>* "
949                   "$ns$$Service$::Stub::Async$Method$Raw("
950                   "::grpc::ClientContext* context, const $Request$& request, "
951                   "::grpc::CompletionQueue* cq, void* tag) {\n");
952    printer->Print(*vars,
953                   "  return new ::grpc::ClientAsyncReader< $Response$>("
954                   "channel_.get(), cq, "
955                   "rpcmethod_$Method$_, "
956                   "context, request, tag);\n"
957                   "}\n\n");
958  } else if (method->BidiStreaming()) {
959    printer->Print(
960        *vars,
961        "::grpc::ClientReaderWriter< $Request$, $Response$>* "
962        "$ns$$Service$::Stub::$Method$Raw(::grpc::ClientContext* context) {\n");
963    printer->Print(*vars,
964                   "  return new ::grpc::ClientReaderWriter< "
965                   "$Request$, $Response$>("
966                   "channel_.get(), "
967                   "rpcmethod_$Method$_, "
968                   "context);\n"
969                   "}\n\n");
970    printer->Print(
971        *vars,
972        "::grpc::ClientAsyncReaderWriter< $Request$, $Response$>* "
973        "$ns$$Service$::Stub::Async$Method$Raw(::grpc::ClientContext* context, "
974        "::grpc::CompletionQueue* cq, void* tag) {\n");
975    printer->Print(*vars,
976                   "  return new "
977                   "::grpc::ClientAsyncReaderWriter< $Request$, $Response$>("
978                   "channel_.get(), cq, "
979                   "rpcmethod_$Method$_, "
980                   "context, tag);\n"
981                   "}\n\n");
982  }
983}
984
985void PrintSourceServerMethod(grpc_generator::Printer *printer,
986                             const grpc_generator::Method *method,
987                             std::map<grpc::string, grpc::string> *vars) {
988  (*vars)["Method"] = method->name();
989  (*vars)["Request"] = method->input_type_name();
990  (*vars)["Response"] = method->output_type_name();
991  if (method->NoStreaming()) {
992    printer->Print(*vars,
993                   "::grpc::Status $ns$$Service$::Service::$Method$("
994                   "::grpc::ServerContext* context, "
995                   "const $Request$* request, $Response$* response) {\n");
996    printer->Print("  (void) context;\n");
997    printer->Print("  (void) request;\n");
998    printer->Print("  (void) response;\n");
999    printer->Print(
1000        "  return ::grpc::Status("
1001        "::grpc::StatusCode::UNIMPLEMENTED, \"\");\n");
1002    printer->Print("}\n\n");
1003  } else if (method->ClientOnlyStreaming()) {
1004    printer->Print(*vars,
1005                   "::grpc::Status $ns$$Service$::Service::$Method$("
1006                   "::grpc::ServerContext* context, "
1007                   "::grpc::ServerReader< $Request$>* reader, "
1008                   "$Response$* response) {\n");
1009    printer->Print("  (void) context;\n");
1010    printer->Print("  (void) reader;\n");
1011    printer->Print("  (void) response;\n");
1012    printer->Print(
1013        "  return ::grpc::Status("
1014        "::grpc::StatusCode::UNIMPLEMENTED, \"\");\n");
1015    printer->Print("}\n\n");
1016  } else if (method->ServerOnlyStreaming()) {
1017    printer->Print(*vars,
1018                   "::grpc::Status $ns$$Service$::Service::$Method$("
1019                   "::grpc::ServerContext* context, "
1020                   "const $Request$* request, "
1021                   "::grpc::ServerWriter< $Response$>* writer) {\n");
1022    printer->Print("  (void) context;\n");
1023    printer->Print("  (void) request;\n");
1024    printer->Print("  (void) writer;\n");
1025    printer->Print(
1026        "  return ::grpc::Status("
1027        "::grpc::StatusCode::UNIMPLEMENTED, \"\");\n");
1028    printer->Print("}\n\n");
1029  } else if (method->BidiStreaming()) {
1030    printer->Print(*vars,
1031                   "::grpc::Status $ns$$Service$::Service::$Method$("
1032                   "::grpc::ServerContext* context, "
1033                   "::grpc::ServerReaderWriter< $Response$, $Request$>* "
1034                   "stream) {\n");
1035    printer->Print("  (void) context;\n");
1036    printer->Print("  (void) stream;\n");
1037    printer->Print(
1038        "  return ::grpc::Status("
1039        "::grpc::StatusCode::UNIMPLEMENTED, \"\");\n");
1040    printer->Print("}\n\n");
1041  }
1042}
1043
1044void PrintSourceService(grpc_generator::Printer *printer,
1045                        const grpc_generator::Service *service,
1046                        std::map<grpc::string, grpc::string> *vars) {
1047  (*vars)["Service"] = service->name();
1048
1049  printer->Print(*vars,
1050                 "static const char* $prefix$$Service$_method_names[] = {\n");
1051  for (int i = 0; i < service->method_count(); ++i) {
1052    (*vars)["Method"] = service->method(i).get()->name();
1053    printer->Print(*vars, "  \"/$Package$$Service$/$Method$\",\n");
1054  }
1055  printer->Print(*vars, "};\n\n");
1056
1057  printer->Print(*vars,
1058                 "std::unique_ptr< $ns$$Service$::Stub> $ns$$Service$::NewStub("
1059                 "const std::shared_ptr< ::grpc::ChannelInterface>& channel, "
1060                 "const ::grpc::StubOptions& options) {\n"
1061                 "  std::unique_ptr< $ns$$Service$::Stub> stub(new "
1062                 "$ns$$Service$::Stub(channel));\n"
1063                 "  return stub;\n"
1064                 "}\n\n");
1065  printer->Print(*vars,
1066                 "$ns$$Service$::Stub::Stub(const std::shared_ptr< "
1067                 "::grpc::ChannelInterface>& channel)\n");
1068  printer->Indent();
1069  printer->Print(": channel_(channel)");
1070  for (int i = 0; i < service->method_count(); ++i) {
1071    auto method = service->method(i);
1072    (*vars)["Method"] = method->name();
1073    (*vars)["Idx"] = as_string(i);
1074    if (method->NoStreaming()) {
1075      (*vars)["StreamingType"] = "NORMAL_RPC";
1076    } else if (method->ClientOnlyStreaming()) {
1077      (*vars)["StreamingType"] = "CLIENT_STREAMING";
1078    } else if (method->ServerOnlyStreaming()) {
1079      (*vars)["StreamingType"] = "SERVER_STREAMING";
1080    } else {
1081      (*vars)["StreamingType"] = "BIDI_STREAMING";
1082    }
1083    printer->Print(*vars,
1084                   ", rpcmethod_$Method$_("
1085                   "$prefix$$Service$_method_names[$Idx$], "
1086                   "::grpc::RpcMethod::$StreamingType$, "
1087                   "channel"
1088                   ")\n");
1089  }
1090  printer->Print("{}\n\n");
1091  printer->Outdent();
1092
1093  for (int i = 0; i < service->method_count(); ++i) {
1094    (*vars)["Idx"] = as_string(i);
1095    PrintSourceClientMethod(printer, service->method(i).get(), vars);
1096  }
1097
1098  printer->Print(*vars, "$ns$$Service$::Service::Service() {\n");
1099  printer->Indent();
1100  printer->Print(*vars, "(void)$prefix$$Service$_method_names;\n");
1101  for (int i = 0; i < service->method_count(); ++i) {
1102    auto method = service->method(i);
1103    (*vars)["Idx"] = as_string(i);
1104    (*vars)["Method"] = method->name();
1105    (*vars)["Request"] = method->input_type_name();
1106    (*vars)["Response"] = method->output_type_name();
1107    if (method->NoStreaming()) {
1108      printer->Print(
1109          *vars,
1110          "AddMethod(new ::grpc::RpcServiceMethod(\n"
1111          "    $prefix$$Service$_method_names[$Idx$],\n"
1112          "    ::grpc::RpcMethod::NORMAL_RPC,\n"
1113          "    new ::grpc::RpcMethodHandler< $ns$$Service$::Service, "
1114          "$Request$, "
1115          "$Response$>(\n"
1116          "        std::mem_fn(&$ns$$Service$::Service::$Method$), this)));\n");
1117    } else if (method->ClientOnlyStreaming()) {
1118      printer->Print(
1119          *vars,
1120          "AddMethod(new ::grpc::RpcServiceMethod(\n"
1121          "    $prefix$$Service$_method_names[$Idx$],\n"
1122          "    ::grpc::RpcMethod::CLIENT_STREAMING,\n"
1123          "    new ::grpc::ClientStreamingHandler< "
1124          "$ns$$Service$::Service, $Request$, $Response$>(\n"
1125          "        std::mem_fn(&$ns$$Service$::Service::$Method$), this)));\n");
1126    } else if (method->ServerOnlyStreaming()) {
1127      printer->Print(
1128          *vars,
1129          "AddMethod(new ::grpc::RpcServiceMethod(\n"
1130          "    $prefix$$Service$_method_names[$Idx$],\n"
1131          "    ::grpc::RpcMethod::SERVER_STREAMING,\n"
1132          "    new ::grpc::ServerStreamingHandler< "
1133          "$ns$$Service$::Service, $Request$, $Response$>(\n"
1134          "        std::mem_fn(&$ns$$Service$::Service::$Method$), this)));\n");
1135    } else if (method->BidiStreaming()) {
1136      printer->Print(
1137          *vars,
1138          "AddMethod(new ::grpc::RpcServiceMethod(\n"
1139          "    $prefix$$Service$_method_names[$Idx$],\n"
1140          "    ::grpc::RpcMethod::BIDI_STREAMING,\n"
1141          "    new ::grpc::BidiStreamingHandler< "
1142          "$ns$$Service$::Service, $Request$, $Response$>(\n"
1143          "        std::mem_fn(&$ns$$Service$::Service::$Method$), this)));\n");
1144    }
1145  }
1146  printer->Outdent();
1147  printer->Print(*vars, "}\n\n");
1148  printer->Print(*vars,
1149                 "$ns$$Service$::Service::~Service() {\n"
1150                 "}\n\n");
1151  for (int i = 0; i < service->method_count(); ++i) {
1152    (*vars)["Idx"] = as_string(i);
1153    PrintSourceServerMethod(printer, service->method(i).get(), vars);
1154  }
1155}
1156
1157grpc::string GetSourceServices(grpc_generator::File *file,
1158                               const Parameters &params) {
1159  grpc::string output;
1160  {
1161    // Scope the output stream so it closes and finalizes output to the string.
1162    auto printer = file->CreatePrinter(&output);
1163    std::map<grpc::string, grpc::string> vars;
1164    // Package string is empty or ends with a dot. It is used to fully qualify
1165    // method names.
1166    vars["Package"] = file->package();
1167    if (!file->package().empty()) {
1168      vars["Package"].append(".");
1169    }
1170    if (!params.services_namespace.empty()) {
1171      vars["ns"] = params.services_namespace + "::";
1172      vars["prefix"] = params.services_namespace;
1173    } else {
1174      vars["ns"] = "";
1175      vars["prefix"] = "";
1176    }
1177
1178    for (int i = 0; i < file->service_count(); ++i) {
1179      PrintSourceService(printer.get(), file->service(i).get(), &vars);
1180      printer->Print("\n");
1181    }
1182  }
1183  return output;
1184}
1185
1186grpc::string GetSourceEpilogue(grpc_generator::File *file, const Parameters & /*params*/) {
1187  grpc::string temp;
1188
1189  if (!file->package().empty()) {
1190    std::vector<grpc::string> parts = file->package_parts();
1191
1192    for (auto part = parts.begin(); part != parts.end(); part++) {
1193      temp.append("}  // namespace ");
1194      temp.append(*part);
1195      temp.append("\n");
1196    }
1197    temp.append("\n");
1198  }
1199
1200  return temp;
1201}
1202
1203}  // namespace grpc_cpp_generator
1204