Home | History | Annotate | Download | only in compiler
      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 
     40 namespace grpc_cpp_generator {
     41 namespace {
     42 
     43 template <class T>
     44 grpc::string as_string(T x) {
     45   std::ostringstream out;
     46   out << x;
     47   return out.str();
     48 }
     49 
     50 grpc::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 
     67 template<class T, size_t N>
     68 T *array_end(T (&array)[N]) { return array + N; }
     69 
     70 void 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 
     90 grpc::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 
    116 grpc::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 
    157 void 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 
    307 void 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 
    449 void 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 
    455 void 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 
    486 void 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 
    602 void 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 
    673 void 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 
    768 grpc::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 
    799 grpc::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 
    825 grpc::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 
    848 grpc::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 
    884 void 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 
    985 void 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 
   1044 void 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 
   1157 grpc::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 
   1186 grpc::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