• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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>
as_string(T x)44 grpc::string as_string(T x) {
45   std::ostringstream out;
46   out << x;
47   return out.str();
48 }
49 
FilenameIdentifier(const grpc::string & filename)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>
array_end(T (& array)[N])68 T *array_end(T (&array)[N]) { return array + N; }
69 
PrintIncludes(grpc_generator::Printer * printer,const std::vector<grpc::string> & headers,const Parameters & params)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 
GetHeaderPrologue(grpc_generator::File * file,const Parameters &)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 
GetHeaderIncludes(grpc_generator::File * file,const Parameters & params)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 
PrintHeaderClientMethodInterfaces(grpc_generator::Printer * printer,const grpc_generator::Method * method,std::map<grpc::string,grpc::string> * vars,bool is_public)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 
PrintHeaderClientMethod(grpc_generator::Printer * printer,const grpc_generator::Method * method,std::map<grpc::string,grpc::string> * vars,bool is_public)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 
PrintHeaderClientMethodData(grpc_generator::Printer * printer,const grpc_generator::Method * method,std::map<grpc::string,grpc::string> * vars)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 
PrintHeaderServerMethodSync(grpc_generator::Printer * printer,const grpc_generator::Method * method,std::map<grpc::string,grpc::string> * vars)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 
PrintHeaderServerMethodAsync(grpc_generator::Printer * printer,const grpc_generator::Method * method,std::map<grpc::string,grpc::string> * vars)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 
PrintHeaderServerMethodGeneric(grpc_generator::Printer * printer,const grpc_generator::Method * method,std::map<grpc::string,grpc::string> * vars)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 
PrintHeaderService(grpc_generator::Printer * printer,const grpc_generator::Service * service,std::map<grpc::string,grpc::string> * vars)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 
GetHeaderServices(grpc_generator::File * file,const Parameters & params)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 
GetHeaderEpilogue(grpc_generator::File * file,const Parameters &)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 
GetSourcePrologue(grpc_generator::File * file,const Parameters &)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 
GetSourceIncludes(grpc_generator::File * file,const Parameters & params)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 
PrintSourceClientMethod(grpc_generator::Printer * printer,const grpc_generator::Method * method,std::map<grpc::string,grpc::string> * vars)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 
PrintSourceServerMethod(grpc_generator::Printer * printer,const grpc_generator::Method * method,std::map<grpc::string,grpc::string> * vars)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 
PrintSourceService(grpc_generator::Printer * printer,const grpc_generator::Service * service,std::map<grpc::string,grpc::string> * vars)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 
GetSourceServices(grpc_generator::File * file,const Parameters & params)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 
GetSourceEpilogue(grpc_generator::File * file,const Parameters &)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