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