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