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