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