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