• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *
3  * Copyright 2015 gRPC authors.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18 
19 #include <map>
20 
21 #include "src/compiler/cpp_generator.h"
22 
23 #include <sstream>
24 
25 namespace grpc_cpp_generator {
26 namespace {
27 
28 template <class T>
as_string(T x)29 std::string as_string(T x) {
30   std::ostringstream out;
31   out << x;
32   return out.str();
33 }
34 
ClientOnlyStreaming(const grpc_generator::Method * method)35 inline bool ClientOnlyStreaming(const grpc_generator::Method* method) {
36   return method->ClientStreaming() && !method->ServerStreaming();
37 }
38 
ServerOnlyStreaming(const grpc_generator::Method * method)39 inline bool ServerOnlyStreaming(const grpc_generator::Method* method) {
40   return !method->ClientStreaming() && method->ServerStreaming();
41 }
42 
FilenameIdentifier(const std::string & filename)43 std::string FilenameIdentifier(const std::string& filename) {
44   std::string result;
45   for (unsigned i = 0; i < filename.size(); i++) {
46     char c = filename[i];
47     if (isalnum(c)) {
48       result.push_back(c);
49     } else {
50       static char hex[] = "0123456789abcdef";
51       result.push_back('_');
52       result.push_back(hex[(c >> 4) & 0xf]);
53       result.push_back(hex[c & 0xf]);
54     }
55   }
56   return result;
57 }
58 }  // namespace
59 
60 template <class T, size_t N>
array_end(T (& array)[N])61 T* array_end(T (&array)[N]) {
62   return array + N;
63 }
64 
PrintIncludes(grpc_generator::Printer * printer,const std::vector<std::string> & headers,bool use_system_headers,const std::string & search_path)65 void PrintIncludes(grpc_generator::Printer* printer,
66                    const std::vector<std::string>& headers,
67                    bool use_system_headers, const std::string& search_path) {
68   std::map<std::string, std::string> vars;
69 
70   vars["l"] = use_system_headers ? '<' : '"';
71   vars["r"] = use_system_headers ? '>' : '"';
72 
73   if (!search_path.empty()) {
74     vars["l"] += search_path;
75     if (search_path[search_path.size() - 1] != '/') {
76       vars["l"] += '/';
77     }
78   }
79 
80   for (auto i = headers.begin(); i != headers.end(); i++) {
81     vars["h"] = *i;
82     printer->Print(vars, "#include $l$$h$$r$\n");
83   }
84 }
85 
GetHeaderPrologue(grpc_generator::File * file,const Parameters & params)86 std::string GetHeaderPrologue(grpc_generator::File* file,
87                               const Parameters& params) {
88   std::string output;
89   {
90     // Scope the output stream so it closes and finalizes output to the string.
91     auto printer = file->CreatePrinter(&output);
92     std::map<std::string, std::string> vars;
93 
94     vars["filename"] = file->filename();
95     vars["filename_identifier"] = FilenameIdentifier(file->filename());
96     vars["filename_base"] = file->filename_without_ext();
97     vars["message_header_ext"] = params.message_header_extension.empty()
98                                      ? kCppGeneratorMessageHeaderExt
99                                      : params.message_header_extension;
100 
101     printer->Print(vars, "// Generated by the gRPC C++ plugin.\n");
102     printer->Print(vars,
103                    "// If you make any local change, they will be lost.\n");
104     printer->Print(vars, "// source: $filename$\n");
105     std::string leading_comments = file->GetLeadingComments("//");
106     if (!leading_comments.empty()) {
107       printer->Print(vars, "// Original file comments:\n");
108       printer->PrintRaw(leading_comments.c_str());
109     }
110     printer->Print(vars, "#ifndef GRPC_$filename_identifier$__INCLUDED\n");
111     printer->Print(vars, "#define GRPC_$filename_identifier$__INCLUDED\n");
112     printer->Print(vars, "\n");
113     printer->Print(vars, "#include \"$filename_base$$message_header_ext$\"\n");
114     printer->Print(vars, file->additional_headers().c_str());
115     printer->Print(vars, "\n");
116   }
117   return output;
118 }
119 
120 // Convert from "a/b/c.proto" to "#include \"a/b/c$message_header_ext$\"\n"
ImportInludeFromProtoName(const std::string & proto_name)121 std::string ImportInludeFromProtoName(const std::string& proto_name) {
122   return std::string("#include \"") +
123          proto_name.substr(0, proto_name.size() - 6) +
124          std::string("$message_header_ext$\"\n");
125 }
126 
GetHeaderIncludes(grpc_generator::File * file,const Parameters & params)127 std::string GetHeaderIncludes(grpc_generator::File* file,
128                               const Parameters& params) {
129   std::string output;
130   {
131     // Scope the output stream so it closes and finalizes output to the string.
132     auto printer = file->CreatePrinter(&output);
133     std::map<std::string, std::string> vars;
134 
135     if (!params.additional_header_includes.empty()) {
136       PrintIncludes(printer.get(), params.additional_header_includes, false,
137                     "");
138     }
139     // TODO(vjpai): Remove port_platform.h from header list when callback API is
140     //              fully de-experimentalized since we will no longer be using
141     //              macros from it.
142     static const char* headers_strs[] = {
143         "functional",
144         "grpc/impl/codegen/port_platform.h",
145         "grpcpp/impl/codegen/async_generic_service.h",
146         "grpcpp/impl/codegen/async_stream.h",
147         "grpcpp/impl/codegen/async_unary_call.h",
148         "grpcpp/impl/codegen/client_callback.h",
149         "grpcpp/impl/codegen/client_context.h",
150         "grpcpp/impl/codegen/completion_queue.h",
151         "grpcpp/impl/codegen/message_allocator.h",
152         "grpcpp/impl/codegen/method_handler.h",
153         "grpcpp/impl/codegen/proto_utils.h",
154         "grpcpp/impl/codegen/rpc_method.h",
155         "grpcpp/impl/codegen/server_callback.h",
156         "grpcpp/impl/codegen/server_callback_handlers.h",
157         "grpcpp/impl/codegen/server_context.h",
158         "grpcpp/impl/codegen/service_type.h",
159         "grpcpp/impl/codegen/status.h",
160         "grpcpp/impl/codegen/stub_options.h",
161         "grpcpp/impl/codegen/sync_stream.h",
162     };
163     std::vector<std::string> headers(headers_strs, array_end(headers_strs));
164     PrintIncludes(printer.get(), headers, params.use_system_headers,
165                   params.grpc_search_path);
166     printer->Print(vars, "\n");
167 
168     vars["message_header_ext"] = params.message_header_extension.empty()
169                                      ? kCppGeneratorMessageHeaderExt
170                                      : params.message_header_extension;
171 
172     if (params.include_import_headers) {
173       const std::vector<std::string> import_names = file->GetImportNames();
174       for (const auto& import_name : import_names) {
175         const std::string include_name = ImportInludeFromProtoName(import_name);
176         printer->Print(vars, include_name.c_str());
177       }
178       printer->PrintRaw("\n");
179     }
180 
181     if (!file->package().empty()) {
182       std::vector<std::string> parts = file->package_parts();
183 
184       for (auto part = parts.begin(); part != parts.end(); part++) {
185         vars["part"] = *part;
186         printer->Print(vars, "namespace $part$ {\n");
187       }
188       printer->Print(vars, "\n");
189     }
190   }
191   return output;
192 }
193 
PrintHeaderClientMethodInterfaces(grpc_generator::Printer * printer,const grpc_generator::Method * method,std::map<std::string,std::string> * vars,bool is_public)194 void PrintHeaderClientMethodInterfaces(grpc_generator::Printer* printer,
195                                        const grpc_generator::Method* method,
196                                        std::map<std::string, std::string>* vars,
197                                        bool is_public) {
198   (*vars)["Method"] = method->name();
199   (*vars)["Request"] = method->input_type_name();
200   (*vars)["Response"] = method->output_type_name();
201 
202   struct {
203     std::string prefix;
204     std::string method_params;  // extra arguments to method
205     std::string raw_args;       // extra arguments to raw version of method
206   } async_prefixes[] = {{"Async", ", void* tag", ", tag"},
207                         {"PrepareAsync", "", ""}};
208 
209   if (is_public) {
210     if (method->NoStreaming()) {
211       printer->Print(
212           *vars,
213           "virtual ::grpc::Status $Method$(::grpc::ClientContext* context, "
214           "const $Request$& request, $Response$* response) = 0;\n");
215       for (auto async_prefix : async_prefixes) {
216         (*vars)["AsyncPrefix"] = async_prefix.prefix;
217         printer->Print(
218             *vars,
219             "std::unique_ptr< "
220             "::grpc::ClientAsyncResponseReaderInterface< $Response$>> "
221             "$AsyncPrefix$$Method$(::grpc::ClientContext* context, "
222             "const $Request$& request, "
223             "::grpc::CompletionQueue* cq) {\n");
224         printer->Indent();
225         printer->Print(
226             *vars,
227             "return std::unique_ptr< "
228             "::grpc::ClientAsyncResponseReaderInterface< $Response$>>("
229             "$AsyncPrefix$$Method$Raw(context, request, cq));\n");
230         printer->Outdent();
231         printer->Print("}\n");
232       }
233     } else if (ClientOnlyStreaming(method)) {
234       printer->Print(
235           *vars,
236           "std::unique_ptr< ::grpc::ClientWriterInterface< $Request$>>"
237           " $Method$("
238           "::grpc::ClientContext* context, $Response$* response) {\n");
239       printer->Indent();
240       printer->Print(
241           *vars,
242           "return std::unique_ptr< ::grpc::ClientWriterInterface< $Request$>>"
243           "($Method$Raw(context, response));\n");
244       printer->Outdent();
245       printer->Print("}\n");
246       for (auto async_prefix : async_prefixes) {
247         (*vars)["AsyncPrefix"] = async_prefix.prefix;
248         (*vars)["AsyncMethodParams"] = async_prefix.method_params;
249         (*vars)["AsyncRawArgs"] = async_prefix.raw_args;
250         printer->Print(
251             *vars,
252             "std::unique_ptr< ::grpc::ClientAsyncWriterInterface< $Request$>>"
253             " $AsyncPrefix$$Method$(::grpc::ClientContext* context, "
254             "$Response$* "
255             "response, "
256             "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
257         printer->Indent();
258         printer->Print(*vars,
259                        "return std::unique_ptr< "
260                        "::grpc::ClientAsyncWriterInterface< $Request$>>("
261                        "$AsyncPrefix$$Method$Raw(context, response, "
262                        "cq$AsyncRawArgs$));\n");
263         printer->Outdent();
264         printer->Print("}\n");
265       }
266     } else if (ServerOnlyStreaming(method)) {
267       printer->Print(
268           *vars,
269           "std::unique_ptr< ::grpc::ClientReaderInterface< $Response$>>"
270           " $Method$(::grpc::ClientContext* context, const $Request$& request)"
271           " {\n");
272       printer->Indent();
273       printer->Print(
274           *vars,
275           "return std::unique_ptr< ::grpc::ClientReaderInterface< $Response$>>"
276           "($Method$Raw(context, request));\n");
277       printer->Outdent();
278       printer->Print("}\n");
279       for (auto async_prefix : async_prefixes) {
280         (*vars)["AsyncPrefix"] = async_prefix.prefix;
281         (*vars)["AsyncMethodParams"] = async_prefix.method_params;
282         (*vars)["AsyncRawArgs"] = async_prefix.raw_args;
283         printer->Print(
284             *vars,
285             "std::unique_ptr< ::grpc::ClientAsyncReaderInterface< $Response$>> "
286             "$AsyncPrefix$$Method$("
287             "::grpc::ClientContext* context, const $Request$& request, "
288             "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
289         printer->Indent();
290         printer->Print(
291             *vars,
292             "return std::unique_ptr< "
293             "::grpc::ClientAsyncReaderInterface< $Response$>>("
294             "$AsyncPrefix$$Method$Raw(context, request, cq$AsyncRawArgs$));\n");
295         printer->Outdent();
296         printer->Print("}\n");
297       }
298     } else if (method->BidiStreaming()) {
299       printer->Print(*vars,
300                      "std::unique_ptr< ::grpc::ClientReaderWriterInterface< "
301                      "$Request$, $Response$>> "
302                      "$Method$(::grpc::ClientContext* context) {\n");
303       printer->Indent();
304       printer->Print(
305           *vars,
306           "return std::unique_ptr< "
307           "::grpc::ClientReaderWriterInterface< $Request$, $Response$>>("
308           "$Method$Raw(context));\n");
309       printer->Outdent();
310       printer->Print("}\n");
311       for (auto async_prefix : async_prefixes) {
312         (*vars)["AsyncPrefix"] = async_prefix.prefix;
313         (*vars)["AsyncMethodParams"] = async_prefix.method_params;
314         (*vars)["AsyncRawArgs"] = async_prefix.raw_args;
315         printer->Print(
316             *vars,
317             "std::unique_ptr< "
318             "::grpc::ClientAsyncReaderWriterInterface< $Request$, $Response$>> "
319             "$AsyncPrefix$$Method$(::grpc::ClientContext* context, "
320             "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
321         printer->Indent();
322         printer->Print(
323             *vars,
324             "return std::unique_ptr< "
325             "::grpc::ClientAsyncReaderWriterInterface< $Request$, $Response$>>("
326             "$AsyncPrefix$$Method$Raw(context, cq$AsyncRawArgs$));\n");
327         printer->Outdent();
328         printer->Print("}\n");
329       }
330     }
331   } else {
332     if (method->NoStreaming()) {
333       for (auto async_prefix : async_prefixes) {
334         (*vars)["AsyncPrefix"] = async_prefix.prefix;
335         printer->Print(
336             *vars,
337             "virtual ::grpc::ClientAsyncResponseReaderInterface< $Response$>* "
338             "$AsyncPrefix$$Method$Raw(::grpc::ClientContext* context, "
339             "const $Request$& request, "
340             "::grpc::CompletionQueue* cq) = 0;\n");
341       }
342     } else if (ClientOnlyStreaming(method)) {
343       printer->Print(
344           *vars,
345           "virtual ::grpc::ClientWriterInterface< $Request$>*"
346           " $Method$Raw("
347           "::grpc::ClientContext* context, $Response$* response) = 0;\n");
348       for (auto async_prefix : async_prefixes) {
349         (*vars)["AsyncPrefix"] = async_prefix.prefix;
350         (*vars)["AsyncMethodParams"] = async_prefix.method_params;
351         printer->Print(
352             *vars,
353             "virtual ::grpc::ClientAsyncWriterInterface< $Request$>*"
354             " $AsyncPrefix$$Method$Raw(::grpc::ClientContext* context, "
355             "$Response$* response, "
356             "::grpc::CompletionQueue* cq$AsyncMethodParams$) = 0;\n");
357       }
358     } else if (ServerOnlyStreaming(method)) {
359       printer->Print(
360           *vars,
361           "virtual ::grpc::ClientReaderInterface< $Response$>* "
362           "$Method$Raw("
363           "::grpc::ClientContext* context, const $Request$& request) = 0;\n");
364       for (auto async_prefix : async_prefixes) {
365         (*vars)["AsyncPrefix"] = async_prefix.prefix;
366         (*vars)["AsyncMethodParams"] = async_prefix.method_params;
367         printer->Print(
368             *vars,
369             "virtual ::grpc::ClientAsyncReaderInterface< $Response$>* "
370             "$AsyncPrefix$$Method$Raw("
371             "::grpc::ClientContext* context, const $Request$& request, "
372             "::grpc::CompletionQueue* cq$AsyncMethodParams$) = 0;\n");
373       }
374     } else if (method->BidiStreaming()) {
375       printer->Print(*vars,
376                      "virtual ::grpc::ClientReaderWriterInterface< $Request$, "
377                      "$Response$>* "
378                      "$Method$Raw(::grpc::ClientContext* context) = 0;\n");
379       for (auto async_prefix : async_prefixes) {
380         (*vars)["AsyncPrefix"] = async_prefix.prefix;
381         (*vars)["AsyncMethodParams"] = async_prefix.method_params;
382         printer->Print(
383             *vars,
384             "virtual ::grpc::ClientAsyncReaderWriterInterface< "
385             "$Request$, $Response$>* "
386             "$AsyncPrefix$$Method$Raw(::grpc::ClientContext* context, "
387             "::grpc::CompletionQueue* cq$AsyncMethodParams$) = 0;\n");
388       }
389     }
390   }
391 }
392 
PrintHeaderClientMethod(grpc_generator::Printer * printer,const grpc_generator::Method * method,std::map<std::string,std::string> * vars,bool is_public)393 void PrintHeaderClientMethod(grpc_generator::Printer* printer,
394                              const grpc_generator::Method* method,
395                              std::map<std::string, std::string>* vars,
396                              bool is_public) {
397   (*vars)["Method"] = method->name();
398   (*vars)["Request"] = method->input_type_name();
399   (*vars)["Response"] = method->output_type_name();
400   struct {
401     std::string prefix;
402     std::string method_params;  // extra arguments to method
403     std::string raw_args;       // extra arguments to raw version of method
404   } async_prefixes[] = {{"Async", ", void* tag", ", tag"},
405                         {"PrepareAsync", "", ""}};
406 
407   if (is_public) {
408     if (method->NoStreaming()) {
409       printer->Print(
410           *vars,
411           "::grpc::Status $Method$(::grpc::ClientContext* context, "
412           "const $Request$& request, $Response$* response) override;\n");
413       for (auto async_prefix : async_prefixes) {
414         (*vars)["AsyncPrefix"] = async_prefix.prefix;
415         printer->Print(
416             *vars,
417             "std::unique_ptr< ::grpc::ClientAsyncResponseReader< $Response$>> "
418             "$AsyncPrefix$$Method$(::grpc::ClientContext* context, "
419             "const $Request$& request, "
420             "::grpc::CompletionQueue* cq) {\n");
421         printer->Indent();
422         printer->Print(*vars,
423                        "return std::unique_ptr< "
424                        "::grpc::ClientAsyncResponseReader< $Response$>>("
425                        "$AsyncPrefix$$Method$Raw(context, request, cq));\n");
426         printer->Outdent();
427         printer->Print("}\n");
428       }
429     } else if (ClientOnlyStreaming(method)) {
430       printer->Print(
431           *vars,
432           "std::unique_ptr< ::grpc::ClientWriter< $Request$>>"
433           " $Method$("
434           "::grpc::ClientContext* context, $Response$* response) {\n");
435       printer->Indent();
436       printer->Print(*vars,
437                      "return std::unique_ptr< ::grpc::ClientWriter< $Request$>>"
438                      "($Method$Raw(context, response));\n");
439       printer->Outdent();
440       printer->Print("}\n");
441       for (auto async_prefix : async_prefixes) {
442         (*vars)["AsyncPrefix"] = async_prefix.prefix;
443         (*vars)["AsyncMethodParams"] = async_prefix.method_params;
444         (*vars)["AsyncRawArgs"] = async_prefix.raw_args;
445         printer->Print(*vars,
446                        "std::unique_ptr< ::grpc::ClientAsyncWriter< $Request$>>"
447                        " $AsyncPrefix$$Method$(::grpc::ClientContext* context, "
448                        "$Response$* response, "
449                        "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
450         printer->Indent();
451         printer->Print(
452             *vars,
453             "return std::unique_ptr< ::grpc::ClientAsyncWriter< $Request$>>("
454             "$AsyncPrefix$$Method$Raw(context, response, "
455             "cq$AsyncRawArgs$));\n");
456         printer->Outdent();
457         printer->Print("}\n");
458       }
459     } else if (ServerOnlyStreaming(method)) {
460       printer->Print(
461           *vars,
462           "std::unique_ptr< ::grpc::ClientReader< $Response$>>"
463           " $Method$(::grpc::ClientContext* context, const $Request$& request)"
464           " {\n");
465       printer->Indent();
466       printer->Print(
467           *vars,
468           "return std::unique_ptr< ::grpc::ClientReader< $Response$>>"
469           "($Method$Raw(context, request));\n");
470       printer->Outdent();
471       printer->Print("}\n");
472       for (auto async_prefix : async_prefixes) {
473         (*vars)["AsyncPrefix"] = async_prefix.prefix;
474         (*vars)["AsyncMethodParams"] = async_prefix.method_params;
475         (*vars)["AsyncRawArgs"] = async_prefix.raw_args;
476         printer->Print(
477             *vars,
478             "std::unique_ptr< ::grpc::ClientAsyncReader< $Response$>> "
479             "$AsyncPrefix$$Method$("
480             "::grpc::ClientContext* context, const $Request$& request, "
481             "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
482         printer->Indent();
483         printer->Print(
484             *vars,
485             "return std::unique_ptr< ::grpc::ClientAsyncReader< $Response$>>("
486             "$AsyncPrefix$$Method$Raw(context, request, cq$AsyncRawArgs$));\n");
487         printer->Outdent();
488         printer->Print("}\n");
489       }
490     } else if (method->BidiStreaming()) {
491       printer->Print(
492           *vars,
493           "std::unique_ptr< ::grpc::ClientReaderWriter< $Request$, $Response$>>"
494           " $Method$(::grpc::ClientContext* context) {\n");
495       printer->Indent();
496       printer->Print(*vars,
497                      "return std::unique_ptr< "
498                      "::grpc::ClientReaderWriter< $Request$, $Response$>>("
499                      "$Method$Raw(context));\n");
500       printer->Outdent();
501       printer->Print("}\n");
502       for (auto async_prefix : async_prefixes) {
503         (*vars)["AsyncPrefix"] = async_prefix.prefix;
504         (*vars)["AsyncMethodParams"] = async_prefix.method_params;
505         (*vars)["AsyncRawArgs"] = async_prefix.raw_args;
506         printer->Print(*vars,
507                        "std::unique_ptr<  ::grpc::ClientAsyncReaderWriter< "
508                        "$Request$, $Response$>> "
509                        "$AsyncPrefix$$Method$(::grpc::ClientContext* context, "
510                        "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
511         printer->Indent();
512         printer->Print(
513             *vars,
514             "return std::unique_ptr< "
515             "::grpc::ClientAsyncReaderWriter< $Request$, $Response$>>("
516             "$AsyncPrefix$$Method$Raw(context, cq$AsyncRawArgs$));\n");
517         printer->Outdent();
518         printer->Print("}\n");
519       }
520     }
521   } else {
522     if (method->NoStreaming()) {
523       for (auto async_prefix : async_prefixes) {
524         (*vars)["AsyncPrefix"] = async_prefix.prefix;
525         printer->Print(
526             *vars,
527             "::grpc::ClientAsyncResponseReader< $Response$>* "
528             "$AsyncPrefix$$Method$Raw(::grpc::ClientContext* context, "
529             "const $Request$& request, "
530             "::grpc::CompletionQueue* cq) override;\n");
531       }
532     } else if (ClientOnlyStreaming(method)) {
533       printer->Print(*vars,
534                      "::grpc::ClientWriter< $Request$>* $Method$Raw("
535                      "::grpc::ClientContext* context, $Response$* response) "
536                      "override;\n");
537       for (auto async_prefix : async_prefixes) {
538         (*vars)["AsyncPrefix"] = async_prefix.prefix;
539         (*vars)["AsyncMethodParams"] = async_prefix.method_params;
540         (*vars)["AsyncRawArgs"] = async_prefix.raw_args;
541         printer->Print(
542             *vars,
543             "::grpc::ClientAsyncWriter< $Request$>* $AsyncPrefix$$Method$Raw("
544             "::grpc::ClientContext* context, $Response$* response, "
545             "::grpc::CompletionQueue* cq$AsyncMethodParams$) override;\n");
546       }
547     } else if (ServerOnlyStreaming(method)) {
548       printer->Print(*vars,
549                      "::grpc::ClientReader< $Response$>* $Method$Raw("
550                      "::grpc::ClientContext* context, const $Request$& request)"
551                      " override;\n");
552       for (auto async_prefix : async_prefixes) {
553         (*vars)["AsyncPrefix"] = async_prefix.prefix;
554         (*vars)["AsyncMethodParams"] = async_prefix.method_params;
555         (*vars)["AsyncRawArgs"] = async_prefix.raw_args;
556         printer->Print(
557             *vars,
558             "::grpc::ClientAsyncReader< $Response$>* $AsyncPrefix$$Method$Raw("
559             "::grpc::ClientContext* context, const $Request$& request, "
560             "::grpc::CompletionQueue* cq$AsyncMethodParams$) override;\n");
561       }
562     } else if (method->BidiStreaming()) {
563       printer->Print(*vars,
564                      "::grpc::ClientReaderWriter< $Request$, $Response$>* "
565                      "$Method$Raw(::grpc::ClientContext* context) override;\n");
566       for (auto async_prefix : async_prefixes) {
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 
PrintHeaderClientMethodCallbackInterfacesStart(grpc_generator::Printer * printer,std::map<std::string,std::string> *)580 void PrintHeaderClientMethodCallbackInterfacesStart(
581     grpc_generator::Printer* printer,
582     std::map<std::string, std::string>* /*vars*/) {
583   // This declares the interface for the callback-based API. The components
584   // are pure; even though this is new (post-1.0) API, it can be pure because
585   // it is an entirely new interface that happens to be scoped within
586   // StubInterface, not new additions to StubInterface itself
587   printer->Print("class experimental_async_interface {\n");
588   // All methods in this new interface are public. There is no need for private
589   // "Raw" methods since the callback-based API returns unowned raw pointers
590   printer->Print(" public:\n");
591   printer->Indent();
592   printer->Print("virtual ~experimental_async_interface() {}\n");
593 }
594 
PrintHeaderClientMethodCallbackInterfaces(grpc_generator::Printer * printer,const grpc_generator::Method * method,std::map<std::string,std::string> * vars)595 void PrintHeaderClientMethodCallbackInterfaces(
596     grpc_generator::Printer* printer, const grpc_generator::Method* method,
597     std::map<std::string, std::string>* vars) {
598   (*vars)["Method"] = method->name();
599   (*vars)["Request"] = method->input_type_name();
600   (*vars)["Response"] = method->output_type_name();
601 
602   if (method->NoStreaming()) {
603     printer->Print(*vars,
604                    "virtual void $Method$(::grpc::ClientContext* context, "
605                    "const $Request$* request, $Response$* response, "
606                    "std::function<void(::grpc::Status)>) = 0;\n");
607     printer->Print(*vars,
608                    "virtual void $Method$(::grpc::ClientContext* context, "
609                    "const ::grpc::ByteBuffer* request, $Response$* response, "
610                    "std::function<void(::grpc::Status)>) = 0;\n");
611     // TODO(vjpai): Remove experimental versions and macros when callback API is
612     //              fully de-experimentalized.
613     printer->Print(*vars,
614                    "#ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL\n"
615                    "virtual void $Method$(::grpc::ClientContext* context, "
616                    "const $Request$* request, $Response$* response, "
617                    "::grpc::ClientUnaryReactor* reactor) = 0;\n"
618                    "#else\n"
619                    "virtual void $Method$(::grpc::ClientContext* context, "
620                    "const $Request$* request, $Response$* response, "
621                    "::grpc::experimental::ClientUnaryReactor* reactor) = 0;\n"
622                    "#endif\n");
623     printer->Print(*vars,
624                    "#ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL\n"
625                    "virtual void $Method$(::grpc::ClientContext* context, "
626                    "const ::grpc::ByteBuffer* request, $Response$* response, "
627                    "::grpc::ClientUnaryReactor* reactor) = 0;\n"
628                    "#else\n"
629                    "virtual void $Method$(::grpc::ClientContext* context, "
630                    "const ::grpc::ByteBuffer* request, $Response$* response, "
631                    "::grpc::experimental::ClientUnaryReactor* reactor) = 0;\n"
632                    "#endif\n");
633   } else if (ClientOnlyStreaming(method)) {
634     printer->Print(*vars,
635                    "#ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL\n"
636                    "virtual void $Method$(::grpc::ClientContext* context, "
637                    "$Response$* response, "
638                    "::grpc::ClientWriteReactor< $Request$>* "
639                    "reactor) = 0;\n"
640                    "#else\n"
641                    "virtual void $Method$(::grpc::ClientContext* context, "
642                    "$Response$* response, "
643                    "::grpc::experimental::ClientWriteReactor< $Request$>* "
644                    "reactor) = 0;\n"
645                    "#endif\n");
646   } else if (ServerOnlyStreaming(method)) {
647     printer->Print(*vars,
648                    "#ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL\n"
649                    "virtual void $Method$(::grpc::ClientContext* context, "
650                    "$Request$* request, "
651                    "::grpc::ClientReadReactor< $Response$>* "
652                    "reactor) = 0;\n"
653                    "#else\n"
654                    "virtual void $Method$(::grpc::ClientContext* context, "
655                    "$Request$* request, "
656                    "::grpc::experimental::ClientReadReactor< $Response$>* "
657                    "reactor) = 0;\n"
658                    "#endif\n");
659   } else if (method->BidiStreaming()) {
660     printer->Print(*vars,
661                    "#ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL\n"
662                    "virtual void $Method$(::grpc::ClientContext* context, "
663                    "::grpc::ClientBidiReactor< "
664                    "$Request$,$Response$>* reactor) = 0;\n"
665                    "#else\n"
666                    "virtual void $Method$(::grpc::ClientContext* context, "
667                    "::grpc::experimental::ClientBidiReactor< "
668                    "$Request$,$Response$>* reactor) = 0;\n"
669                    "#endif\n");
670   }
671 }
672 
PrintHeaderClientMethodCallbackInterfacesEnd(grpc_generator::Printer * printer,std::map<std::string,std::string> *)673 void PrintHeaderClientMethodCallbackInterfacesEnd(
674     grpc_generator::Printer* printer,
675     std::map<std::string, std::string>* /*vars*/) {
676   printer->Outdent();
677   printer->Print("};\n");
678   printer->Print(
679       "#ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL\n"
680       "typedef class experimental_async_interface async_interface;\n"
681       "#endif\n");
682 
683   // Declare a function to give the async stub contents. It can't be pure
684   // since this is a new API in StubInterface, but it is meaningless by default
685   // (since any stub that wants to use it must have its own implementation of
686   // the callback functions therein), so make the default return value nullptr.
687   // Intentionally include the word "class" to avoid possible shadowing.
688   printer->Print(
689       "#ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL\n"
690       "async_interface* async() { return experimental_async(); }\n"
691       "#endif\n");
692   printer->Print(
693       "virtual class experimental_async_interface* experimental_async() { "
694       "return nullptr; }\n");
695 }
696 
PrintHeaderClientMethodCallbackStart(grpc_generator::Printer * printer,std::map<std::string,std::string> *)697 void PrintHeaderClientMethodCallbackStart(
698     grpc_generator::Printer* printer,
699     std::map<std::string, std::string>* /*vars*/) {
700   // This declares the stub entry for the callback-based API.
701   printer->Print("class experimental_async final :\n");
702   printer->Print("  public StubInterface::experimental_async_interface {\n");
703   printer->Print(" public:\n");
704   printer->Indent();
705 }
706 
PrintHeaderClientMethodCallback(grpc_generator::Printer * printer,const grpc_generator::Method * method,std::map<std::string,std::string> * vars)707 void PrintHeaderClientMethodCallback(grpc_generator::Printer* printer,
708                                      const grpc_generator::Method* method,
709                                      std::map<std::string, std::string>* vars) {
710   (*vars)["Method"] = method->name();
711   (*vars)["Request"] = method->input_type_name();
712   (*vars)["Response"] = method->output_type_name();
713 
714   if (method->NoStreaming()) {
715     printer->Print(*vars,
716                    "void $Method$(::grpc::ClientContext* context, "
717                    "const $Request$* request, $Response$* response, "
718                    "std::function<void(::grpc::Status)>) override;\n");
719     printer->Print(*vars,
720                    "void $Method$(::grpc::ClientContext* context, "
721                    "const ::grpc::ByteBuffer* request, $Response$* response, "
722                    "std::function<void(::grpc::Status)>) override;\n");
723     printer->Print(
724         *vars,
725         "#ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL\n"
726         "void $Method$(::grpc::ClientContext* context, "
727         "const $Request$* request, $Response$* response, "
728         "::grpc::ClientUnaryReactor* reactor) override;\n"
729         "#else\n"
730         "void $Method$(::grpc::ClientContext* context, "
731         "const $Request$* request, $Response$* response, "
732         "::grpc::experimental::ClientUnaryReactor* reactor) override;\n"
733         "#endif\n");
734     printer->Print(
735         *vars,
736         "#ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL\n"
737         "void $Method$(::grpc::ClientContext* context, "
738         "const ::grpc::ByteBuffer* request, $Response$* response, "
739         "::grpc::ClientUnaryReactor* reactor) override;\n"
740         "#else\n"
741         "void $Method$(::grpc::ClientContext* context, "
742         "const ::grpc::ByteBuffer* request, $Response$* response, "
743         "::grpc::experimental::ClientUnaryReactor* reactor) override;\n"
744         "#endif\n");
745   } else if (ClientOnlyStreaming(method)) {
746     printer->Print(*vars,
747                    "#ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL\n"
748                    "void $Method$(::grpc::ClientContext* context, "
749                    "$Response$* response, "
750                    "::grpc::ClientWriteReactor< $Request$>* "
751                    "reactor) override;\n"
752                    "#else\n"
753                    "void $Method$(::grpc::ClientContext* context, "
754                    "$Response$* response, "
755                    "::grpc::experimental::ClientWriteReactor< $Request$>* "
756                    "reactor) override;\n"
757                    "#endif\n");
758   } else if (ServerOnlyStreaming(method)) {
759     printer->Print(*vars,
760                    "#ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL\n"
761                    "void $Method$(::grpc::ClientContext* context, "
762                    "$Request$* request, "
763                    "::grpc::ClientReadReactor< $Response$>* "
764                    "reactor) override;\n"
765                    "#else\n"
766                    "void $Method$(::grpc::ClientContext* context, "
767                    "$Request$* request, "
768                    "::grpc::experimental::ClientReadReactor< $Response$>* "
769                    "reactor) override;\n"
770                    "#endif\n");
771 
772   } else if (method->BidiStreaming()) {
773     printer->Print(*vars,
774                    "#ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL\n"
775                    "void $Method$(::grpc::ClientContext* context, "
776                    "::grpc::ClientBidiReactor< "
777                    "$Request$,$Response$>* reactor) override;\n"
778                    "#else\n"
779                    "void $Method$(::grpc::ClientContext* context, "
780                    "::grpc::experimental::ClientBidiReactor< "
781                    "$Request$,$Response$>* reactor) override;\n"
782                    "#endif\n");
783   }
784 }
785 
PrintHeaderClientMethodCallbackEnd(grpc_generator::Printer * printer,std::map<std::string,std::string> *)786 void PrintHeaderClientMethodCallbackEnd(
787     grpc_generator::Printer* printer,
788     std::map<std::string, std::string>* /*vars*/) {
789   printer->Outdent();
790   printer->Print(" private:\n");
791   printer->Indent();
792   printer->Print("friend class Stub;\n");
793   printer->Print("explicit experimental_async(Stub* stub): stub_(stub) { }\n");
794   // include a function with a dummy use of stub_ to avoid an unused
795   // private member warning for service with no methods
796   printer->Print("Stub* stub() { return stub_; }\n");
797   printer->Print("Stub* stub_;\n");
798   printer->Outdent();
799   printer->Print("};\n");
800 
801   printer->Print(
802       "class experimental_async_interface* experimental_async() override { "
803       "return &async_stub_; }\n");
804 }
805 
PrintHeaderClientMethodData(grpc_generator::Printer * printer,const grpc_generator::Method * method,std::map<std::string,std::string> * vars)806 void PrintHeaderClientMethodData(grpc_generator::Printer* printer,
807                                  const grpc_generator::Method* method,
808                                  std::map<std::string, std::string>* vars) {
809   (*vars)["Method"] = method->name();
810   printer->Print(*vars,
811                  "const ::grpc::internal::RpcMethod rpcmethod_$Method$_;\n");
812 }
813 
PrintHeaderServerMethodSync(grpc_generator::Printer * printer,const grpc_generator::Method * method,std::map<std::string,std::string> * vars)814 void PrintHeaderServerMethodSync(grpc_generator::Printer* printer,
815                                  const grpc_generator::Method* method,
816                                  std::map<std::string, std::string>* vars) {
817   (*vars)["Method"] = method->name();
818   (*vars)["Request"] = method->input_type_name();
819   (*vars)["Response"] = method->output_type_name();
820   printer->Print(method->GetLeadingComments("//").c_str());
821   if (method->NoStreaming()) {
822     printer->Print(*vars,
823                    "virtual ::grpc::Status $Method$("
824                    "::grpc::ServerContext* context, const $Request$* request, "
825                    "$Response$* response);\n");
826   } else if (ClientOnlyStreaming(method)) {
827     printer->Print(*vars,
828                    "virtual ::grpc::Status $Method$("
829                    "::grpc::ServerContext* context, "
830                    "::grpc::ServerReader< $Request$>* reader, "
831                    "$Response$* response);\n");
832   } else if (ServerOnlyStreaming(method)) {
833     printer->Print(*vars,
834                    "virtual ::grpc::Status $Method$("
835                    "::grpc::ServerContext* context, const $Request$* request, "
836                    "::grpc::ServerWriter< $Response$>* writer);\n");
837   } else if (method->BidiStreaming()) {
838     printer->Print(
839         *vars,
840         "virtual ::grpc::Status $Method$("
841         "::grpc::ServerContext* context, "
842         "::grpc::ServerReaderWriter< $Response$, $Request$>* stream);"
843         "\n");
844   }
845   printer->Print(method->GetTrailingComments("//").c_str());
846 }
847 
848 // Helper generator. Disables the sync API for Request and Response, then adds
849 // in an async API for RealRequest and RealResponse types. This is to be used
850 // to generate async and raw async APIs.
PrintHeaderServerAsyncMethodsHelper(grpc_generator::Printer * printer,const grpc_generator::Method * method,std::map<std::string,std::string> * vars)851 void PrintHeaderServerAsyncMethodsHelper(
852     grpc_generator::Printer* printer, const grpc_generator::Method* method,
853     std::map<std::string, std::string>* vars) {
854   if (method->NoStreaming()) {
855     printer->Print(
856         *vars,
857         "// disable synchronous version of this method\n"
858         "::grpc::Status $Method$("
859         "::grpc::ServerContext* /*context*/, const $Request$* /*request*/, "
860         "$Response$* /*response*/) override {\n"
861         "  abort();\n"
862         "  return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
863         "}\n");
864     printer->Print(
865         *vars,
866         "void Request$Method$("
867         "::grpc::ServerContext* context, $RealRequest$* request, "
868         "::grpc::ServerAsyncResponseWriter< $RealResponse$>* response, "
869         "::grpc::CompletionQueue* new_call_cq, "
870         "::grpc::ServerCompletionQueue* notification_cq, void *tag) {\n");
871     printer->Print(*vars,
872                    "  ::grpc::Service::RequestAsyncUnary($Idx$, context, "
873                    "request, response, new_call_cq, notification_cq, tag);\n");
874     printer->Print("}\n");
875   } else if (ClientOnlyStreaming(method)) {
876     printer->Print(
877         *vars,
878         "// disable synchronous version of this method\n"
879         "::grpc::Status $Method$("
880         "::grpc::ServerContext* /*context*/, "
881         "::grpc::ServerReader< $Request$>* /*reader*/, "
882         "$Response$* /*response*/) override {\n"
883         "  abort();\n"
884         "  return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
885         "}\n");
886     printer->Print(
887         *vars,
888         "void Request$Method$("
889         "::grpc::ServerContext* context, "
890         "::grpc::ServerAsyncReader< $RealResponse$, $RealRequest$>* reader, "
891         "::grpc::CompletionQueue* new_call_cq, "
892         "::grpc::ServerCompletionQueue* notification_cq, void *tag) {\n");
893     printer->Print(*vars,
894                    "  ::grpc::Service::RequestAsyncClientStreaming($Idx$, "
895                    "context, reader, new_call_cq, notification_cq, tag);\n");
896     printer->Print("}\n");
897   } else if (ServerOnlyStreaming(method)) {
898     printer->Print(
899         *vars,
900         "// disable synchronous version of this method\n"
901         "::grpc::Status $Method$("
902         "::grpc::ServerContext* /*context*/, const $Request$* /*request*/, "
903         "::grpc::ServerWriter< $Response$>* /*writer*/) override "
904         "{\n"
905         "  abort();\n"
906         "  return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
907         "}\n");
908     printer->Print(
909         *vars,
910         "void Request$Method$("
911         "::grpc::ServerContext* context, $RealRequest$* request, "
912         "::grpc::ServerAsyncWriter< $RealResponse$>* writer, "
913         "::grpc::CompletionQueue* new_call_cq, "
914         "::grpc::ServerCompletionQueue* notification_cq, void *tag) {\n");
915     printer->Print(
916         *vars,
917         "  ::grpc::Service::RequestAsyncServerStreaming($Idx$, "
918         "context, request, writer, new_call_cq, notification_cq, tag);\n");
919     printer->Print("}\n");
920   } else if (method->BidiStreaming()) {
921     printer->Print(
922         *vars,
923         "// disable synchronous version of this method\n"
924         "::grpc::Status $Method$("
925         "::grpc::ServerContext* /*context*/, "
926         "::grpc::ServerReaderWriter< $Response$, $Request$>* /*stream*/) "
927         " override {\n"
928         "  abort();\n"
929         "  return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
930         "}\n");
931     printer->Print(
932         *vars,
933         "void Request$Method$("
934         "::grpc::ServerContext* context, "
935         "::grpc::ServerAsyncReaderWriter< $RealResponse$, $RealRequest$>* "
936         "stream, "
937         "::grpc::CompletionQueue* new_call_cq, "
938         "::grpc::ServerCompletionQueue* notification_cq, void *tag) {\n");
939     printer->Print(*vars,
940                    "  ::grpc::Service::RequestAsyncBidiStreaming($Idx$, "
941                    "context, stream, new_call_cq, notification_cq, tag);\n");
942     printer->Print("}\n");
943   }
944 }
945 
PrintHeaderServerMethodAsync(grpc_generator::Printer * printer,const grpc_generator::Method * method,std::map<std::string,std::string> * vars)946 void PrintHeaderServerMethodAsync(grpc_generator::Printer* printer,
947                                   const grpc_generator::Method* method,
948                                   std::map<std::string, std::string>* vars) {
949   (*vars)["Method"] = method->name();
950   // These will be disabled
951   (*vars)["Request"] = method->input_type_name();
952   (*vars)["Response"] = method->output_type_name();
953   // These will be used for the async API
954   (*vars)["RealRequest"] = method->input_type_name();
955   (*vars)["RealResponse"] = method->output_type_name();
956   printer->Print(*vars, "template <class BaseClass>\n");
957   printer->Print(*vars,
958                  "class WithAsyncMethod_$Method$ : public BaseClass {\n");
959   printer->Print(
960       " private:\n"
961       "  void BaseClassMustBeDerivedFromService(const Service* /*service*/) "
962       "{}\n");
963   printer->Print(" public:\n");
964   printer->Indent();
965   printer->Print(*vars,
966                  "WithAsyncMethod_$Method$() {\n"
967                  "  ::grpc::Service::MarkMethodAsync($Idx$);\n"
968                  "}\n");
969   printer->Print(*vars,
970                  "~WithAsyncMethod_$Method$() override {\n"
971                  "  BaseClassMustBeDerivedFromService(this);\n"
972                  "}\n");
973   PrintHeaderServerAsyncMethodsHelper(printer, method, vars);
974   printer->Outdent();
975   printer->Print(*vars, "};\n");
976 }
977 
978 // Helper generator. Disables the sync API for Request and Response, then adds
979 // in a callback API for RealRequest and RealResponse types. This is to be used
980 // to generate callback and raw callback APIs.
PrintHeaderServerCallbackMethodsHelper(grpc_generator::Printer * printer,const grpc_generator::Method * method,std::map<std::string,std::string> * vars)981 void PrintHeaderServerCallbackMethodsHelper(
982     grpc_generator::Printer* printer, const grpc_generator::Method* method,
983     std::map<std::string, std::string>* vars) {
984   if (method->NoStreaming()) {
985     printer->Print(
986         *vars,
987         "// disable synchronous version of this method\n"
988         "::grpc::Status $Method$("
989         "::grpc::ServerContext* /*context*/, const $Request$* /*request*/, "
990         "$Response$* /*response*/) override {\n"
991         "  abort();\n"
992         "  return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
993         "}\n");
994     printer->Print(*vars,
995                    "#ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL\n"
996                    "virtual ::grpc::ServerUnaryReactor* $Method$(\n"
997                    "  ::grpc::CallbackServerContext* /*context*/, "
998                    "const $RealRequest$* /*request*/, "
999                    "$RealResponse$* /*response*/)\n"
1000                    "#else\n"
1001                    "virtual ::grpc::experimental::ServerUnaryReactor* "
1002                    "$Method$(\n"
1003                    "  ::grpc::experimental::CallbackServerContext* "
1004                    "/*context*/, const $RealRequest$* /*request*/, "
1005                    "$RealResponse$* /*response*/)\n"
1006                    "#endif\n"
1007                    "  { return nullptr; }\n");
1008   } else if (ClientOnlyStreaming(method)) {
1009     printer->Print(
1010         *vars,
1011         "// disable synchronous version of this method\n"
1012         "::grpc::Status $Method$("
1013         "::grpc::ServerContext* /*context*/, "
1014         "::grpc::ServerReader< $Request$>* /*reader*/, "
1015         "$Response$* /*response*/) override {\n"
1016         "  abort();\n"
1017         "  return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
1018         "}\n");
1019     printer->Print(*vars,
1020                    "#ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL\n"
1021                    "virtual ::grpc::ServerReadReactor< "
1022                    "$RealRequest$>* $Method$(\n"
1023                    "  ::grpc::CallbackServerContext* "
1024                    "/*context*/, $RealResponse$* /*response*/)\n"
1025                    "#else\n"
1026                    "virtual ::grpc::experimental::ServerReadReactor< "
1027                    "$RealRequest$>* $Method$(\n"
1028                    "  ::grpc::experimental::CallbackServerContext* "
1029                    "/*context*/, $RealResponse$* /*response*/)\n"
1030                    "#endif\n"
1031                    "  { return nullptr; }\n");
1032   } else if (ServerOnlyStreaming(method)) {
1033     printer->Print(
1034         *vars,
1035         "// disable synchronous version of this method\n"
1036         "::grpc::Status $Method$("
1037         "::grpc::ServerContext* /*context*/, const $Request$* /*request*/, "
1038         "::grpc::ServerWriter< $Response$>* /*writer*/) override "
1039         "{\n"
1040         "  abort();\n"
1041         "  return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
1042         "}\n");
1043     printer->Print(
1044         *vars,
1045         "#ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL\n"
1046         "virtual ::grpc::ServerWriteReactor< $RealResponse$>* $Method$(\n"
1047         "  ::grpc::CallbackServerContext* "
1048         "/*context*/, const $RealRequest$* /*request*/)\n"
1049         "#else\n"
1050         "virtual ::grpc::experimental::ServerWriteReactor< $RealResponse$>* "
1051         "$Method$(\n"
1052         "  ::grpc::experimental::CallbackServerContext* "
1053         "/*context*/, const $RealRequest$* /*request*/)\n"
1054         "#endif\n"
1055         "  { return nullptr; }\n");
1056   } else if (method->BidiStreaming()) {
1057     printer->Print(
1058         *vars,
1059         "// disable synchronous version of this method\n"
1060         "::grpc::Status $Method$("
1061         "::grpc::ServerContext* /*context*/, "
1062         "::grpc::ServerReaderWriter< $Response$, $Request$>* /*stream*/) "
1063         " override {\n"
1064         "  abort();\n"
1065         "  return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
1066         "}\n");
1067     printer->Print(
1068         *vars,
1069         "#ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL\n"
1070         "virtual ::grpc::ServerBidiReactor< $RealRequest$, $RealResponse$>* "
1071         "$Method$(\n"
1072         "  ::grpc::CallbackServerContext* /*context*/)\n"
1073         "#else\n"
1074         "virtual ::grpc::experimental::ServerBidiReactor< "
1075         "$RealRequest$, $RealResponse$>* "
1076         "$Method$(\n"
1077         "  ::grpc::experimental::CallbackServerContext* /*context*/)\n"
1078         "#endif\n"
1079         "  { return nullptr; }\n");
1080   }
1081 }
1082 
PrintHeaderServerMethodCallback(grpc_generator::Printer * printer,const grpc_generator::Method * method,std::map<std::string,std::string> * vars)1083 void PrintHeaderServerMethodCallback(grpc_generator::Printer* printer,
1084                                      const grpc_generator::Method* method,
1085                                      std::map<std::string, std::string>* vars) {
1086   (*vars)["Method"] = method->name();
1087   // These will be disabled
1088   (*vars)["Request"] = method->input_type_name();
1089   (*vars)["Response"] = method->output_type_name();
1090   // These will be used for the callback API
1091   (*vars)["RealRequest"] = method->input_type_name();
1092   (*vars)["RealResponse"] = method->output_type_name();
1093   printer->Print(*vars, "template <class BaseClass>\n");
1094   printer->Print(
1095       *vars,
1096       "class ExperimentalWithCallbackMethod_$Method$ : public BaseClass {\n");
1097   printer->Print(
1098       " private:\n"
1099       "  void BaseClassMustBeDerivedFromService(const Service* /*service*/) "
1100       "{}\n");
1101   printer->Print(" public:\n");
1102   printer->Indent();
1103   printer->Print(*vars, "ExperimentalWithCallbackMethod_$Method$() {\n");
1104   if (method->NoStreaming()) {
1105     printer->Print(
1106         *vars,
1107         "#ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL\n"
1108         "  ::grpc::Service::\n"
1109         "#else\n"
1110         "  ::grpc::Service::experimental().\n"
1111         "#endif\n"
1112         "    MarkMethodCallback($Idx$,\n"
1113         "      new ::grpc_impl::internal::CallbackUnaryHandler< "
1114         "$RealRequest$, $RealResponse$>(\n"
1115         "        [this](\n"
1116         "#ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL\n"
1117         "               ::grpc::CallbackServerContext*\n"
1118         "#else\n"
1119         "               ::grpc::experimental::CallbackServerContext*\n"
1120         "#endif\n"
1121         "                 context, "
1122         "const $RealRequest$* "
1123         "request, "
1124         "$RealResponse$* response) { "
1125         "return this->$Method$(context, request, response); }));}\n");
1126     printer->Print(*vars,
1127                    "void SetMessageAllocatorFor_$Method$(\n"
1128                    "    ::grpc::experimental::MessageAllocator< "
1129                    "$RealRequest$, $RealResponse$>* allocator) {\n"
1130                    "#ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL\n"
1131                    "  ::grpc::internal::MethodHandler* const handler = "
1132                    "::grpc::Service::GetHandler($Idx$);\n"
1133                    "#else\n"
1134                    "  ::grpc::internal::MethodHandler* const handler = "
1135                    "::grpc::Service::experimental().GetHandler($Idx$);\n"
1136                    "#endif\n"
1137                    "  static_cast<::grpc_impl::internal::CallbackUnaryHandler< "
1138                    "$RealRequest$, $RealResponse$>*>(handler)\n"
1139                    "          ->SetMessageAllocator(allocator);\n");
1140   } else if (ClientOnlyStreaming(method)) {
1141     printer->Print(
1142         *vars,
1143         "#ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL\n"
1144         "  ::grpc::Service::\n"
1145         "#else\n"
1146         "  ::grpc::Service::experimental().\n"
1147         "#endif\n"
1148         "    MarkMethodCallback($Idx$,\n"
1149         "      new ::grpc_impl::internal::CallbackClientStreamingHandler< "
1150         "$RealRequest$, $RealResponse$>(\n"
1151         "        [this](\n"
1152         "#ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL\n"
1153         "               ::grpc::CallbackServerContext*\n"
1154         "#else\n"
1155         "               ::grpc::experimental::CallbackServerContext*\n"
1156         "#endif\n"
1157         "                 context, "
1158         "$RealResponse$* "
1159         "response) { "
1160         "return this->$Method$(context, response); }));\n");
1161   } else if (ServerOnlyStreaming(method)) {
1162     printer->Print(
1163         *vars,
1164         "#ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL\n"
1165         "  ::grpc::Service::\n"
1166         "#else\n"
1167         "  ::grpc::Service::experimental().\n"
1168         "#endif\n"
1169         "    MarkMethodCallback($Idx$,\n"
1170         "      new ::grpc_impl::internal::CallbackServerStreamingHandler< "
1171         "$RealRequest$, $RealResponse$>(\n"
1172         "        [this](\n"
1173         "#ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL\n"
1174         "               ::grpc::CallbackServerContext*\n"
1175         "#else\n"
1176         "               ::grpc::experimental::CallbackServerContext*\n"
1177         "#endif\n"
1178         "                 context, "
1179         "const $RealRequest$* "
1180         "request) { "
1181         "return this->$Method$(context, request); }));\n");
1182   } else if (method->BidiStreaming()) {
1183     printer->Print(
1184         *vars,
1185         "#ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL\n"
1186         "  ::grpc::Service::\n"
1187         "#else\n"
1188         "  ::grpc::Service::experimental().\n"
1189         "#endif\n"
1190         "    MarkMethodCallback($Idx$,\n"
1191         "      new ::grpc_impl::internal::CallbackBidiHandler< "
1192         "$RealRequest$, $RealResponse$>(\n"
1193         "        [this](\n"
1194         "#ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL\n"
1195         "               ::grpc::CallbackServerContext*\n"
1196         "#else\n"
1197         "               ::grpc::experimental::CallbackServerContext*\n"
1198         "#endif\n"
1199         "                 context) "
1200         "{ return this->$Method$(context); }));\n");
1201   }
1202   printer->Print(*vars, "}\n");
1203   printer->Print(*vars,
1204                  "~ExperimentalWithCallbackMethod_$Method$() override {\n"
1205                  "  BaseClassMustBeDerivedFromService(this);\n"
1206                  "}\n");
1207   PrintHeaderServerCallbackMethodsHelper(printer, method, vars);
1208   printer->Outdent();
1209   printer->Print(*vars, "};\n");
1210 }
1211 
PrintHeaderServerMethodRawCallback(grpc_generator::Printer * printer,const grpc_generator::Method * method,std::map<std::string,std::string> * vars)1212 void PrintHeaderServerMethodRawCallback(
1213     grpc_generator::Printer* printer, const grpc_generator::Method* method,
1214     std::map<std::string, std::string>* vars) {
1215   (*vars)["Method"] = method->name();
1216   // These will be disabled
1217   (*vars)["Request"] = method->input_type_name();
1218   (*vars)["Response"] = method->output_type_name();
1219   // These will be used for raw API
1220   (*vars)["RealRequest"] = "::grpc::ByteBuffer";
1221   (*vars)["RealResponse"] = "::grpc::ByteBuffer";
1222   printer->Print(*vars, "template <class BaseClass>\n");
1223   printer->Print(*vars,
1224                  "class ExperimentalWithRawCallbackMethod_$Method$ : public "
1225                  "BaseClass {\n");
1226   printer->Print(
1227       " private:\n"
1228       "  void BaseClassMustBeDerivedFromService(const Service* /*service*/) "
1229       "{}\n");
1230   printer->Print(" public:\n");
1231   printer->Indent();
1232   printer->Print(*vars, "ExperimentalWithRawCallbackMethod_$Method$() {\n");
1233   if (method->NoStreaming()) {
1234     printer->Print(
1235         *vars,
1236         "#ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL\n"
1237         "  ::grpc::Service::\n"
1238         "#else\n"
1239         "  ::grpc::Service::experimental().\n"
1240         "#endif\n"
1241         "    MarkMethodRawCallback($Idx$,\n"
1242         "      new ::grpc_impl::internal::CallbackUnaryHandler< "
1243         "$RealRequest$, $RealResponse$>(\n"
1244         "        [this](\n"
1245         "#ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL\n"
1246         "               ::grpc::CallbackServerContext*\n"
1247         "#else\n"
1248         "               ::grpc::experimental::CallbackServerContext*\n"
1249         "#endif\n"
1250         "                 context, "
1251         "const $RealRequest$* "
1252         "request, "
1253         "$RealResponse$* response) { return "
1254         "this->$Method$(context, request, response); }));\n");
1255   } else if (ClientOnlyStreaming(method)) {
1256     printer->Print(
1257         *vars,
1258         "#ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL\n"
1259         "  ::grpc::Service::\n"
1260         "#else\n"
1261         "  ::grpc::Service::experimental().\n"
1262         "#endif\n"
1263         "    MarkMethodRawCallback($Idx$,\n"
1264         "      new ::grpc_impl::internal::CallbackClientStreamingHandler< "
1265         "$RealRequest$, $RealResponse$>(\n"
1266         "        [this](\n"
1267         "#ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL\n"
1268         "               ::grpc::CallbackServerContext*\n"
1269         "#else\n"
1270         "               ::grpc::experimental::CallbackServerContext*\n"
1271         "#endif\n"
1272         "                 context, "
1273         "$RealResponse$* response) "
1274         "{ return this->$Method$(context, response); }));\n");
1275   } else if (ServerOnlyStreaming(method)) {
1276     printer->Print(
1277         *vars,
1278         "#ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL\n"
1279         "  ::grpc::Service::\n"
1280         "#else\n"
1281         "  ::grpc::Service::experimental().\n"
1282         "#endif\n"
1283         "    MarkMethodRawCallback($Idx$,\n"
1284         "      new ::grpc_impl::internal::CallbackServerStreamingHandler< "
1285         "$RealRequest$, $RealResponse$>(\n"
1286         "        [this](\n"
1287         "#ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL\n"
1288         "               ::grpc::CallbackServerContext*\n"
1289         "#else\n"
1290         "               ::grpc::experimental::CallbackServerContext*\n"
1291         "#endif\n"
1292         "                 context, "
1293         "const"
1294         "$RealRequest$* request) { return "
1295         "this->$Method$(context, request); }));\n");
1296   } else if (method->BidiStreaming()) {
1297     printer->Print(
1298         *vars,
1299         "#ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL\n"
1300         "  ::grpc::Service::\n"
1301         "#else\n"
1302         "  ::grpc::Service::experimental().\n"
1303         "#endif\n"
1304         "    MarkMethodRawCallback($Idx$,\n"
1305         "      new ::grpc_impl::internal::CallbackBidiHandler< "
1306         "$RealRequest$, $RealResponse$>(\n"
1307         "        [this](\n"
1308         "#ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL\n"
1309         "               ::grpc::CallbackServerContext*\n"
1310         "#else\n"
1311         "               ::grpc::experimental::CallbackServerContext*\n"
1312         "#endif\n"
1313         "                 context) "
1314         "{ return this->$Method$(context); }));\n");
1315   }
1316   printer->Print(*vars, "}\n");
1317   printer->Print(*vars,
1318                  "~ExperimentalWithRawCallbackMethod_$Method$() override {\n"
1319                  "  BaseClassMustBeDerivedFromService(this);\n"
1320                  "}\n");
1321   PrintHeaderServerCallbackMethodsHelper(printer, method, vars);
1322   printer->Outdent();
1323   printer->Print(*vars, "};\n");
1324 }
1325 
PrintHeaderServerMethodStreamedUnary(grpc_generator::Printer * printer,const grpc_generator::Method * method,std::map<std::string,std::string> * vars)1326 void PrintHeaderServerMethodStreamedUnary(
1327     grpc_generator::Printer* printer, const grpc_generator::Method* method,
1328     std::map<std::string, std::string>* vars) {
1329   (*vars)["Method"] = method->name();
1330   (*vars)["Request"] = method->input_type_name();
1331   (*vars)["Response"] = method->output_type_name();
1332   if (method->NoStreaming()) {
1333     printer->Print(*vars, "template <class BaseClass>\n");
1334     printer->Print(*vars,
1335                    "class WithStreamedUnaryMethod_$Method$ : "
1336                    "public BaseClass {\n");
1337     printer->Print(
1338         " private:\n"
1339         "  void BaseClassMustBeDerivedFromService(const Service* /*service*/) "
1340         "{}\n");
1341     printer->Print(" public:\n");
1342     printer->Indent();
1343     printer->Print(*vars,
1344                    "WithStreamedUnaryMethod_$Method$() {\n"
1345                    "  ::grpc::Service::MarkMethodStreamed($Idx$,\n"
1346                    "    new ::grpc::internal::StreamedUnaryHandler<\n"
1347                    "      $Request$, $Response$>(\n"
1348                    "        [this](::grpc_impl::ServerContext* context,\n"
1349                    "               ::grpc_impl::ServerUnaryStreamer<\n"
1350                    "                 $Request$, $Response$>* streamer) {\n"
1351                    "                   return this->Streamed$Method$(context,\n"
1352                    "                     streamer);\n"
1353                    "              }));\n"
1354                    "}\n");
1355     printer->Print(*vars,
1356                    "~WithStreamedUnaryMethod_$Method$() override {\n"
1357                    "  BaseClassMustBeDerivedFromService(this);\n"
1358                    "}\n");
1359     printer->Print(
1360         *vars,
1361         "// disable regular version of this method\n"
1362         "::grpc::Status $Method$("
1363         "::grpc::ServerContext* /*context*/, const $Request$* /*request*/, "
1364         "$Response$* /*response*/) override {\n"
1365         "  abort();\n"
1366         "  return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
1367         "}\n");
1368     printer->Print(*vars,
1369                    "// replace default version of method with streamed unary\n"
1370                    "virtual ::grpc::Status Streamed$Method$("
1371                    "::grpc::ServerContext* context, "
1372                    "::grpc::ServerUnaryStreamer< "
1373                    "$Request$,$Response$>* server_unary_streamer)"
1374                    " = 0;\n");
1375     printer->Outdent();
1376     printer->Print(*vars, "};\n");
1377   }
1378 }
1379 
PrintHeaderServerMethodSplitStreaming(grpc_generator::Printer * printer,const grpc_generator::Method * method,std::map<std::string,std::string> * vars)1380 void PrintHeaderServerMethodSplitStreaming(
1381     grpc_generator::Printer* printer, const grpc_generator::Method* method,
1382     std::map<std::string, std::string>* vars) {
1383   (*vars)["Method"] = method->name();
1384   (*vars)["Request"] = method->input_type_name();
1385   (*vars)["Response"] = method->output_type_name();
1386   if (ServerOnlyStreaming(method)) {
1387     printer->Print(*vars, "template <class BaseClass>\n");
1388     printer->Print(*vars,
1389                    "class WithSplitStreamingMethod_$Method$ : "
1390                    "public BaseClass {\n");
1391     printer->Print(
1392         " private:\n"
1393         "  void BaseClassMustBeDerivedFromService(const Service* /*service*/) "
1394         "{}\n");
1395     printer->Print(" public:\n");
1396     printer->Indent();
1397     printer->Print(*vars,
1398                    "WithSplitStreamingMethod_$Method$() {\n"
1399                    "  ::grpc::Service::MarkMethodStreamed($Idx$,\n"
1400                    "    new ::grpc::internal::SplitServerStreamingHandler<\n"
1401                    "      $Request$, $Response$>(\n"
1402                    "        [this](::grpc_impl::ServerContext* context,\n"
1403                    "               ::grpc_impl::ServerSplitStreamer<\n"
1404                    "                 $Request$, $Response$>* streamer) {\n"
1405                    "                   return this->Streamed$Method$(context,\n"
1406                    "                     streamer);\n"
1407                    "              }));\n"
1408                    "}\n");
1409     printer->Print(*vars,
1410                    "~WithSplitStreamingMethod_$Method$() override {\n"
1411                    "  BaseClassMustBeDerivedFromService(this);\n"
1412                    "}\n");
1413     printer->Print(
1414         *vars,
1415         "// disable regular version of this method\n"
1416         "::grpc::Status $Method$("
1417         "::grpc::ServerContext* /*context*/, const $Request$* /*request*/, "
1418         "::grpc::ServerWriter< $Response$>* /*writer*/) override "
1419         "{\n"
1420         "  abort();\n"
1421         "  return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
1422         "}\n");
1423     printer->Print(*vars,
1424                    "// replace default version of method with split streamed\n"
1425                    "virtual ::grpc::Status Streamed$Method$("
1426                    "::grpc::ServerContext* context, "
1427                    "::grpc::ServerSplitStreamer< "
1428                    "$Request$,$Response$>* server_split_streamer)"
1429                    " = 0;\n");
1430     printer->Outdent();
1431     printer->Print(*vars, "};\n");
1432   }
1433 }
1434 
PrintHeaderServerMethodGeneric(grpc_generator::Printer * printer,const grpc_generator::Method * method,std::map<std::string,std::string> * vars)1435 void PrintHeaderServerMethodGeneric(grpc_generator::Printer* printer,
1436                                     const grpc_generator::Method* method,
1437                                     std::map<std::string, std::string>* vars) {
1438   (*vars)["Method"] = method->name();
1439   (*vars)["Request"] = method->input_type_name();
1440   (*vars)["Response"] = method->output_type_name();
1441   printer->Print(*vars, "template <class BaseClass>\n");
1442   printer->Print(*vars,
1443                  "class WithGenericMethod_$Method$ : public BaseClass {\n");
1444   printer->Print(
1445       " private:\n"
1446       "  void BaseClassMustBeDerivedFromService(const Service* /*service*/) "
1447       "{}\n");
1448   printer->Print(" public:\n");
1449   printer->Indent();
1450   printer->Print(*vars,
1451                  "WithGenericMethod_$Method$() {\n"
1452                  "  ::grpc::Service::MarkMethodGeneric($Idx$);\n"
1453                  "}\n");
1454   printer->Print(*vars,
1455                  "~WithGenericMethod_$Method$() override {\n"
1456                  "  BaseClassMustBeDerivedFromService(this);\n"
1457                  "}\n");
1458   if (method->NoStreaming()) {
1459     printer->Print(
1460         *vars,
1461         "// disable synchronous version of this method\n"
1462         "::grpc::Status $Method$("
1463         "::grpc::ServerContext* /*context*/, const $Request$* /*request*/, "
1464         "$Response$* /*response*/) override {\n"
1465         "  abort();\n"
1466         "  return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
1467         "}\n");
1468   } else if (ClientOnlyStreaming(method)) {
1469     printer->Print(
1470         *vars,
1471         "// disable synchronous version of this method\n"
1472         "::grpc::Status $Method$("
1473         "::grpc::ServerContext* /*context*/, "
1474         "::grpc::ServerReader< $Request$>* /*reader*/, "
1475         "$Response$* /*response*/) override {\n"
1476         "  abort();\n"
1477         "  return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
1478         "}\n");
1479   } else if (ServerOnlyStreaming(method)) {
1480     printer->Print(
1481         *vars,
1482         "// disable synchronous version of this method\n"
1483         "::grpc::Status $Method$("
1484         "::grpc::ServerContext* /*context*/, const $Request$* /*request*/, "
1485         "::grpc::ServerWriter< $Response$>* /*writer*/) override "
1486         "{\n"
1487         "  abort();\n"
1488         "  return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
1489         "}\n");
1490   } else if (method->BidiStreaming()) {
1491     printer->Print(
1492         *vars,
1493         "// disable synchronous version of this method\n"
1494         "::grpc::Status $Method$("
1495         "::grpc::ServerContext* /*context*/, "
1496         "::grpc::ServerReaderWriter< $Response$, $Request$>* /*stream*/) "
1497         " override {\n"
1498         "  abort();\n"
1499         "  return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
1500         "}\n");
1501   }
1502   printer->Outdent();
1503   printer->Print(*vars, "};\n");
1504 }
1505 
PrintHeaderServerMethodRaw(grpc_generator::Printer * printer,const grpc_generator::Method * method,std::map<std::string,std::string> * vars)1506 void PrintHeaderServerMethodRaw(grpc_generator::Printer* printer,
1507                                 const grpc_generator::Method* method,
1508                                 std::map<std::string, std::string>* vars) {
1509   (*vars)["Method"] = method->name();
1510   // These will be disabled
1511   (*vars)["Request"] = method->input_type_name();
1512   (*vars)["Response"] = method->output_type_name();
1513   // These will be used for raw API
1514   (*vars)["RealRequest"] = "::grpc::ByteBuffer";
1515   (*vars)["RealResponse"] = "::grpc::ByteBuffer";
1516   printer->Print(*vars, "template <class BaseClass>\n");
1517   printer->Print(*vars, "class WithRawMethod_$Method$ : public BaseClass {\n");
1518   printer->Print(
1519       " private:\n"
1520       "  void BaseClassMustBeDerivedFromService(const Service* /*service*/) "
1521       "{}\n");
1522   printer->Print(" public:\n");
1523   printer->Indent();
1524   printer->Print(*vars,
1525                  "WithRawMethod_$Method$() {\n"
1526                  "  ::grpc::Service::MarkMethodRaw($Idx$);\n"
1527                  "}\n");
1528   printer->Print(*vars,
1529                  "~WithRawMethod_$Method$() override {\n"
1530                  "  BaseClassMustBeDerivedFromService(this);\n"
1531                  "}\n");
1532   PrintHeaderServerAsyncMethodsHelper(printer, method, vars);
1533   printer->Outdent();
1534   printer->Print(*vars, "};\n");
1535 }
1536 
PrintHeaderService(grpc_generator::Printer * printer,const grpc_generator::Service * service,std::map<std::string,std::string> * vars)1537 void PrintHeaderService(grpc_generator::Printer* printer,
1538                         const grpc_generator::Service* service,
1539                         std::map<std::string, std::string>* vars) {
1540   (*vars)["Service"] = service->name();
1541 
1542   printer->Print(service->GetLeadingComments("//").c_str());
1543   printer->Print(*vars,
1544                  "class $Service$ final {\n"
1545                  " public:\n");
1546   printer->Indent();
1547 
1548   // Service metadata
1549   printer->Print(*vars,
1550                  "static constexpr char const* service_full_name() {\n"
1551                  "  return \"$Package$$Service$\";\n"
1552                  "}\n");
1553 
1554   // Client side
1555   printer->Print(
1556       "class StubInterface {\n"
1557       " public:\n");
1558   printer->Indent();
1559   printer->Print("virtual ~StubInterface() {}\n");
1560   for (int i = 0; i < service->method_count(); ++i) {
1561     printer->Print(service->method(i)->GetLeadingComments("//").c_str());
1562     PrintHeaderClientMethodInterfaces(printer, service->method(i).get(), vars,
1563                                       true);
1564     printer->Print(service->method(i)->GetTrailingComments("//").c_str());
1565   }
1566   PrintHeaderClientMethodCallbackInterfacesStart(printer, vars);
1567   for (int i = 0; i < service->method_count(); ++i) {
1568     printer->Print(service->method(i)->GetLeadingComments("//").c_str());
1569     PrintHeaderClientMethodCallbackInterfaces(printer, service->method(i).get(),
1570                                               vars);
1571     printer->Print(service->method(i)->GetTrailingComments("//").c_str());
1572   }
1573   PrintHeaderClientMethodCallbackInterfacesEnd(printer, vars);
1574   printer->Outdent();
1575   printer->Print("private:\n");
1576   printer->Indent();
1577   for (int i = 0; i < service->method_count(); ++i) {
1578     PrintHeaderClientMethodInterfaces(printer, service->method(i).get(), vars,
1579                                       false);
1580   }
1581   printer->Outdent();
1582   printer->Print("};\n");
1583   printer->Print(
1584       "class Stub final : public StubInterface"
1585       " {\n public:\n");
1586   printer->Indent();
1587   printer->Print(
1588       "Stub(const std::shared_ptr< ::grpc::ChannelInterface>& "
1589       "channel);\n");
1590   for (int i = 0; i < service->method_count(); ++i) {
1591     PrintHeaderClientMethod(printer, service->method(i).get(), vars, true);
1592   }
1593   PrintHeaderClientMethodCallbackStart(printer, vars);
1594   for (int i = 0; i < service->method_count(); ++i) {
1595     PrintHeaderClientMethodCallback(printer, service->method(i).get(), vars);
1596   }
1597   PrintHeaderClientMethodCallbackEnd(printer, vars);
1598   printer->Outdent();
1599   printer->Print("\n private:\n");
1600   printer->Indent();
1601   printer->Print("std::shared_ptr< ::grpc::ChannelInterface> channel_;\n");
1602   printer->Print("class experimental_async async_stub_{this};\n");
1603   for (int i = 0; i < service->method_count(); ++i) {
1604     PrintHeaderClientMethod(printer, service->method(i).get(), vars, false);
1605   }
1606   for (int i = 0; i < service->method_count(); ++i) {
1607     PrintHeaderClientMethodData(printer, service->method(i).get(), vars);
1608   }
1609   printer->Outdent();
1610   printer->Print("};\n");
1611   printer->Print(
1612       "static std::unique_ptr<Stub> NewStub(const std::shared_ptr< "
1613       "::grpc::ChannelInterface>& channel, "
1614       "const ::grpc::StubOptions& options = ::grpc::StubOptions());\n");
1615 
1616   printer->Print("\n");
1617 
1618   // Server side - base
1619   printer->Print(
1620       "class Service : public ::grpc::Service {\n"
1621       " public:\n");
1622   printer->Indent();
1623   printer->Print("Service();\n");
1624   printer->Print("virtual ~Service();\n");
1625   for (int i = 0; i < service->method_count(); ++i) {
1626     PrintHeaderServerMethodSync(printer, service->method(i).get(), vars);
1627   }
1628   printer->Outdent();
1629   printer->Print("};\n");
1630 
1631   // Server side - Asynchronous
1632   for (int i = 0; i < service->method_count(); ++i) {
1633     (*vars)["Idx"] = as_string(i);
1634     PrintHeaderServerMethodAsync(printer, service->method(i).get(), vars);
1635   }
1636 
1637   printer->Print("typedef ");
1638 
1639   for (int i = 0; i < service->method_count(); ++i) {
1640     (*vars)["method_name"] = service->method(i)->name();
1641     printer->Print(*vars, "WithAsyncMethod_$method_name$<");
1642   }
1643   printer->Print("Service");
1644   for (int i = 0; i < service->method_count(); ++i) {
1645     printer->Print(" >");
1646   }
1647   printer->Print(" AsyncService;\n");
1648 
1649   // Server side - Callback
1650   for (int i = 0; i < service->method_count(); ++i) {
1651     (*vars)["Idx"] = as_string(i);
1652     PrintHeaderServerMethodCallback(printer, service->method(i).get(), vars);
1653   }
1654 
1655   printer->Print("#ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL\n");
1656   printer->Print("typedef ");
1657 
1658   for (int i = 0; i < service->method_count(); ++i) {
1659     (*vars)["method_name"] = service->method(i)->name();
1660     printer->Print(*vars, "ExperimentalWithCallbackMethod_$method_name$<");
1661   }
1662   printer->Print("Service");
1663   for (int i = 0; i < service->method_count(); ++i) {
1664     printer->Print(" >");
1665   }
1666   printer->Print(" CallbackService;\n");
1667   printer->Print("#endif\n\n");
1668 
1669   printer->Print("typedef ");
1670 
1671   for (int i = 0; i < service->method_count(); ++i) {
1672     (*vars)["method_name"] = service->method(i)->name();
1673     printer->Print(*vars, "ExperimentalWithCallbackMethod_$method_name$<");
1674   }
1675   printer->Print("Service");
1676   for (int i = 0; i < service->method_count(); ++i) {
1677     printer->Print(" >");
1678   }
1679   printer->Print(" ExperimentalCallbackService;\n");
1680 
1681   // Server side - Generic
1682   for (int i = 0; i < service->method_count(); ++i) {
1683     (*vars)["Idx"] = as_string(i);
1684     PrintHeaderServerMethodGeneric(printer, service->method(i).get(), vars);
1685   }
1686 
1687   // Server side - Raw
1688   for (int i = 0; i < service->method_count(); ++i) {
1689     (*vars)["Idx"] = as_string(i);
1690     PrintHeaderServerMethodRaw(printer, service->method(i).get(), vars);
1691   }
1692 
1693   // Server side - Raw Callback
1694   for (int i = 0; i < service->method_count(); ++i) {
1695     (*vars)["Idx"] = as_string(i);
1696     PrintHeaderServerMethodRawCallback(printer, service->method(i).get(), vars);
1697   }
1698 
1699   // Server side - Streamed Unary
1700   for (int i = 0; i < service->method_count(); ++i) {
1701     (*vars)["Idx"] = as_string(i);
1702     PrintHeaderServerMethodStreamedUnary(printer, service->method(i).get(),
1703                                          vars);
1704   }
1705 
1706   printer->Print("typedef ");
1707   for (int i = 0; i < service->method_count(); ++i) {
1708     (*vars)["method_name"] = service->method(i)->name();
1709     if (service->method(i)->NoStreaming()) {
1710       printer->Print(*vars, "WithStreamedUnaryMethod_$method_name$<");
1711     }
1712   }
1713   printer->Print("Service");
1714   for (int i = 0; i < service->method_count(); ++i) {
1715     if (service->method(i)->NoStreaming()) {
1716       printer->Print(" >");
1717     }
1718   }
1719   printer->Print(" StreamedUnaryService;\n");
1720 
1721   // Server side - controlled server-side streaming
1722   for (int i = 0; i < service->method_count(); ++i) {
1723     (*vars)["Idx"] = as_string(i);
1724     PrintHeaderServerMethodSplitStreaming(printer, service->method(i).get(),
1725                                           vars);
1726   }
1727 
1728   printer->Print("typedef ");
1729   for (int i = 0; i < service->method_count(); ++i) {
1730     (*vars)["method_name"] = service->method(i)->name();
1731     auto method = service->method(i);
1732     if (ServerOnlyStreaming(method.get())) {
1733       printer->Print(*vars, "WithSplitStreamingMethod_$method_name$<");
1734     }
1735   }
1736   printer->Print("Service");
1737   for (int i = 0; i < service->method_count(); ++i) {
1738     auto method = service->method(i);
1739     if (ServerOnlyStreaming(method.get())) {
1740       printer->Print(" >");
1741     }
1742   }
1743   printer->Print(" SplitStreamedService;\n");
1744 
1745   // Server side - typedef for controlled both unary and server-side streaming
1746   printer->Print("typedef ");
1747   for (int i = 0; i < service->method_count(); ++i) {
1748     (*vars)["method_name"] = service->method(i)->name();
1749     auto method = service->method(i);
1750     if (ServerOnlyStreaming(method.get())) {
1751       printer->Print(*vars, "WithSplitStreamingMethod_$method_name$<");
1752     }
1753     if (service->method(i)->NoStreaming()) {
1754       printer->Print(*vars, "WithStreamedUnaryMethod_$method_name$<");
1755     }
1756   }
1757   printer->Print("Service");
1758   for (int i = 0; i < service->method_count(); ++i) {
1759     auto method = service->method(i);
1760     if (service->method(i)->NoStreaming() ||
1761         ServerOnlyStreaming(method.get())) {
1762       printer->Print(" >");
1763     }
1764   }
1765   printer->Print(" StreamedService;\n");
1766 
1767   printer->Outdent();
1768   printer->Print("};\n");
1769   printer->Print(service->GetTrailingComments("//").c_str());
1770 }
1771 
GetHeaderServices(grpc_generator::File * file,const Parameters & params)1772 std::string GetHeaderServices(grpc_generator::File* file,
1773                               const Parameters& params) {
1774   std::string output;
1775   {
1776     // Scope the output stream so it closes and finalizes output to the string.
1777     auto printer = file->CreatePrinter(&output);
1778     std::map<std::string, std::string> vars;
1779     // Package string is empty or ends with a dot. It is used to fully qualify
1780     // method names.
1781     vars["Package"] = file->package();
1782     if (!file->package().empty()) {
1783       vars["Package"].append(".");
1784     }
1785 
1786     if (!params.services_namespace.empty()) {
1787       vars["services_namespace"] = params.services_namespace;
1788       printer->Print(vars, "\nnamespace $services_namespace$ {\n\n");
1789     }
1790 
1791     for (int i = 0; i < file->service_count(); ++i) {
1792       PrintHeaderService(printer.get(), file->service(i).get(), &vars);
1793       printer->Print("\n");
1794     }
1795 
1796     if (!params.services_namespace.empty()) {
1797       printer->Print(vars, "}  // namespace $services_namespace$\n\n");
1798     }
1799   }
1800   return output;
1801 }
1802 
GetHeaderEpilogue(grpc_generator::File * file,const Parameters &)1803 std::string GetHeaderEpilogue(grpc_generator::File* file,
1804                               const Parameters& /*params*/) {
1805   std::string output;
1806   {
1807     // Scope the output stream so it closes and finalizes output to the string.
1808     auto printer = file->CreatePrinter(&output);
1809     std::map<std::string, std::string> vars;
1810 
1811     vars["filename"] = file->filename();
1812     vars["filename_identifier"] = FilenameIdentifier(file->filename());
1813 
1814     if (!file->package().empty()) {
1815       std::vector<std::string> parts = file->package_parts();
1816 
1817       for (auto part = parts.rbegin(); part != parts.rend(); part++) {
1818         vars["part"] = *part;
1819         printer->Print(vars, "}  // namespace $part$\n");
1820       }
1821       printer->Print(vars, "\n");
1822     }
1823 
1824     printer->Print(vars, "\n");
1825     printer->Print(vars, "#endif  // GRPC_$filename_identifier$__INCLUDED\n");
1826 
1827     printer->Print(file->GetTrailingComments("//").c_str());
1828   }
1829   return output;
1830 }
1831 
GetSourcePrologue(grpc_generator::File * file,const Parameters & params)1832 std::string GetSourcePrologue(grpc_generator::File* file,
1833                               const Parameters& params) {
1834   std::string output;
1835   {
1836     // Scope the output stream so it closes and finalizes output to the string.
1837     auto printer = file->CreatePrinter(&output);
1838     std::map<std::string, std::string> vars;
1839 
1840     vars["filename"] = file->filename();
1841     vars["filename_base"] = file->filename_without_ext();
1842     vars["message_header_ext"] = params.message_header_extension.empty()
1843                                      ? kCppGeneratorMessageHeaderExt
1844                                      : params.message_header_extension;
1845     vars["service_header_ext"] = kCppGeneratorServiceHeaderExt;
1846 
1847     printer->Print(vars, "// Generated by the gRPC C++ plugin.\n");
1848     printer->Print(vars,
1849                    "// If you make any local change, they will be lost.\n");
1850     printer->Print(vars, "// source: $filename$\n\n");
1851 
1852     printer->Print(vars, "#include \"$filename_base$$message_header_ext$\"\n");
1853     printer->Print(vars, "#include \"$filename_base$$service_header_ext$\"\n");
1854     printer->Print(vars, "\n");
1855   }
1856   return output;
1857 }
1858 
GetSourceIncludes(grpc_generator::File * file,const Parameters & params)1859 std::string GetSourceIncludes(grpc_generator::File* file,
1860                               const Parameters& params) {
1861   std::string output;
1862   {
1863     // Scope the output stream so it closes and finalizes output to the string.
1864     auto printer = file->CreatePrinter(&output);
1865     std::map<std::string, std::string> vars;
1866     static const char* headers_strs[] = {
1867         "functional",
1868         "grpcpp/impl/codegen/async_stream.h",
1869         "grpcpp/impl/codegen/async_unary_call.h",
1870         "grpcpp/impl/codegen/channel_interface.h",
1871         "grpcpp/impl/codegen/client_unary_call.h",
1872         "grpcpp/impl/codegen/client_callback.h",
1873         "grpcpp/impl/codegen/message_allocator.h",
1874         "grpcpp/impl/codegen/method_handler.h",
1875         "grpcpp/impl/codegen/rpc_service_method.h",
1876         "grpcpp/impl/codegen/server_callback.h",
1877         "grpcpp/impl/codegen/server_callback_handlers.h",
1878         "grpcpp/impl/codegen/server_context.h",
1879         "grpcpp/impl/codegen/service_type.h",
1880         "grpcpp/impl/codegen/sync_stream.h"};
1881     std::vector<std::string> headers(headers_strs, array_end(headers_strs));
1882     PrintIncludes(printer.get(), headers, params.use_system_headers,
1883                   params.grpc_search_path);
1884 
1885     if (!file->package().empty()) {
1886       std::vector<std::string> parts = file->package_parts();
1887 
1888       for (auto part = parts.begin(); part != parts.end(); part++) {
1889         vars["part"] = *part;
1890         printer->Print(vars, "namespace $part$ {\n");
1891       }
1892     }
1893 
1894     printer->Print(vars, "\n");
1895   }
1896   return output;
1897 }
1898 
PrintSourceClientMethod(grpc_generator::Printer * printer,const grpc_generator::Method * method,std::map<std::string,std::string> * vars)1899 void PrintSourceClientMethod(grpc_generator::Printer* printer,
1900                              const grpc_generator::Method* method,
1901                              std::map<std::string, std::string>* vars) {
1902   (*vars)["Method"] = method->name();
1903   (*vars)["Request"] = method->input_type_name();
1904   (*vars)["Response"] = method->output_type_name();
1905   struct {
1906     std::string prefix;
1907     std::string start;          // bool literal expressed as string
1908     std::string method_params;  // extra arguments to method
1909     std::string create_args;    // extra arguments to creator
1910   } async_prefixes[] = {{"Async", "true", ", void* tag", ", tag"},
1911                         {"PrepareAsync", "false", "", ", nullptr"}};
1912   if (method->NoStreaming()) {
1913     printer->Print(*vars,
1914                    "::grpc::Status $ns$$Service$::Stub::$Method$("
1915                    "::grpc::ClientContext* context, "
1916                    "const $Request$& request, $Response$* response) {\n");
1917     printer->Print(*vars,
1918                    "  return ::grpc::internal::BlockingUnaryCall"
1919                    "(channel_.get(), rpcmethod_$Method$_, "
1920                    "context, request, response);\n}\n\n");
1921 
1922     printer->Print(*vars,
1923                    "void $ns$$Service$::Stub::experimental_async::$Method$("
1924                    "::grpc::ClientContext* context, "
1925                    "const $Request$* request, $Response$* response, "
1926                    "std::function<void(::grpc::Status)> f) {\n");
1927     printer->Print(*vars,
1928                    "  ::grpc_impl::internal::CallbackUnaryCall"
1929                    "(stub_->channel_.get(), stub_->rpcmethod_$Method$_, "
1930                    "context, request, response, std::move(f));\n}\n\n");
1931 
1932     printer->Print(*vars,
1933                    "void $ns$$Service$::Stub::experimental_async::$Method$("
1934                    "::grpc::ClientContext* context, "
1935                    "const ::grpc::ByteBuffer* request, $Response$* response, "
1936                    "std::function<void(::grpc::Status)> f) {\n");
1937     printer->Print(*vars,
1938                    "  ::grpc_impl::internal::CallbackUnaryCall"
1939                    "(stub_->channel_.get(), stub_->rpcmethod_$Method$_, "
1940                    "context, request, response, std::move(f));\n}\n\n");
1941 
1942     printer->Print(*vars,
1943                    "void $ns$$Service$::Stub::experimental_async::$Method$("
1944                    "::grpc::ClientContext* context, "
1945                    "const $Request$* request, $Response$* response, "
1946                    "::grpc::experimental::ClientUnaryReactor* reactor) {\n");
1947     printer->Print(*vars,
1948                    "  ::grpc_impl::internal::ClientCallbackUnaryFactory::Create"
1949                    "(stub_->channel_.get(), stub_->rpcmethod_$Method$_, "
1950                    "context, request, response, reactor);\n}\n\n");
1951 
1952     printer->Print(*vars,
1953                    "void $ns$$Service$::Stub::experimental_async::$Method$("
1954                    "::grpc::ClientContext* context, "
1955                    "const ::grpc::ByteBuffer* request, $Response$* response, "
1956                    "::grpc::experimental::ClientUnaryReactor* reactor) {\n");
1957     printer->Print(*vars,
1958                    "  ::grpc_impl::internal::ClientCallbackUnaryFactory::Create"
1959                    "(stub_->channel_.get(), stub_->rpcmethod_$Method$_, "
1960                    "context, request, response, reactor);\n}\n\n");
1961 
1962     for (auto async_prefix : async_prefixes) {
1963       (*vars)["AsyncPrefix"] = async_prefix.prefix;
1964       (*vars)["AsyncStart"] = async_prefix.start;
1965       printer->Print(*vars,
1966                      "::grpc::ClientAsyncResponseReader< $Response$>* "
1967                      "$ns$$Service$::Stub::$AsyncPrefix$$Method$Raw(::grpc::"
1968                      "ClientContext* context, "
1969                      "const $Request$& request, "
1970                      "::grpc::CompletionQueue* cq) {\n");
1971       printer->Print(
1972           *vars,
1973           "  return "
1974           "::grpc_impl::internal::ClientAsyncResponseReaderFactory< $Response$>"
1975           "::Create(channel_.get(), cq, "
1976           "rpcmethod_$Method$_, "
1977           "context, request, $AsyncStart$);\n"
1978           "}\n\n");
1979     }
1980   } else if (ClientOnlyStreaming(method)) {
1981     printer->Print(*vars,
1982                    "::grpc::ClientWriter< $Request$>* "
1983                    "$ns$$Service$::Stub::$Method$Raw("
1984                    "::grpc::ClientContext* context, $Response$* response) {\n");
1985     printer->Print(*vars,
1986                    "  return ::grpc_impl::internal::ClientWriterFactory< "
1987                    "$Request$>::Create("
1988                    "channel_.get(), "
1989                    "rpcmethod_$Method$_, "
1990                    "context, response);\n"
1991                    "}\n\n");
1992 
1993     printer->Print(
1994         *vars,
1995         "void $ns$$Service$::"
1996         "Stub::experimental_async::$Method$(::grpc::ClientContext* context, "
1997         "$Response$* response, "
1998         "::grpc::experimental::ClientWriteReactor< $Request$>* reactor) {\n");
1999     printer->Print(*vars,
2000                    "  ::grpc_impl::internal::ClientCallbackWriterFactory< "
2001                    "$Request$>::Create("
2002                    "stub_->channel_.get(), "
2003                    "stub_->rpcmethod_$Method$_, "
2004                    "context, response, reactor);\n"
2005                    "}\n\n");
2006 
2007     for (auto async_prefix : async_prefixes) {
2008       (*vars)["AsyncPrefix"] = async_prefix.prefix;
2009       (*vars)["AsyncStart"] = async_prefix.start;
2010       (*vars)["AsyncMethodParams"] = async_prefix.method_params;
2011       (*vars)["AsyncCreateArgs"] = async_prefix.create_args;
2012       printer->Print(*vars,
2013                      "::grpc::ClientAsyncWriter< $Request$>* "
2014                      "$ns$$Service$::Stub::$AsyncPrefix$$Method$Raw("
2015                      "::grpc::ClientContext* context, $Response$* response, "
2016                      "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
2017       printer->Print(
2018           *vars,
2019           "  return ::grpc_impl::internal::ClientAsyncWriterFactory< $Request$>"
2020           "::Create(channel_.get(), cq, "
2021           "rpcmethod_$Method$_, "
2022           "context, response, $AsyncStart$$AsyncCreateArgs$);\n"
2023           "}\n\n");
2024     }
2025   } else if (ServerOnlyStreaming(method)) {
2026     printer->Print(
2027         *vars,
2028         "::grpc::ClientReader< $Response$>* "
2029         "$ns$$Service$::Stub::$Method$Raw("
2030         "::grpc::ClientContext* context, const $Request$& request) {\n");
2031     printer->Print(*vars,
2032                    "  return ::grpc_impl::internal::ClientReaderFactory< "
2033                    "$Response$>::Create("
2034                    "channel_.get(), "
2035                    "rpcmethod_$Method$_, "
2036                    "context, request);\n"
2037                    "}\n\n");
2038 
2039     printer->Print(
2040         *vars,
2041         "void $ns$$Service$::Stub::experimental_async::$Method$(::grpc::"
2042         "ClientContext* context, "
2043         "$Request$* request, "
2044         "::grpc::experimental::ClientReadReactor< $Response$>* reactor) {\n");
2045     printer->Print(*vars,
2046                    "  ::grpc_impl::internal::ClientCallbackReaderFactory< "
2047                    "$Response$>::Create("
2048                    "stub_->channel_.get(), "
2049                    "stub_->rpcmethod_$Method$_, "
2050                    "context, request, reactor);\n"
2051                    "}\n\n");
2052 
2053     for (auto async_prefix : async_prefixes) {
2054       (*vars)["AsyncPrefix"] = async_prefix.prefix;
2055       (*vars)["AsyncStart"] = async_prefix.start;
2056       (*vars)["AsyncMethodParams"] = async_prefix.method_params;
2057       (*vars)["AsyncCreateArgs"] = async_prefix.create_args;
2058       printer->Print(
2059           *vars,
2060           "::grpc::ClientAsyncReader< $Response$>* "
2061           "$ns$$Service$::Stub::$AsyncPrefix$$Method$Raw("
2062           "::grpc::ClientContext* context, const $Request$& request, "
2063           "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
2064       printer->Print(
2065           *vars,
2066           "  return ::grpc_impl::internal::ClientAsyncReaderFactory< "
2067           "$Response$>"
2068           "::Create(channel_.get(), cq, "
2069           "rpcmethod_$Method$_, "
2070           "context, request, $AsyncStart$$AsyncCreateArgs$);\n"
2071           "}\n\n");
2072     }
2073   } else if (method->BidiStreaming()) {
2074     printer->Print(
2075         *vars,
2076         "::grpc::ClientReaderWriter< $Request$, $Response$>* "
2077         "$ns$$Service$::Stub::$Method$Raw(::grpc::ClientContext* context) {\n");
2078     printer->Print(*vars,
2079                    "  return ::grpc_impl::internal::ClientReaderWriterFactory< "
2080                    "$Request$, $Response$>::Create("
2081                    "channel_.get(), "
2082                    "rpcmethod_$Method$_, "
2083                    "context);\n"
2084                    "}\n\n");
2085 
2086     printer->Print(
2087         *vars,
2088         "void $ns$$Service$::Stub::experimental_async::$Method$(::grpc::"
2089         "ClientContext* context, "
2090         "::grpc::experimental::ClientBidiReactor< $Request$,$Response$>* "
2091         "reactor) {\n");
2092     printer->Print(
2093         *vars,
2094         "  ::grpc_impl::internal::ClientCallbackReaderWriterFactory< "
2095         "$Request$,$Response$>::Create("
2096         "stub_->channel_.get(), "
2097         "stub_->rpcmethod_$Method$_, "
2098         "context, reactor);\n"
2099         "}\n\n");
2100 
2101     for (auto async_prefix : async_prefixes) {
2102       (*vars)["AsyncPrefix"] = async_prefix.prefix;
2103       (*vars)["AsyncStart"] = async_prefix.start;
2104       (*vars)["AsyncMethodParams"] = async_prefix.method_params;
2105       (*vars)["AsyncCreateArgs"] = async_prefix.create_args;
2106       printer->Print(*vars,
2107                      "::grpc::ClientAsyncReaderWriter< $Request$, $Response$>* "
2108                      "$ns$$Service$::Stub::$AsyncPrefix$$Method$Raw(::grpc::"
2109                      "ClientContext* context, "
2110                      "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
2111       printer->Print(*vars,
2112                      "  return "
2113                      "::grpc_impl::internal::ClientAsyncReaderWriterFactory< "
2114                      "$Request$, $Response$>::Create("
2115                      "channel_.get(), cq, "
2116                      "rpcmethod_$Method$_, "
2117                      "context, $AsyncStart$$AsyncCreateArgs$);\n"
2118                      "}\n\n");
2119     }
2120   }
2121 }
2122 
PrintSourceServerMethod(grpc_generator::Printer * printer,const grpc_generator::Method * method,std::map<std::string,std::string> * vars)2123 void PrintSourceServerMethod(grpc_generator::Printer* printer,
2124                              const grpc_generator::Method* method,
2125                              std::map<std::string, std::string>* vars) {
2126   (*vars)["Method"] = method->name();
2127   (*vars)["Request"] = method->input_type_name();
2128   (*vars)["Response"] = method->output_type_name();
2129   if (method->NoStreaming()) {
2130     printer->Print(*vars,
2131                    "::grpc::Status $ns$$Service$::Service::$Method$("
2132                    "::grpc::ServerContext* context, "
2133                    "const $Request$* request, $Response$* response) {\n");
2134     printer->Print("  (void) context;\n");
2135     printer->Print("  (void) request;\n");
2136     printer->Print("  (void) response;\n");
2137     printer->Print(
2138         "  return ::grpc::Status("
2139         "::grpc::StatusCode::UNIMPLEMENTED, \"\");\n");
2140     printer->Print("}\n\n");
2141   } else if (ClientOnlyStreaming(method)) {
2142     printer->Print(*vars,
2143                    "::grpc::Status $ns$$Service$::Service::$Method$("
2144                    "::grpc::ServerContext* context, "
2145                    "::grpc::ServerReader< $Request$>* reader, "
2146                    "$Response$* response) {\n");
2147     printer->Print("  (void) context;\n");
2148     printer->Print("  (void) reader;\n");
2149     printer->Print("  (void) response;\n");
2150     printer->Print(
2151         "  return ::grpc::Status("
2152         "::grpc::StatusCode::UNIMPLEMENTED, \"\");\n");
2153     printer->Print("}\n\n");
2154   } else if (ServerOnlyStreaming(method)) {
2155     printer->Print(*vars,
2156                    "::grpc::Status $ns$$Service$::Service::$Method$("
2157                    "::grpc::ServerContext* context, "
2158                    "const $Request$* request, "
2159                    "::grpc::ServerWriter< $Response$>* writer) {\n");
2160     printer->Print("  (void) context;\n");
2161     printer->Print("  (void) request;\n");
2162     printer->Print("  (void) writer;\n");
2163     printer->Print(
2164         "  return ::grpc::Status("
2165         "::grpc::StatusCode::UNIMPLEMENTED, \"\");\n");
2166     printer->Print("}\n\n");
2167   } else if (method->BidiStreaming()) {
2168     printer->Print(*vars,
2169                    "::grpc::Status $ns$$Service$::Service::$Method$("
2170                    "::grpc::ServerContext* context, "
2171                    "::grpc::ServerReaderWriter< $Response$, $Request$>* "
2172                    "stream) {\n");
2173     printer->Print("  (void) context;\n");
2174     printer->Print("  (void) stream;\n");
2175     printer->Print(
2176         "  return ::grpc::Status("
2177         "::grpc::StatusCode::UNIMPLEMENTED, \"\");\n");
2178     printer->Print("}\n\n");
2179   }
2180 }
2181 
PrintSourceService(grpc_generator::Printer * printer,const grpc_generator::Service * service,std::map<std::string,std::string> * vars)2182 void PrintSourceService(grpc_generator::Printer* printer,
2183                         const grpc_generator::Service* service,
2184                         std::map<std::string, std::string>* vars) {
2185   (*vars)["Service"] = service->name();
2186 
2187   if (service->method_count() > 0) {
2188     printer->Print(*vars,
2189                    "static const char* $prefix$$Service$_method_names[] = {\n");
2190     for (int i = 0; i < service->method_count(); ++i) {
2191       (*vars)["Method"] = service->method(i)->name();
2192       printer->Print(*vars, "  \"/$Package$$Service$/$Method$\",\n");
2193     }
2194     printer->Print(*vars, "};\n\n");
2195   }
2196 
2197   printer->Print(*vars,
2198                  "std::unique_ptr< $ns$$Service$::Stub> $ns$$Service$::NewStub("
2199                  "const std::shared_ptr< ::grpc::ChannelInterface>& channel, "
2200                  "const ::grpc::StubOptions& options) {\n"
2201                  "  (void)options;\n"
2202                  "  std::unique_ptr< $ns$$Service$::Stub> stub(new "
2203                  "$ns$$Service$::Stub(channel));\n"
2204                  "  return stub;\n"
2205                  "}\n\n");
2206   printer->Print(*vars,
2207                  "$ns$$Service$::Stub::Stub(const std::shared_ptr< "
2208                  "::grpc::ChannelInterface>& channel)\n");
2209   printer->Indent();
2210   printer->Print(": channel_(channel)");
2211   for (int i = 0; i < service->method_count(); ++i) {
2212     auto method = service->method(i);
2213     (*vars)["Method"] = method->name();
2214     (*vars)["Idx"] = as_string(i);
2215     if (method->NoStreaming()) {
2216       (*vars)["StreamingType"] = "NORMAL_RPC";
2217       // NOTE: There is no reason to consider streamed-unary as a separate
2218       // category here since this part is setting up the client-side stub
2219       // and this appears as a NORMAL_RPC from the client-side.
2220     } else if (ClientOnlyStreaming(method.get())) {
2221       (*vars)["StreamingType"] = "CLIENT_STREAMING";
2222     } else if (ServerOnlyStreaming(method.get())) {
2223       (*vars)["StreamingType"] = "SERVER_STREAMING";
2224     } else {
2225       (*vars)["StreamingType"] = "BIDI_STREAMING";
2226     }
2227     printer->Print(*vars,
2228                    ", rpcmethod_$Method$_("
2229                    "$prefix$$Service$_method_names[$Idx$], "
2230                    "::grpc::internal::RpcMethod::$StreamingType$, "
2231                    "channel"
2232                    ")\n");
2233   }
2234   printer->Print("{}\n\n");
2235   printer->Outdent();
2236 
2237   for (int i = 0; i < service->method_count(); ++i) {
2238     (*vars)["Idx"] = as_string(i);
2239     PrintSourceClientMethod(printer, service->method(i).get(), vars);
2240   }
2241 
2242   printer->Print(*vars, "$ns$$Service$::Service::Service() {\n");
2243   printer->Indent();
2244   for (int i = 0; i < service->method_count(); ++i) {
2245     auto method = service->method(i);
2246     (*vars)["Idx"] = as_string(i);
2247     (*vars)["Method"] = method->name();
2248     (*vars)["Request"] = method->input_type_name();
2249     (*vars)["Response"] = method->output_type_name();
2250     if (method->NoStreaming()) {
2251       printer->Print(
2252           *vars,
2253           "AddMethod(new ::grpc::internal::RpcServiceMethod(\n"
2254           "    $prefix$$Service$_method_names[$Idx$],\n"
2255           "    ::grpc::internal::RpcMethod::NORMAL_RPC,\n"
2256           "    new ::grpc::internal::RpcMethodHandler< $ns$$Service$::Service, "
2257           "$Request$, "
2258           "$Response$>(\n"
2259           "        []($ns$$Service$::Service* service,\n"
2260           "           ::grpc_impl::ServerContext* ctx,\n"
2261           "           const $Request$* req,\n"
2262           "           $Response$* resp) {\n"
2263           "             return service->$Method$(ctx, req, resp);\n"
2264           "           }, this)));\n");
2265     } else if (ClientOnlyStreaming(method.get())) {
2266       printer->Print(
2267           *vars,
2268           "AddMethod(new ::grpc::internal::RpcServiceMethod(\n"
2269           "    $prefix$$Service$_method_names[$Idx$],\n"
2270           "    ::grpc::internal::RpcMethod::CLIENT_STREAMING,\n"
2271           "    new ::grpc::internal::ClientStreamingHandler< "
2272           "$ns$$Service$::Service, $Request$, $Response$>(\n"
2273           "        []($ns$$Service$::Service* service,\n"
2274           "           ::grpc_impl::ServerContext* ctx,\n"
2275           "           ::grpc_impl::ServerReader<$Request$>* reader,\n"
2276           "           $Response$* resp) {\n"
2277           "             return service->$Method$(ctx, reader, resp);\n"
2278           "           }, this)));\n");
2279     } else if (ServerOnlyStreaming(method.get())) {
2280       printer->Print(
2281           *vars,
2282           "AddMethod(new ::grpc::internal::RpcServiceMethod(\n"
2283           "    $prefix$$Service$_method_names[$Idx$],\n"
2284           "    ::grpc::internal::RpcMethod::SERVER_STREAMING,\n"
2285           "    new ::grpc::internal::ServerStreamingHandler< "
2286           "$ns$$Service$::Service, $Request$, $Response$>(\n"
2287           "        []($ns$$Service$::Service* service,\n"
2288           "           ::grpc_impl::ServerContext* ctx,\n"
2289           "           const $Request$* req,\n"
2290           "           ::grpc_impl::ServerWriter<$Response$>* writer) {\n"
2291           "             return service->$Method$(ctx, req, writer);\n"
2292           "           }, this)));\n");
2293     } else if (method->BidiStreaming()) {
2294       printer->Print(*vars,
2295                      "AddMethod(new ::grpc::internal::RpcServiceMethod(\n"
2296                      "    $prefix$$Service$_method_names[$Idx$],\n"
2297                      "    ::grpc::internal::RpcMethod::BIDI_STREAMING,\n"
2298                      "    new ::grpc::internal::BidiStreamingHandler< "
2299                      "$ns$$Service$::Service, $Request$, $Response$>(\n"
2300                      "        []($ns$$Service$::Service* service,\n"
2301                      "           ::grpc_impl::ServerContext* ctx,\n"
2302                      "           ::grpc_impl::ServerReaderWriter<$Response$,\n"
2303                      "           $Request$>* stream) {\n"
2304                      "             return service->$Method$(ctx, stream);\n"
2305                      "           }, this)));\n");
2306     }
2307   }
2308   printer->Outdent();
2309   printer->Print(*vars, "}\n\n");
2310   printer->Print(*vars,
2311                  "$ns$$Service$::Service::~Service() {\n"
2312                  "}\n\n");
2313   for (int i = 0; i < service->method_count(); ++i) {
2314     (*vars)["Idx"] = as_string(i);
2315     PrintSourceServerMethod(printer, service->method(i).get(), vars);
2316   }
2317 }
2318 
GetSourceServices(grpc_generator::File * file,const Parameters & params)2319 std::string GetSourceServices(grpc_generator::File* file,
2320                               const Parameters& params) {
2321   std::string output;
2322   {
2323     // Scope the output stream so it closes and finalizes output to the string.
2324     auto printer = file->CreatePrinter(&output);
2325     std::map<std::string, std::string> vars;
2326     // Package string is empty or ends with a dot. It is used to fully qualify
2327     // method names.
2328     vars["Package"] = file->package();
2329     if (!file->package().empty()) {
2330       vars["Package"].append(".");
2331     }
2332     if (!params.services_namespace.empty()) {
2333       vars["ns"] = params.services_namespace + "::";
2334       vars["prefix"] = params.services_namespace;
2335     } else {
2336       vars["ns"] = "";
2337       vars["prefix"] = "";
2338     }
2339 
2340     for (int i = 0; i < file->service_count(); ++i) {
2341       PrintSourceService(printer.get(), file->service(i).get(), &vars);
2342       printer->Print("\n");
2343     }
2344   }
2345   return output;
2346 }
2347 
GetSourceEpilogue(grpc_generator::File * file,const Parameters &)2348 std::string GetSourceEpilogue(grpc_generator::File* file,
2349                               const Parameters& /*params*/) {
2350   std::string temp;
2351 
2352   if (!file->package().empty()) {
2353     std::vector<std::string> parts = file->package_parts();
2354 
2355     for (auto part = parts.begin(); part != parts.end(); part++) {
2356       temp.append("}  // namespace ");
2357       temp.append(*part);
2358       temp.append("\n");
2359     }
2360     temp.append("\n");
2361   }
2362 
2363   return temp;
2364 }
2365 
2366 // TODO(mmukhi): Make sure we need parameters or not.
GetMockPrologue(grpc_generator::File * file,const Parameters & params)2367 std::string GetMockPrologue(grpc_generator::File* file,
2368                             const Parameters& params) {
2369   std::string output;
2370   {
2371     // Scope the output stream so it closes and finalizes output to the string.
2372     auto printer = file->CreatePrinter(&output);
2373     std::map<std::string, std::string> vars;
2374 
2375     vars["filename"] = file->filename();
2376     vars["filename_base"] = file->filename_without_ext();
2377     vars["message_header_ext"] = params.message_header_extension.empty()
2378                                      ? kCppGeneratorMessageHeaderExt
2379                                      : params.message_header_extension;
2380     vars["service_header_ext"] = kCppGeneratorServiceHeaderExt;
2381 
2382     printer->Print(vars, "// Generated by the gRPC C++ plugin.\n");
2383     printer->Print(vars,
2384                    "// If you make any local change, they will be lost.\n");
2385     printer->Print(vars, "// source: $filename$\n\n");
2386 
2387     printer->Print(vars, "#include \"$filename_base$$message_header_ext$\"\n");
2388     printer->Print(vars, "#include \"$filename_base$$service_header_ext$\"\n");
2389     if (params.include_import_headers) {
2390       const std::vector<std::string> import_names = file->GetImportNames();
2391       for (const auto& import_name : import_names) {
2392         const std::string include_name = ImportInludeFromProtoName(import_name);
2393         printer->Print(vars, include_name.c_str());
2394       }
2395       printer->PrintRaw("\n");
2396     }
2397     printer->Print(vars, file->additional_headers().c_str());
2398     printer->Print(vars, "\n");
2399   }
2400   return output;
2401 }
2402 
2403 // TODO(mmukhi): Add client-stream and completion-queue headers.
GetMockIncludes(grpc_generator::File * file,const Parameters & params)2404 std::string GetMockIncludes(grpc_generator::File* file,
2405                             const Parameters& params) {
2406   std::string output;
2407   {
2408     // Scope the output stream so it closes and finalizes output to the string.
2409     auto printer = file->CreatePrinter(&output);
2410     std::map<std::string, std::string> vars;
2411 
2412     static const char* headers_strs[] = {
2413         "grpcpp/impl/codegen/async_stream.h",
2414         "grpcpp/impl/codegen/sync_stream.h",
2415     };
2416     std::vector<std::string> headers(headers_strs, array_end(headers_strs));
2417     PrintIncludes(printer.get(), headers, params.use_system_headers,
2418                   params.grpc_search_path);
2419 
2420     std::vector<std::string> gmock_header;
2421     if (params.gmock_search_path.empty()) {
2422       gmock_header.push_back("gmock/gmock.h");
2423       PrintIncludes(printer.get(), gmock_header, params.use_system_headers,
2424                     params.grpc_search_path);
2425     } else {
2426       gmock_header.push_back("gmock.h");
2427       // We use local includes when a gmock_search_path is given
2428       PrintIncludes(printer.get(), gmock_header, false,
2429                     params.gmock_search_path);
2430     }
2431 
2432     if (!file->package().empty()) {
2433       std::vector<std::string> parts = file->package_parts();
2434 
2435       for (auto part = parts.begin(); part != parts.end(); part++) {
2436         vars["part"] = *part;
2437         printer->Print(vars, "namespace $part$ {\n");
2438       }
2439     }
2440 
2441     printer->Print(vars, "\n");
2442   }
2443   return output;
2444 }
2445 
PrintMockClientMethods(grpc_generator::Printer * printer,const grpc_generator::Method * method,std::map<std::string,std::string> * vars)2446 void PrintMockClientMethods(grpc_generator::Printer* printer,
2447                             const grpc_generator::Method* method,
2448                             std::map<std::string, std::string>* vars) {
2449   (*vars)["Method"] = method->name();
2450   (*vars)["Request"] = method->input_type_name();
2451   (*vars)["Response"] = method->output_type_name();
2452 
2453   struct {
2454     std::string prefix;
2455     std::string method_params;  // extra arguments to method
2456     int extra_method_param_count;
2457   } async_prefixes[] = {{"Async", ", void* tag", 1}, {"PrepareAsync", "", 0}};
2458 
2459   if (method->NoStreaming()) {
2460     printer->Print(
2461         *vars,
2462         "MOCK_METHOD3($Method$, ::grpc::Status(::grpc::ClientContext* context, "
2463         "const $Request$& request, $Response$* response));\n");
2464     for (auto async_prefix : async_prefixes) {
2465       (*vars)["AsyncPrefix"] = async_prefix.prefix;
2466       printer->Print(
2467           *vars,
2468           "MOCK_METHOD3($AsyncPrefix$$Method$Raw, "
2469           "::grpc::ClientAsyncResponseReaderInterface< $Response$>*"
2470           "(::grpc::ClientContext* context, const $Request$& request, "
2471           "::grpc::CompletionQueue* cq));\n");
2472     }
2473   } else if (ClientOnlyStreaming(method)) {
2474     printer->Print(
2475         *vars,
2476         "MOCK_METHOD2($Method$Raw, "
2477         "::grpc::ClientWriterInterface< $Request$>*"
2478         "(::grpc::ClientContext* context, $Response$* response));\n");
2479     for (auto async_prefix : async_prefixes) {
2480       (*vars)["AsyncPrefix"] = async_prefix.prefix;
2481       (*vars)["AsyncMethodParams"] = async_prefix.method_params;
2482       (*vars)["MockArgs"] =
2483           std::to_string(3 + async_prefix.extra_method_param_count);
2484       printer->Print(*vars,
2485                      "MOCK_METHOD$MockArgs$($AsyncPrefix$$Method$Raw, "
2486                      "::grpc::ClientAsyncWriterInterface< $Request$>*"
2487                      "(::grpc::ClientContext* context, $Response$* response, "
2488                      "::grpc::CompletionQueue* cq$AsyncMethodParams$));\n");
2489     }
2490   } else if (ServerOnlyStreaming(method)) {
2491     printer->Print(
2492         *vars,
2493         "MOCK_METHOD2($Method$Raw, "
2494         "::grpc::ClientReaderInterface< $Response$>*"
2495         "(::grpc::ClientContext* context, const $Request$& request));\n");
2496     for (auto async_prefix : async_prefixes) {
2497       (*vars)["AsyncPrefix"] = async_prefix.prefix;
2498       (*vars)["AsyncMethodParams"] = async_prefix.method_params;
2499       (*vars)["MockArgs"] =
2500           std::to_string(3 + async_prefix.extra_method_param_count);
2501       printer->Print(
2502           *vars,
2503           "MOCK_METHOD$MockArgs$($AsyncPrefix$$Method$Raw, "
2504           "::grpc::ClientAsyncReaderInterface< $Response$>*"
2505           "(::grpc::ClientContext* context, const $Request$& request, "
2506           "::grpc::CompletionQueue* cq$AsyncMethodParams$));\n");
2507     }
2508   } else if (method->BidiStreaming()) {
2509     printer->Print(
2510         *vars,
2511         "MOCK_METHOD1($Method$Raw, "
2512         "::grpc::ClientReaderWriterInterface< $Request$, $Response$>*"
2513         "(::grpc::ClientContext* context));\n");
2514     for (auto async_prefix : async_prefixes) {
2515       (*vars)["AsyncPrefix"] = async_prefix.prefix;
2516       (*vars)["AsyncMethodParams"] = async_prefix.method_params;
2517       (*vars)["MockArgs"] =
2518           std::to_string(2 + async_prefix.extra_method_param_count);
2519       printer->Print(
2520           *vars,
2521           "MOCK_METHOD$MockArgs$($AsyncPrefix$$Method$Raw, "
2522           "::grpc::ClientAsyncReaderWriterInterface<$Request$, "
2523           "$Response$>*"
2524           "(::grpc::ClientContext* context, ::grpc::CompletionQueue* cq"
2525           "$AsyncMethodParams$));\n");
2526     }
2527   }
2528 }
2529 
PrintMockService(grpc_generator::Printer * printer,const grpc_generator::Service * service,std::map<std::string,std::string> * vars)2530 void PrintMockService(grpc_generator::Printer* printer,
2531                       const grpc_generator::Service* service,
2532                       std::map<std::string, std::string>* vars) {
2533   (*vars)["Service"] = service->name();
2534 
2535   printer->Print(*vars,
2536                  "class Mock$Service$Stub : public $Service$::StubInterface {\n"
2537                  " public:\n");
2538   printer->Indent();
2539   for (int i = 0; i < service->method_count(); ++i) {
2540     PrintMockClientMethods(printer, service->method(i).get(), vars);
2541   }
2542   printer->Outdent();
2543   printer->Print("};\n");
2544 }
2545 
GetMockServices(grpc_generator::File * file,const Parameters & params)2546 std::string GetMockServices(grpc_generator::File* file,
2547                             const Parameters& params) {
2548   std::string output;
2549   {
2550     // Scope the output stream so it closes and finalizes output to the string.
2551     auto printer = file->CreatePrinter(&output);
2552     std::map<std::string, std::string> vars;
2553     // Package string is empty or ends with a dot. It is used to fully qualify
2554     // method names.
2555     vars["Package"] = file->package();
2556     if (!file->package().empty()) {
2557       vars["Package"].append(".");
2558     }
2559 
2560     if (!params.services_namespace.empty()) {
2561       vars["services_namespace"] = params.services_namespace;
2562       printer->Print(vars, "\nnamespace $services_namespace$ {\n\n");
2563     }
2564 
2565     for (int i = 0; i < file->service_count(); i++) {
2566       PrintMockService(printer.get(), file->service(i).get(), &vars);
2567       printer->Print("\n");
2568     }
2569 
2570     if (!params.services_namespace.empty()) {
2571       printer->Print(vars, "} // namespace $services_namespace$\n\n");
2572     }
2573   }
2574   return output;
2575 }
2576 
GetMockEpilogue(grpc_generator::File * file,const Parameters &)2577 std::string GetMockEpilogue(grpc_generator::File* file,
2578                             const Parameters& /*params*/) {
2579   std::string temp;
2580 
2581   if (!file->package().empty()) {
2582     std::vector<std::string> parts = file->package_parts();
2583 
2584     for (auto part = parts.begin(); part != parts.end(); part++) {
2585       temp.append("} // namespace ");
2586       temp.append(*part);
2587       temp.append("\n");
2588     }
2589     temp.append("\n");
2590   }
2591 
2592   return temp;
2593 }
2594 
2595 }  // namespace grpc_cpp_generator
2596