blob: 69dcf59d9128898081862c74b32a721646a5376e [file] [log] [blame]
James Kuszmaul8e62b022022-03-22 09:33:25 -07001#include "src/compiler/cpp_generator.h"
Austin Schuhe89fa2d2019-08-14 20:24:23 -07002
3#include <map>
Austin Schuhe89fa2d2019-08-14 20:24:23 -07004#include <sstream>
5
James Kuszmaul8e62b022022-03-22 09:33:25 -07006#include "flatbuffers/util.h"
7
Austin Schuhe89fa2d2019-08-14 20:24:23 -07008namespace grpc_cpp_generator {
9namespace {
10
11grpc::string message_header_ext() { return "_generated.h"; }
12grpc::string service_header_ext() { return ".grpc.fb.h"; }
13
James Kuszmaul8e62b022022-03-22 09:33:25 -070014template<class T> grpc::string as_string(T x) {
Austin Schuhe89fa2d2019-08-14 20:24:23 -070015 std::ostringstream out;
16 out << x;
17 return out.str();
18}
19
20inline bool ClientOnlyStreaming(const grpc_generator::Method *method) {
21 return method->ClientStreaming() && !method->ServerStreaming();
22}
23
24inline bool ServerOnlyStreaming(const grpc_generator::Method *method) {
25 return !method->ClientStreaming() && method->ServerStreaming();
26}
27
28grpc::string FilenameIdentifier(const grpc::string &filename) {
29 grpc::string result;
30 for (unsigned i = 0; i < filename.size(); i++) {
31 char c = filename[i];
32 if (isalnum(c)) {
33 result.push_back(c);
34 } else {
35 static char hex[] = "0123456789abcdef";
36 result.push_back('_');
37 result.push_back(hex[(c >> 4) & 0xf]);
38 result.push_back(hex[c & 0xf]);
39 }
40 }
41 return result;
42}
43} // namespace
44
James Kuszmaul8e62b022022-03-22 09:33:25 -070045template<class T, size_t N> T *array_end(T (&array)[N]) { return array + N; }
Austin Schuhe89fa2d2019-08-14 20:24:23 -070046
47void PrintIncludes(grpc_generator::Printer *printer,
48 const std::vector<grpc::string> &headers,
49 const Parameters &params) {
50 std::map<grpc::string, grpc::string> vars;
51
52 vars["l"] = params.use_system_headers ? '<' : '"';
53 vars["r"] = params.use_system_headers ? '>' : '"';
54
55 auto &s = params.grpc_search_path;
56 if (!s.empty()) {
57 vars["l"] += s;
James Kuszmaul8e62b022022-03-22 09:33:25 -070058 if (s[s.size() - 1] != '/') { vars["l"] += '/'; }
Austin Schuhe89fa2d2019-08-14 20:24:23 -070059 }
60
61 for (auto i = headers.begin(); i != headers.end(); i++) {
62 vars["h"] = *i;
63 printer->Print(vars, "#include $l$$h$$r$\n");
64 }
65}
66
67grpc::string GetHeaderPrologue(grpc_generator::File *file,
68 const Parameters & /*params*/) {
69 grpc::string output;
70 {
71 // Scope the output stream so it closes and finalizes output to the string.
72 auto printer = file->CreatePrinter(&output);
73 std::map<grpc::string, grpc::string> vars;
74
75 vars["filename"] = file->filename();
76 vars["filename_identifier"] = FilenameIdentifier(file->filename());
77 vars["filename_base"] = file->filename_without_ext();
James Kuszmaul8e62b022022-03-22 09:33:25 -070078 vars["message_header_ext"] = file->message_header_ext();
Austin Schuhe89fa2d2019-08-14 20:24:23 -070079
80 printer->Print(vars, "// Generated by the gRPC C++ plugin.\n");
81 printer->Print(vars,
82 "// If you make any local change, they will be lost.\n");
83 printer->Print(vars, "// source: $filename$\n");
84 grpc::string leading_comments = file->GetLeadingComments("//");
85 if (!leading_comments.empty()) {
86 printer->Print(vars, "// Original file comments:\n");
87 printer->Print(leading_comments.c_str());
88 }
89 printer->Print(vars, "#ifndef GRPC_$filename_identifier$__INCLUDED\n");
90 printer->Print(vars, "#define GRPC_$filename_identifier$__INCLUDED\n");
91 printer->Print(vars, "\n");
92 printer->Print(vars, "#include \"$filename_base$$message_header_ext$\"\n");
93 printer->Print(vars, file->additional_headers().c_str());
94 printer->Print(vars, "\n");
95 }
96 return output;
97}
98
99grpc::string GetHeaderIncludes(grpc_generator::File *file,
100 const Parameters &params) {
101 grpc::string output;
102 {
103 // Scope the output stream so it closes and finalizes output to the string.
104 auto printer = file->CreatePrinter(&output);
105 std::map<grpc::string, grpc::string> vars;
106
107 static const char *headers_strs[] = {
James Kuszmaul8e62b022022-03-22 09:33:25 -0700108 "grpcpp/impl/codegen/async_stream.h",
109 "grpcpp/impl/codegen/async_unary_call.h",
110 "grpcpp/impl/codegen/method_handler.h",
111 "grpcpp/impl/codegen/proto_utils.h",
112 "grpcpp/impl/codegen/rpc_method.h",
113 "grpcpp/impl/codegen/service_type.h",
114 "grpcpp/impl/codegen/status.h",
115 "grpcpp/impl/codegen/stub_options.h",
116 "grpcpp/impl/codegen/sync_stream.h"
117 };
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700118 std::vector<grpc::string> headers(headers_strs, array_end(headers_strs));
119 PrintIncludes(printer.get(), headers, params);
120 printer->Print(vars, "\n");
121 printer->Print(vars, "namespace grpc {\n");
122 printer->Print(vars, "class CompletionQueue;\n");
123 printer->Print(vars, "class Channel;\n");
124 printer->Print(vars, "class ServerCompletionQueue;\n");
125 printer->Print(vars, "class ServerContext;\n");
126 printer->Print(vars, "} // namespace grpc\n\n");
127
128 if (!file->package().empty()) {
129 std::vector<grpc::string> parts = file->package_parts();
130
131 for (auto part = parts.begin(); part != parts.end(); part++) {
132 vars["part"] = *part;
133 printer->Print(vars, "namespace $part$ {\n");
134 }
135 printer->Print(vars, "\n");
136 }
137 }
138 return output;
139}
140
141void PrintHeaderClientMethodInterfaces(
142 grpc_generator::Printer *printer, const grpc_generator::Method *method,
143 std::map<grpc::string, grpc::string> *vars, bool is_public) {
144 (*vars)["Method"] = method->name();
145 (*vars)["Request"] = method->input_type_name();
146 (*vars)["Response"] = method->output_type_name();
147
148 struct {
149 grpc::string prefix;
150 grpc::string method_params; // extra arguments to method
151 grpc::string raw_args; // extra arguments to raw version of method
James Kuszmaul8e62b022022-03-22 09:33:25 -0700152 } async_prefixes[] = { { "Async", ", void* tag", ", tag" },
153 { "PrepareAsync", "", "" } };
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700154
155 if (is_public) {
156 if (method->NoStreaming()) {
157 printer->Print(
158 *vars,
159 "virtual ::grpc::Status $Method$(::grpc::ClientContext* context, "
160 "const $Request$& request, $Response$* response) = 0;\n");
James Kuszmaul8e62b022022-03-22 09:33:25 -0700161 for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
162 i++) {
163 auto &async_prefix = async_prefixes[i];
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700164 (*vars)["AsyncPrefix"] = async_prefix.prefix;
165 printer->Print(
166 *vars,
167 "std::unique_ptr< "
168 "::grpc::ClientAsyncResponseReaderInterface< $Response$>> "
169 "$AsyncPrefix$$Method$(::grpc::ClientContext* context, "
170 "const $Request$& request, "
171 "::grpc::CompletionQueue* cq) {\n");
172 printer->Indent();
173 printer->Print(
174 *vars,
175 "return std::unique_ptr< "
176 "::grpc::ClientAsyncResponseReaderInterface< $Response$>>("
177 "$AsyncPrefix$$Method$Raw(context, request, cq));\n");
178 printer->Outdent();
179 printer->Print("}\n");
180 }
181 } else if (ClientOnlyStreaming(method)) {
182 printer->Print(
183 *vars,
184 "std::unique_ptr< ::grpc::ClientWriterInterface< $Request$>>"
185 " $Method$("
186 "::grpc::ClientContext* context, $Response$* response) {\n");
187 printer->Indent();
188 printer->Print(
189 *vars,
190 "return std::unique_ptr< ::grpc::ClientWriterInterface< $Request$>>"
191 "($Method$Raw(context, response));\n");
192 printer->Outdent();
193 printer->Print("}\n");
James Kuszmaul8e62b022022-03-22 09:33:25 -0700194 for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
195 i++) {
196 auto &async_prefix = async_prefixes[i];
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700197 (*vars)["AsyncPrefix"] = async_prefix.prefix;
198 (*vars)["AsyncMethodParams"] = async_prefix.method_params;
199 (*vars)["AsyncRawArgs"] = async_prefix.raw_args;
200 printer->Print(
201 *vars,
202 "std::unique_ptr< ::grpc::ClientAsyncWriterInterface< $Request$>>"
203 " $AsyncPrefix$$Method$(::grpc::ClientContext* context, "
204 "$Response$* "
205 "response, "
206 "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
207 printer->Indent();
208 printer->Print(*vars,
209 "return std::unique_ptr< "
210 "::grpc::ClientAsyncWriterInterface< $Request$>>("
211 "$AsyncPrefix$$Method$Raw(context, response, "
212 "cq$AsyncRawArgs$));\n");
213 printer->Outdent();
214 printer->Print("}\n");
215 }
216 } else if (ServerOnlyStreaming(method)) {
217 printer->Print(
218 *vars,
219 "std::unique_ptr< ::grpc::ClientReaderInterface< $Response$>>"
220 " $Method$(::grpc::ClientContext* context, const $Request$& request)"
221 " {\n");
222 printer->Indent();
223 printer->Print(
224 *vars,
225 "return std::unique_ptr< ::grpc::ClientReaderInterface< $Response$>>"
226 "($Method$Raw(context, request));\n");
227 printer->Outdent();
228 printer->Print("}\n");
James Kuszmaul8e62b022022-03-22 09:33:25 -0700229 for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
230 i++) {
231 auto &async_prefix = async_prefixes[i];
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700232 (*vars)["AsyncPrefix"] = async_prefix.prefix;
233 (*vars)["AsyncMethodParams"] = async_prefix.method_params;
234 (*vars)["AsyncRawArgs"] = async_prefix.raw_args;
235 printer->Print(
236 *vars,
237 "std::unique_ptr< ::grpc::ClientAsyncReaderInterface< $Response$>> "
238 "$AsyncPrefix$$Method$("
239 "::grpc::ClientContext* context, const $Request$& request, "
240 "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
241 printer->Indent();
242 printer->Print(
243 *vars,
244 "return std::unique_ptr< "
245 "::grpc::ClientAsyncReaderInterface< $Response$>>("
246 "$AsyncPrefix$$Method$Raw(context, request, cq$AsyncRawArgs$));\n");
247 printer->Outdent();
248 printer->Print("}\n");
249 }
250 } else if (method->BidiStreaming()) {
251 printer->Print(*vars,
252 "std::unique_ptr< ::grpc::ClientReaderWriterInterface< "
253 "$Request$, $Response$>> "
254 "$Method$(::grpc::ClientContext* context) {\n");
255 printer->Indent();
256 printer->Print(
257 *vars,
258 "return std::unique_ptr< "
259 "::grpc::ClientReaderWriterInterface< $Request$, $Response$>>("
260 "$Method$Raw(context));\n");
261 printer->Outdent();
262 printer->Print("}\n");
James Kuszmaul8e62b022022-03-22 09:33:25 -0700263 for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
264 i++) {
265 auto &async_prefix = async_prefixes[i];
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700266 (*vars)["AsyncPrefix"] = async_prefix.prefix;
267 (*vars)["AsyncMethodParams"] = async_prefix.method_params;
268 (*vars)["AsyncRawArgs"] = async_prefix.raw_args;
269 printer->Print(
270 *vars,
271 "std::unique_ptr< "
272 "::grpc::ClientAsyncReaderWriterInterface< $Request$, $Response$>> "
273 "$AsyncPrefix$$Method$(::grpc::ClientContext* context, "
274 "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
275 printer->Indent();
276 printer->Print(
277 *vars,
278 "return std::unique_ptr< "
279 "::grpc::ClientAsyncReaderWriterInterface< $Request$, $Response$>>("
280 "$AsyncPrefix$$Method$Raw(context, cq$AsyncRawArgs$));\n");
281 printer->Outdent();
282 printer->Print("}\n");
283 }
284 }
285 } else {
286 if (method->NoStreaming()) {
James Kuszmaul8e62b022022-03-22 09:33:25 -0700287 for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
288 i++) {
289 auto &async_prefix = async_prefixes[i];
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700290 (*vars)["AsyncPrefix"] = async_prefix.prefix;
291 printer->Print(
292 *vars,
293 "virtual ::grpc::ClientAsyncResponseReaderInterface< $Response$>* "
294 "$AsyncPrefix$$Method$Raw(::grpc::ClientContext* context, "
295 "const $Request$& request, "
296 "::grpc::CompletionQueue* cq) = 0;\n");
297 }
298 } else if (ClientOnlyStreaming(method)) {
299 printer->Print(
300 *vars,
301 "virtual ::grpc::ClientWriterInterface< $Request$>*"
302 " $Method$Raw("
303 "::grpc::ClientContext* context, $Response$* response) = 0;\n");
James Kuszmaul8e62b022022-03-22 09:33:25 -0700304 for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
305 i++) {
306 auto &async_prefix = async_prefixes[i];
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700307 (*vars)["AsyncPrefix"] = async_prefix.prefix;
308 (*vars)["AsyncMethodParams"] = async_prefix.method_params;
309 printer->Print(
310 *vars,
311 "virtual ::grpc::ClientAsyncWriterInterface< $Request$>*"
312 " $AsyncPrefix$$Method$Raw(::grpc::ClientContext* context, "
313 "$Response$* response, "
314 "::grpc::CompletionQueue* cq$AsyncMethodParams$) = 0;\n");
315 }
316 } else if (ServerOnlyStreaming(method)) {
317 printer->Print(
318 *vars,
319 "virtual ::grpc::ClientReaderInterface< $Response$>* "
320 "$Method$Raw("
321 "::grpc::ClientContext* context, const $Request$& request) = 0;\n");
James Kuszmaul8e62b022022-03-22 09:33:25 -0700322 for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
323 i++) {
324 auto &async_prefix = async_prefixes[i];
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700325 (*vars)["AsyncPrefix"] = async_prefix.prefix;
326 (*vars)["AsyncMethodParams"] = async_prefix.method_params;
327 printer->Print(
328 *vars,
329 "virtual ::grpc::ClientAsyncReaderInterface< $Response$>* "
330 "$AsyncPrefix$$Method$Raw("
331 "::grpc::ClientContext* context, const $Request$& request, "
332 "::grpc::CompletionQueue* cq$AsyncMethodParams$) = 0;\n");
333 }
334 } else if (method->BidiStreaming()) {
335 printer->Print(*vars,
336 "virtual ::grpc::ClientReaderWriterInterface< $Request$, "
337 "$Response$>* "
338 "$Method$Raw(::grpc::ClientContext* context) = 0;\n");
James Kuszmaul8e62b022022-03-22 09:33:25 -0700339 for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
340 i++) {
341 auto &async_prefix = async_prefixes[i];
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700342 (*vars)["AsyncPrefix"] = async_prefix.prefix;
343 (*vars)["AsyncMethodParams"] = async_prefix.method_params;
344 printer->Print(
345 *vars,
346 "virtual ::grpc::ClientAsyncReaderWriterInterface< "
347 "$Request$, $Response$>* "
348 "$AsyncPrefix$$Method$Raw(::grpc::ClientContext* context, "
349 "::grpc::CompletionQueue* cq$AsyncMethodParams$) = 0;\n");
350 }
351 }
352 }
353}
354
355void PrintHeaderClientMethod(grpc_generator::Printer *printer,
356 const grpc_generator::Method *method,
357 std::map<grpc::string, grpc::string> *vars,
358 bool is_public) {
359 (*vars)["Method"] = method->name();
360 (*vars)["Request"] = method->input_type_name();
361 (*vars)["Response"] = method->output_type_name();
362 struct {
363 grpc::string prefix;
364 grpc::string method_params; // extra arguments to method
365 grpc::string raw_args; // extra arguments to raw version of method
James Kuszmaul8e62b022022-03-22 09:33:25 -0700366 } async_prefixes[] = { { "Async", ", void* tag", ", tag" },
367 { "PrepareAsync", "", "" } };
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700368
369 if (is_public) {
370 if (method->NoStreaming()) {
371 printer->Print(
372 *vars,
373 "::grpc::Status $Method$(::grpc::ClientContext* context, "
374 "const $Request$& request, $Response$* response) override;\n");
James Kuszmaul8e62b022022-03-22 09:33:25 -0700375 for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
376 i++) {
377 auto &async_prefix = async_prefixes[i];
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700378 (*vars)["AsyncPrefix"] = async_prefix.prefix;
379 printer->Print(
380 *vars,
381 "std::unique_ptr< ::grpc::ClientAsyncResponseReader< $Response$>> "
382 "$AsyncPrefix$$Method$(::grpc::ClientContext* context, "
383 "const $Request$& request, "
384 "::grpc::CompletionQueue* cq) {\n");
385 printer->Indent();
386 printer->Print(*vars,
387 "return std::unique_ptr< "
388 "::grpc::ClientAsyncResponseReader< $Response$>>("
389 "$AsyncPrefix$$Method$Raw(context, request, cq));\n");
390 printer->Outdent();
391 printer->Print("}\n");
392 }
393 } else if (ClientOnlyStreaming(method)) {
394 printer->Print(
395 *vars,
396 "std::unique_ptr< ::grpc::ClientWriter< $Request$>>"
397 " $Method$("
398 "::grpc::ClientContext* context, $Response$* response) {\n");
399 printer->Indent();
400 printer->Print(*vars,
401 "return std::unique_ptr< ::grpc::ClientWriter< $Request$>>"
402 "($Method$Raw(context, response));\n");
403 printer->Outdent();
404 printer->Print("}\n");
James Kuszmaul8e62b022022-03-22 09:33:25 -0700405 for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
406 i++) {
407 auto &async_prefix = async_prefixes[i];
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700408 (*vars)["AsyncPrefix"] = async_prefix.prefix;
409 (*vars)["AsyncMethodParams"] = async_prefix.method_params;
410 (*vars)["AsyncRawArgs"] = async_prefix.raw_args;
411 printer->Print(*vars,
412 "std::unique_ptr< ::grpc::ClientAsyncWriter< $Request$>>"
413 " $AsyncPrefix$$Method$(::grpc::ClientContext* context, "
414 "$Response$* response, "
415 "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
416 printer->Indent();
417 printer->Print(
418 *vars,
419 "return std::unique_ptr< ::grpc::ClientAsyncWriter< $Request$>>("
420 "$AsyncPrefix$$Method$Raw(context, response, "
421 "cq$AsyncRawArgs$));\n");
422 printer->Outdent();
423 printer->Print("}\n");
424 }
425 } else if (ServerOnlyStreaming(method)) {
426 printer->Print(
427 *vars,
428 "std::unique_ptr< ::grpc::ClientReader< $Response$>>"
429 " $Method$(::grpc::ClientContext* context, const $Request$& request)"
430 " {\n");
431 printer->Indent();
432 printer->Print(
433 *vars,
434 "return std::unique_ptr< ::grpc::ClientReader< $Response$>>"
435 "($Method$Raw(context, request));\n");
436 printer->Outdent();
437 printer->Print("}\n");
James Kuszmaul8e62b022022-03-22 09:33:25 -0700438 for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
439 i++) {
440 auto &async_prefix = async_prefixes[i];
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700441 (*vars)["AsyncPrefix"] = async_prefix.prefix;
442 (*vars)["AsyncMethodParams"] = async_prefix.method_params;
443 (*vars)["AsyncRawArgs"] = async_prefix.raw_args;
444 printer->Print(
445 *vars,
446 "std::unique_ptr< ::grpc::ClientAsyncReader< $Response$>> "
447 "$AsyncPrefix$$Method$("
448 "::grpc::ClientContext* context, const $Request$& request, "
449 "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
450 printer->Indent();
451 printer->Print(
452 *vars,
453 "return std::unique_ptr< ::grpc::ClientAsyncReader< $Response$>>("
454 "$AsyncPrefix$$Method$Raw(context, request, cq$AsyncRawArgs$));\n");
455 printer->Outdent();
456 printer->Print("}\n");
457 }
458 } else if (method->BidiStreaming()) {
459 printer->Print(
460 *vars,
461 "std::unique_ptr< ::grpc::ClientReaderWriter< $Request$, $Response$>>"
462 " $Method$(::grpc::ClientContext* context) {\n");
463 printer->Indent();
464 printer->Print(*vars,
465 "return std::unique_ptr< "
466 "::grpc::ClientReaderWriter< $Request$, $Response$>>("
467 "$Method$Raw(context));\n");
468 printer->Outdent();
469 printer->Print("}\n");
James Kuszmaul8e62b022022-03-22 09:33:25 -0700470 for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
471 i++) {
472 auto &async_prefix = async_prefixes[i];
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700473 (*vars)["AsyncPrefix"] = async_prefix.prefix;
474 (*vars)["AsyncMethodParams"] = async_prefix.method_params;
475 (*vars)["AsyncRawArgs"] = async_prefix.raw_args;
476 printer->Print(*vars,
477 "std::unique_ptr< ::grpc::ClientAsyncReaderWriter< "
478 "$Request$, $Response$>> "
479 "$AsyncPrefix$$Method$(::grpc::ClientContext* context, "
480 "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
481 printer->Indent();
482 printer->Print(
483 *vars,
484 "return std::unique_ptr< "
485 "::grpc::ClientAsyncReaderWriter< $Request$, $Response$>>("
486 "$AsyncPrefix$$Method$Raw(context, cq$AsyncRawArgs$));\n");
487 printer->Outdent();
488 printer->Print("}\n");
489 }
490 }
491 } else {
492 if (method->NoStreaming()) {
James Kuszmaul8e62b022022-03-22 09:33:25 -0700493 for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
494 i++) {
495 auto &async_prefix = async_prefixes[i];
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700496 (*vars)["AsyncPrefix"] = async_prefix.prefix;
497 printer->Print(
498 *vars,
499 "::grpc::ClientAsyncResponseReader< $Response$>* "
500 "$AsyncPrefix$$Method$Raw(::grpc::ClientContext* context, "
501 "const $Request$& request, "
502 "::grpc::CompletionQueue* cq) override;\n");
503 }
504 } else if (ClientOnlyStreaming(method)) {
505 printer->Print(*vars,
506 "::grpc::ClientWriter< $Request$>* $Method$Raw("
507 "::grpc::ClientContext* context, $Response$* response) "
508 "override;\n");
James Kuszmaul8e62b022022-03-22 09:33:25 -0700509 for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
510 i++) {
511 auto &async_prefix = async_prefixes[i];
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700512 (*vars)["AsyncPrefix"] = async_prefix.prefix;
513 (*vars)["AsyncMethodParams"] = async_prefix.method_params;
514 (*vars)["AsyncRawArgs"] = async_prefix.raw_args;
515 printer->Print(
516 *vars,
517 "::grpc::ClientAsyncWriter< $Request$>* $AsyncPrefix$$Method$Raw("
518 "::grpc::ClientContext* context, $Response$* response, "
519 "::grpc::CompletionQueue* cq$AsyncMethodParams$) override;\n");
520 }
521 } else if (ServerOnlyStreaming(method)) {
522 printer->Print(*vars,
523 "::grpc::ClientReader< $Response$>* $Method$Raw("
524 "::grpc::ClientContext* context, const $Request$& request)"
525 " override;\n");
James Kuszmaul8e62b022022-03-22 09:33:25 -0700526 for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
527 i++) {
528 auto &async_prefix = async_prefixes[i];
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700529 (*vars)["AsyncPrefix"] = async_prefix.prefix;
530 (*vars)["AsyncMethodParams"] = async_prefix.method_params;
531 (*vars)["AsyncRawArgs"] = async_prefix.raw_args;
532 printer->Print(
533 *vars,
534 "::grpc::ClientAsyncReader< $Response$>* $AsyncPrefix$$Method$Raw("
535 "::grpc::ClientContext* context, const $Request$& request, "
536 "::grpc::CompletionQueue* cq$AsyncMethodParams$) override;\n");
537 }
538 } else if (method->BidiStreaming()) {
539 printer->Print(*vars,
540 "::grpc::ClientReaderWriter< $Request$, $Response$>* "
541 "$Method$Raw(::grpc::ClientContext* context) override;\n");
James Kuszmaul8e62b022022-03-22 09:33:25 -0700542 for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
543 i++) {
544 auto &async_prefix = async_prefixes[i];
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700545 (*vars)["AsyncPrefix"] = async_prefix.prefix;
546 (*vars)["AsyncMethodParams"] = async_prefix.method_params;
547 (*vars)["AsyncRawArgs"] = async_prefix.raw_args;
548 printer->Print(
549 *vars,
550 "::grpc::ClientAsyncReaderWriter< $Request$, $Response$>* "
551 "$AsyncPrefix$$Method$Raw(::grpc::ClientContext* context, "
552 "::grpc::CompletionQueue* cq$AsyncMethodParams$) override;\n");
553 }
554 }
555 }
556}
557
558void PrintHeaderClientMethodData(grpc_generator::Printer *printer,
559 const grpc_generator::Method *method,
560 std::map<grpc::string, grpc::string> *vars) {
561 (*vars)["Method"] = method->name();
562 printer->Print(*vars,
563 "const ::grpc::internal::RpcMethod rpcmethod_$Method$_;\n");
564}
565
566void PrintHeaderServerMethodSync(grpc_generator::Printer *printer,
567 const grpc_generator::Method *method,
568 std::map<grpc::string, grpc::string> *vars) {
569 (*vars)["Method"] = method->name();
570 (*vars)["Request"] = method->input_type_name();
571 (*vars)["Response"] = method->output_type_name();
572 printer->Print(method->GetLeadingComments("//").c_str());
573 if (method->NoStreaming()) {
574 printer->Print(*vars,
575 "virtual ::grpc::Status $Method$("
576 "::grpc::ServerContext* context, const $Request$* request, "
577 "$Response$* response);\n");
578 } else if (ClientOnlyStreaming(method)) {
579 printer->Print(*vars,
580 "virtual ::grpc::Status $Method$("
581 "::grpc::ServerContext* context, "
582 "::grpc::ServerReader< $Request$>* reader, "
583 "$Response$* response);\n");
584 } else if (ServerOnlyStreaming(method)) {
585 printer->Print(*vars,
586 "virtual ::grpc::Status $Method$("
587 "::grpc::ServerContext* context, const $Request$* request, "
588 "::grpc::ServerWriter< $Response$>* writer);\n");
589 } else if (method->BidiStreaming()) {
590 printer->Print(
591 *vars,
592 "virtual ::grpc::Status $Method$("
593 "::grpc::ServerContext* context, "
594 "::grpc::ServerReaderWriter< $Response$, $Request$>* stream);"
595 "\n");
596 }
597 printer->Print(method->GetTrailingComments("//").c_str());
598}
599
600void PrintHeaderServerMethodAsync(grpc_generator::Printer *printer,
601 const grpc_generator::Method *method,
602 std::map<grpc::string, grpc::string> *vars) {
603 (*vars)["Method"] = method->name();
604 (*vars)["Request"] = method->input_type_name();
605 (*vars)["Response"] = method->output_type_name();
606 printer->Print(*vars, "template <class BaseClass>\n");
607 printer->Print(*vars,
608 "class WithAsyncMethod_$Method$ : public BaseClass {\n");
609 printer->Print(
610 " private:\n"
James Kuszmaul8e62b022022-03-22 09:33:25 -0700611 " void BaseClassMustBeDerivedFromService(const Service */*service*/) "
612 "{}\n");
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700613 printer->Print(" public:\n");
614 printer->Indent();
615 printer->Print(*vars,
616 "WithAsyncMethod_$Method$() {\n"
617 " ::grpc::Service::MarkMethodAsync($Idx$);\n"
618 "}\n");
619 printer->Print(*vars,
620 "~WithAsyncMethod_$Method$() override {\n"
621 " BaseClassMustBeDerivedFromService(this);\n"
622 "}\n");
623 if (method->NoStreaming()) {
624 printer->Print(
625 *vars,
626 "// disable synchronous version of this method\n"
627 "::grpc::Status $Method$("
James Kuszmaul8e62b022022-03-22 09:33:25 -0700628 "::grpc::ServerContext* /*context*/, const $Request$* /*request*/, "
629 "$Response$* /*response*/) final override {\n"
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700630 " abort();\n"
631 " return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
632 "}\n");
633 printer->Print(
634 *vars,
635 "void Request$Method$("
636 "::grpc::ServerContext* context, $Request$* request, "
637 "::grpc::ServerAsyncResponseWriter< $Response$>* response, "
638 "::grpc::CompletionQueue* new_call_cq, "
639 "::grpc::ServerCompletionQueue* notification_cq, void *tag) {\n");
640 printer->Print(*vars,
641 " ::grpc::Service::RequestAsyncUnary($Idx$, context, "
642 "request, response, new_call_cq, notification_cq, tag);\n");
643 printer->Print("}\n");
644 } else if (ClientOnlyStreaming(method)) {
645 printer->Print(
646 *vars,
647 "// disable synchronous version of this method\n"
648 "::grpc::Status $Method$("
James Kuszmaul8e62b022022-03-22 09:33:25 -0700649 "::grpc::ServerContext* /*context*/, "
650 "::grpc::ServerReader< $Request$>* /*reader*/, "
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700651 "$Response$* response) final override {\n"
652 " abort();\n"
653 " return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
654 "}\n");
655 printer->Print(
656 *vars,
657 "void Request$Method$("
658 "::grpc::ServerContext* context, "
659 "::grpc::ServerAsyncReader< $Response$, $Request$>* reader, "
660 "::grpc::CompletionQueue* new_call_cq, "
661 "::grpc::ServerCompletionQueue* notification_cq, void *tag) {\n");
662 printer->Print(*vars,
663 " ::grpc::Service::RequestAsyncClientStreaming($Idx$, "
664 "context, reader, new_call_cq, notification_cq, tag);\n");
665 printer->Print("}\n");
666 } else if (ServerOnlyStreaming(method)) {
667 printer->Print(
668 *vars,
669 "// disable synchronous version of this method\n"
670 "::grpc::Status $Method$("
James Kuszmaul8e62b022022-03-22 09:33:25 -0700671 "::grpc::ServerContext* /*context*/, const $Request$* /*request*/, "
672 "::grpc::ServerWriter< $Response$>* /*writer*/) final override "
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700673 "{\n"
674 " abort();\n"
675 " return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
676 "}\n");
677 printer->Print(
678 *vars,
679 "void Request$Method$("
680 "::grpc::ServerContext* context, $Request$* request, "
681 "::grpc::ServerAsyncWriter< $Response$>* writer, "
682 "::grpc::CompletionQueue* new_call_cq, "
683 "::grpc::ServerCompletionQueue* notification_cq, void *tag) {\n");
684 printer->Print(
685 *vars,
686 " ::grpc::Service::RequestAsyncServerStreaming($Idx$, "
687 "context, request, writer, new_call_cq, notification_cq, tag);\n");
688 printer->Print("}\n");
689 } else if (method->BidiStreaming()) {
690 printer->Print(
691 *vars,
692 "// disable synchronous version of this method\n"
693 "::grpc::Status $Method$("
James Kuszmaul8e62b022022-03-22 09:33:25 -0700694 "::grpc::ServerContext* /*context*/, "
695 "::grpc::ServerReaderWriter< $Response$, $Request$>* /*stream*/) "
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700696 "final override {\n"
697 " abort();\n"
698 " return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
699 "}\n");
700 printer->Print(
701 *vars,
702 "void Request$Method$("
703 "::grpc::ServerContext* context, "
704 "::grpc::ServerAsyncReaderWriter< $Response$, $Request$>* stream, "
705 "::grpc::CompletionQueue* new_call_cq, "
706 "::grpc::ServerCompletionQueue* notification_cq, void *tag) {\n");
707 printer->Print(*vars,
708 " ::grpc::Service::RequestAsyncBidiStreaming($Idx$, "
709 "context, stream, new_call_cq, notification_cq, tag);\n");
710 printer->Print("}\n");
711 }
712 printer->Outdent();
713 printer->Print(*vars, "};\n");
714}
715
716void PrintHeaderServerMethodStreamedUnary(
717 grpc_generator::Printer *printer, const grpc_generator::Method *method,
718 std::map<grpc::string, grpc::string> *vars) {
719 (*vars)["Method"] = method->name();
720 (*vars)["Request"] = method->input_type_name();
721 (*vars)["Response"] = method->output_type_name();
722 if (method->NoStreaming()) {
723 printer->Print(*vars, "template <class BaseClass>\n");
724 printer->Print(*vars,
725 "class WithStreamedUnaryMethod_$Method$ : "
726 "public BaseClass {\n");
727 printer->Print(
728 " private:\n"
James Kuszmaul8e62b022022-03-22 09:33:25 -0700729 " void BaseClassMustBeDerivedFromService(const Service */*service*/) "
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700730 "{}\n");
731 printer->Print(" public:\n");
732 printer->Indent();
733 printer->Print(*vars,
734 "WithStreamedUnaryMethod_$Method$() {\n"
735 " ::grpc::Service::MarkMethodStreamed($Idx$,\n"
736 " new ::grpc::internal::StreamedUnaryHandler< $Request$, "
737 "$Response$>(std::bind"
738 "(&WithStreamedUnaryMethod_$Method$<BaseClass>::"
739 "Streamed$Method$, this, std::placeholders::_1, "
740 "std::placeholders::_2)));\n"
741 "}\n");
742 printer->Print(*vars,
743 "~WithStreamedUnaryMethod_$Method$() override {\n"
744 " BaseClassMustBeDerivedFromService(this);\n"
745 "}\n");
746 printer->Print(
747 *vars,
748 "// disable regular version of this method\n"
749 "::grpc::Status $Method$("
James Kuszmaul8e62b022022-03-22 09:33:25 -0700750 "::grpc::ServerContext* /*context*/, const $Request$* /*request*/, "
751 "$Response$* /*response*/) final override {\n"
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700752 " abort();\n"
753 " return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
754 "}\n");
755 printer->Print(*vars,
756 "// replace default version of method with streamed unary\n"
757 "virtual ::grpc::Status Streamed$Method$("
758 "::grpc::ServerContext* context, "
759 "::grpc::ServerUnaryStreamer< "
760 "$Request$,$Response$>* server_unary_streamer)"
761 " = 0;\n");
762 printer->Outdent();
763 printer->Print(*vars, "};\n");
764 }
765}
766
767void PrintHeaderServerMethodSplitStreaming(
768 grpc_generator::Printer *printer, const grpc_generator::Method *method,
769 std::map<grpc::string, grpc::string> *vars) {
770 (*vars)["Method"] = method->name();
771 (*vars)["Request"] = method->input_type_name();
772 (*vars)["Response"] = method->output_type_name();
773 if (ServerOnlyStreaming(method)) {
774 printer->Print(*vars, "template <class BaseClass>\n");
775 printer->Print(*vars,
776 "class WithSplitStreamingMethod_$Method$ : "
777 "public BaseClass {\n");
778 printer->Print(
779 " private:\n"
James Kuszmaul8e62b022022-03-22 09:33:25 -0700780 " void BaseClassMustBeDerivedFromService(const Service */*service*/) "
781 "{ }\n");
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700782 printer->Print(" public:\n");
783 printer->Indent();
784 printer->Print(
785 *vars,
786 "WithSplitStreamingMethod_$Method$() {\n"
787 " ::grpc::Service::MarkMethodStreamed($Idx$,\n"
788 " new ::grpc::internal::SplitServerStreamingHandler< $Request$, "
789 "$Response$>(std::bind"
790 "(&WithSplitStreamingMethod_$Method$<BaseClass>::"
791 "Streamed$Method$, this, std::placeholders::_1, "
792 "std::placeholders::_2)));\n"
793 "}\n");
794 printer->Print(*vars,
795 "~WithSplitStreamingMethod_$Method$() override {\n"
796 " BaseClassMustBeDerivedFromService(this);\n"
797 "}\n");
798 printer->Print(
799 *vars,
800 "// disable regular version of this method\n"
801 "::grpc::Status $Method$("
James Kuszmaul8e62b022022-03-22 09:33:25 -0700802 "::grpc::ServerContext* /*context*/, const $Request$* /*request*/, "
803 "::grpc::ServerWriter< $Response$>* /*writer*/) final override "
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700804 "{\n"
805 " abort();\n"
806 " return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
807 "}\n");
808 printer->Print(*vars,
809 "// replace default version of method with split streamed\n"
810 "virtual ::grpc::Status Streamed$Method$("
811 "::grpc::ServerContext* context, "
812 "::grpc::ServerSplitStreamer< "
813 "$Request$,$Response$>* server_split_streamer)"
814 " = 0;\n");
815 printer->Outdent();
816 printer->Print(*vars, "};\n");
817 }
818}
819
820void PrintHeaderServerMethodGeneric(
821 grpc_generator::Printer *printer, const grpc_generator::Method *method,
822 std::map<grpc::string, grpc::string> *vars) {
823 (*vars)["Method"] = method->name();
824 (*vars)["Request"] = method->input_type_name();
825 (*vars)["Response"] = method->output_type_name();
826 printer->Print(*vars, "template <class BaseClass>\n");
827 printer->Print(*vars,
828 "class WithGenericMethod_$Method$ : public BaseClass {\n");
829 printer->Print(
830 " private:\n"
James Kuszmaul8e62b022022-03-22 09:33:25 -0700831 " void BaseClassMustBeDerivedFromService(const Service */*service*/) "
832 "{}\n");
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700833 printer->Print(" public:\n");
834 printer->Indent();
835 printer->Print(*vars,
836 "WithGenericMethod_$Method$() {\n"
837 " ::grpc::Service::MarkMethodGeneric($Idx$);\n"
838 "}\n");
839 printer->Print(*vars,
840 "~WithGenericMethod_$Method$() override {\n"
841 " BaseClassMustBeDerivedFromService(this);\n"
842 "}\n");
843 if (method->NoStreaming()) {
844 printer->Print(
845 *vars,
846 "// disable synchronous version of this method\n"
847 "::grpc::Status $Method$("
James Kuszmaul8e62b022022-03-22 09:33:25 -0700848 "::grpc::ServerContext* /*context*/, const $Request$* /*request*/, "
849 "$Response$* /*response*/) final override {\n"
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700850 " abort();\n"
851 " return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
852 "}\n");
853 } else if (ClientOnlyStreaming(method)) {
854 printer->Print(
855 *vars,
856 "// disable synchronous version of this method\n"
857 "::grpc::Status $Method$("
James Kuszmaul8e62b022022-03-22 09:33:25 -0700858 "::grpc::ServerContext* /*context*/, "
859 "::grpc::ServerReader< $Request$>* /*reader*/, "
860 "$Response$* /*response*/) final override {\n"
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700861 " abort();\n"
862 " return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
863 "}\n");
864 } else if (ServerOnlyStreaming(method)) {
865 printer->Print(
866 *vars,
867 "// disable synchronous version of this method\n"
868 "::grpc::Status $Method$("
James Kuszmaul8e62b022022-03-22 09:33:25 -0700869 "::grpc::ServerContext* /*context*/, const $Request$* /*request*/, "
870 "::grpc::ServerWriter< $Response$>* /*writer*/) final override "
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700871 "{\n"
872 " abort();\n"
873 " return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
874 "}\n");
875 } else if (method->BidiStreaming()) {
876 printer->Print(
877 *vars,
878 "// disable synchronous version of this method\n"
879 "::grpc::Status $Method$("
James Kuszmaul8e62b022022-03-22 09:33:25 -0700880 "::grpc::ServerContext* /*context*/, "
881 "::grpc::ServerReaderWriter< $Response$, $Request$>* /*stream*/) "
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700882 "final override {\n"
883 " abort();\n"
884 " return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
885 "}\n");
886 }
887 printer->Outdent();
888 printer->Print(*vars, "};\n");
889}
890
891void PrintHeaderService(grpc_generator::Printer *printer,
892 const grpc_generator::Service *service,
893 std::map<grpc::string, grpc::string> *vars) {
894 (*vars)["Service"] = service->name();
895
896 printer->Print(service->GetLeadingComments("//").c_str());
897 printer->Print(*vars,
898 "class $Service$ final {\n"
899 " public:\n");
900 printer->Indent();
901
902 // Service metadata
903 printer->Print(*vars,
904 "static constexpr char const* service_full_name() {\n"
905 " return \"$Package$$Service$\";\n"
906 "}\n");
907
908 // Client side
909 printer->Print(
910 "class StubInterface {\n"
911 " public:\n");
912 printer->Indent();
913 printer->Print("virtual ~StubInterface() {}\n");
914 for (int i = 0; i < service->method_count(); ++i) {
915 printer->Print(service->method(i)->GetLeadingComments("//").c_str());
916 PrintHeaderClientMethodInterfaces(printer, service->method(i).get(), vars,
917 true);
918 printer->Print(service->method(i)->GetTrailingComments("//").c_str());
919 }
920 printer->Outdent();
921 printer->Print("private:\n");
922 printer->Indent();
923 for (int i = 0; i < service->method_count(); ++i) {
924 PrintHeaderClientMethodInterfaces(printer, service->method(i).get(), vars,
925 false);
926 }
927 printer->Outdent();
928 printer->Print("};\n");
929 printer->Print(
930 "class Stub final : public StubInterface"
931 " {\n public:\n");
932 printer->Indent();
933 printer->Print(
934 "Stub(const std::shared_ptr< ::grpc::ChannelInterface>& "
935 "channel);\n");
936 for (int i = 0; i < service->method_count(); ++i) {
937 PrintHeaderClientMethod(printer, service->method(i).get(), vars, true);
938 }
939 printer->Outdent();
940 printer->Print("\n private:\n");
941 printer->Indent();
942 printer->Print("std::shared_ptr< ::grpc::ChannelInterface> channel_;\n");
943 for (int i = 0; i < service->method_count(); ++i) {
944 PrintHeaderClientMethod(printer, service->method(i).get(), vars, false);
945 }
946 for (int i = 0; i < service->method_count(); ++i) {
947 PrintHeaderClientMethodData(printer, service->method(i).get(), vars);
948 }
949 printer->Outdent();
950 printer->Print("};\n");
951 printer->Print(
952 "static std::unique_ptr<Stub> NewStub(const std::shared_ptr< "
953 "::grpc::ChannelInterface>& channel, "
954 "const ::grpc::StubOptions& options = ::grpc::StubOptions());\n");
955
956 printer->Print("\n");
957
958 // Server side - base
959 printer->Print(
960 "class Service : public ::grpc::Service {\n"
961 " public:\n");
962 printer->Indent();
963 printer->Print("Service();\n");
964 printer->Print("virtual ~Service();\n");
965 for (int i = 0; i < service->method_count(); ++i) {
966 PrintHeaderServerMethodSync(printer, service->method(i).get(), vars);
967 }
968 printer->Outdent();
969 printer->Print("};\n");
970
971 // Server side - Asynchronous
972 for (int i = 0; i < service->method_count(); ++i) {
973 (*vars)["Idx"] = as_string(i);
974 PrintHeaderServerMethodAsync(printer, service->method(i).get(), vars);
975 }
976
977 printer->Print("typedef ");
978
979 for (int i = 0; i < service->method_count(); ++i) {
980 (*vars)["method_name"] = service->method(i).get()->name();
981 printer->Print(*vars, "WithAsyncMethod_$method_name$<");
982 }
983 printer->Print("Service");
James Kuszmaul8e62b022022-03-22 09:33:25 -0700984 for (int i = 0; i < service->method_count(); ++i) { printer->Print(" >"); }
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700985 printer->Print(" AsyncService;\n");
986
987 // Server side - Generic
988 for (int i = 0; i < service->method_count(); ++i) {
989 (*vars)["Idx"] = as_string(i);
990 PrintHeaderServerMethodGeneric(printer, service->method(i).get(), vars);
991 }
992
993 // Server side - Streamed Unary
994 for (int i = 0; i < service->method_count(); ++i) {
995 (*vars)["Idx"] = as_string(i);
996 PrintHeaderServerMethodStreamedUnary(printer, service->method(i).get(),
997 vars);
998 }
999
1000 printer->Print("typedef ");
1001 for (int i = 0; i < service->method_count(); ++i) {
1002 (*vars)["method_name"] = service->method(i).get()->name();
1003 if (service->method(i)->NoStreaming()) {
1004 printer->Print(*vars, "WithStreamedUnaryMethod_$method_name$<");
1005 }
1006 }
1007 printer->Print("Service");
1008 for (int i = 0; i < service->method_count(); ++i) {
James Kuszmaul8e62b022022-03-22 09:33:25 -07001009 if (service->method(i)->NoStreaming()) { printer->Print(" >"); }
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001010 }
1011 printer->Print(" StreamedUnaryService;\n");
1012
1013 // Server side - controlled server-side streaming
1014 for (int i = 0; i < service->method_count(); ++i) {
1015 (*vars)["Idx"] = as_string(i);
1016 PrintHeaderServerMethodSplitStreaming(printer, service->method(i).get(),
1017 vars);
1018 }
1019
1020 printer->Print("typedef ");
1021 for (int i = 0; i < service->method_count(); ++i) {
1022 (*vars)["method_name"] = service->method(i).get()->name();
1023 auto method = service->method(i);
1024 if (ServerOnlyStreaming(method.get())) {
1025 printer->Print(*vars, "WithSplitStreamingMethod_$method_name$<");
1026 }
1027 }
1028 printer->Print("Service");
1029 for (int i = 0; i < service->method_count(); ++i) {
1030 auto method = service->method(i);
James Kuszmaul8e62b022022-03-22 09:33:25 -07001031 if (ServerOnlyStreaming(method.get())) { printer->Print(" >"); }
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001032 }
1033 printer->Print(" SplitStreamedService;\n");
1034
1035 // Server side - typedef for controlled both unary and server-side streaming
1036 printer->Print("typedef ");
1037 for (int i = 0; i < service->method_count(); ++i) {
1038 (*vars)["method_name"] = service->method(i).get()->name();
1039 auto method = service->method(i);
1040 if (ServerOnlyStreaming(method.get())) {
1041 printer->Print(*vars, "WithSplitStreamingMethod_$method_name$<");
1042 }
1043 if (service->method(i)->NoStreaming()) {
1044 printer->Print(*vars, "WithStreamedUnaryMethod_$method_name$<");
1045 }
1046 }
1047 printer->Print("Service");
1048 for (int i = 0; i < service->method_count(); ++i) {
1049 auto method = service->method(i);
1050 if (service->method(i)->NoStreaming() ||
1051 ServerOnlyStreaming(method.get())) {
1052 printer->Print(" >");
1053 }
1054 }
1055 printer->Print(" StreamedService;\n");
1056
1057 printer->Outdent();
1058 printer->Print("};\n");
1059 printer->Print(service->GetTrailingComments("//").c_str());
1060}
1061
1062grpc::string GetHeaderServices(grpc_generator::File *file,
1063 const Parameters &params) {
1064 grpc::string output;
1065 {
1066 // Scope the output stream so it closes and finalizes output to the string.
1067 auto printer = file->CreatePrinter(&output);
1068 std::map<grpc::string, grpc::string> vars;
1069 // Package string is empty or ends with a dot. It is used to fully qualify
1070 // method names.
1071 vars["Package"] = file->package();
James Kuszmaul8e62b022022-03-22 09:33:25 -07001072 if (!file->package().empty()) { vars["Package"].append("."); }
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001073
1074 if (!params.services_namespace.empty()) {
1075 vars["services_namespace"] = params.services_namespace;
1076 printer->Print(vars, "\nnamespace $services_namespace$ {\n\n");
1077 }
1078
1079 for (int i = 0; i < file->service_count(); ++i) {
1080 PrintHeaderService(printer.get(), file->service(i).get(), &vars);
1081 printer->Print("\n");
1082 }
1083
1084 if (!params.services_namespace.empty()) {
1085 printer->Print(vars, "} // namespace $services_namespace$\n\n");
1086 }
1087 }
1088 return output;
1089}
1090
1091grpc::string GetHeaderEpilogue(grpc_generator::File *file,
1092 const Parameters & /*params*/) {
1093 grpc::string output;
1094 {
1095 // Scope the output stream so it closes and finalizes output to the string.
1096 auto printer = file->CreatePrinter(&output);
1097 std::map<grpc::string, grpc::string> vars;
1098
1099 vars["filename"] = file->filename();
1100 vars["filename_identifier"] = FilenameIdentifier(file->filename());
1101
1102 if (!file->package().empty()) {
1103 std::vector<grpc::string> parts = file->package_parts();
1104
1105 for (auto part = parts.rbegin(); part != parts.rend(); part++) {
1106 vars["part"] = *part;
1107 printer->Print(vars, "} // namespace $part$\n");
1108 }
1109 printer->Print(vars, "\n");
1110 }
1111
1112 printer->Print(vars, "\n");
1113 printer->Print(vars, "#endif // GRPC_$filename_identifier$__INCLUDED\n");
1114
1115 printer->Print(file->GetTrailingComments("//").c_str());
1116 }
1117 return output;
1118}
1119
1120grpc::string GetSourcePrologue(grpc_generator::File *file,
1121 const Parameters & /*params*/) {
1122 grpc::string output;
1123 {
1124 // Scope the output stream so it closes and finalizes output to the string.
1125 auto printer = file->CreatePrinter(&output);
1126 std::map<grpc::string, grpc::string> vars;
1127
1128 vars["filename"] = file->filename();
1129 vars["filename_base"] = file->filename_without_ext();
James Kuszmaul8e62b022022-03-22 09:33:25 -07001130 vars["message_header_ext"] = file->message_header_ext();
1131 vars["service_header_ext"] = file->service_header_ext();
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001132
1133 printer->Print(vars, "// Generated by the gRPC C++ plugin.\n");
1134 printer->Print(vars,
1135 "// If you make any local change, they will be lost.\n");
1136 printer->Print(vars, "// source: $filename$\n\n");
1137
1138 printer->Print(vars, "#include \"$filename_base$$message_header_ext$\"\n");
1139 printer->Print(vars, "#include \"$filename_base$$service_header_ext$\"\n");
1140 printer->Print(vars, "\n");
1141 }
1142 return output;
1143}
1144
1145grpc::string GetSourceIncludes(grpc_generator::File *file,
1146 const Parameters &params) {
1147 grpc::string output;
1148 {
1149 // Scope the output stream so it closes and finalizes output to the string.
1150 auto printer = file->CreatePrinter(&output);
1151 std::map<grpc::string, grpc::string> vars;
1152
1153 static const char *headers_strs[] = {
James Kuszmaul8e62b022022-03-22 09:33:25 -07001154 "grpcpp/impl/codegen/async_stream.h",
1155 "grpcpp/impl/codegen/async_unary_call.h",
1156 "grpcpp/impl/codegen/channel_interface.h",
1157 "grpcpp/impl/codegen/client_unary_call.h",
1158 "grpcpp/impl/codegen/method_handler.h",
1159 "grpcpp/impl/codegen/rpc_service_method.h",
1160 "grpcpp/impl/codegen/service_type.h",
1161 "grpcpp/impl/codegen/sync_stream.h"
1162 };
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001163 std::vector<grpc::string> headers(headers_strs, array_end(headers_strs));
1164 PrintIncludes(printer.get(), headers, params);
1165
1166 if (!file->package().empty()) {
1167 std::vector<grpc::string> parts = file->package_parts();
1168
1169 for (auto part = parts.begin(); part != parts.end(); part++) {
1170 vars["part"] = *part;
1171 printer->Print(vars, "namespace $part$ {\n");
1172 }
1173 }
1174
1175 printer->Print(vars, "\n");
1176 }
1177 return output;
1178}
1179
1180void PrintSourceClientMethod(grpc_generator::Printer *printer,
1181 const grpc_generator::Method *method,
1182 std::map<grpc::string, grpc::string> *vars) {
1183 (*vars)["Method"] = method->name();
1184 (*vars)["Request"] = method->input_type_name();
1185 (*vars)["Response"] = method->output_type_name();
1186 struct {
1187 grpc::string prefix;
1188 grpc::string start; // bool literal expressed as string
1189 grpc::string method_params; // extra arguments to method
1190 grpc::string create_args; // extra arguments to creator
James Kuszmaul8e62b022022-03-22 09:33:25 -07001191 } async_prefixes[] = { { "Async", "true", ", void* tag", ", tag" },
1192 { "PrepareAsync", "false", "", ", nullptr" } };
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001193 if (method->NoStreaming()) {
1194 printer->Print(*vars,
1195 "::grpc::Status $ns$$Service$::Stub::$Method$("
1196 "::grpc::ClientContext* context, "
1197 "const $Request$& request, $Response$* response) {\n");
1198 printer->Print(*vars,
1199 " return ::grpc::internal::BlockingUnaryCall"
1200 "(channel_.get(), rpcmethod_$Method$_, "
1201 "context, request, response);\n}\n\n");
James Kuszmaul8e62b022022-03-22 09:33:25 -07001202 for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
1203 i++) {
1204 auto &async_prefix = async_prefixes[i];
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001205 (*vars)["AsyncPrefix"] = async_prefix.prefix;
1206 (*vars)["AsyncStart"] = async_prefix.start;
1207 printer->Print(*vars,
1208 "::grpc::ClientAsyncResponseReader< $Response$>* "
1209 "$ns$$Service$::Stub::$AsyncPrefix$$Method$Raw(::grpc::"
1210 "ClientContext* context, "
1211 "const $Request$& request, "
1212 "::grpc::CompletionQueue* cq) {\n");
1213 printer->Print(
1214 *vars,
1215 " return "
1216 "::grpc::internal::ClientAsyncResponseReaderFactory< $Response$>"
1217 "::Create(channel_.get(), cq, "
1218 "rpcmethod_$Method$_, "
1219 "context, request, $AsyncStart$);\n"
1220 "}\n\n");
1221 }
1222 } else if (ClientOnlyStreaming(method)) {
1223 printer->Print(*vars,
1224 "::grpc::ClientWriter< $Request$>* "
1225 "$ns$$Service$::Stub::$Method$Raw("
1226 "::grpc::ClientContext* context, $Response$* response) {\n");
1227 printer->Print(
1228 *vars,
1229 " return ::grpc::internal::ClientWriterFactory< $Request$>::Create("
1230 "channel_.get(), "
1231 "rpcmethod_$Method$_, "
1232 "context, response);\n"
1233 "}\n\n");
James Kuszmaul8e62b022022-03-22 09:33:25 -07001234 for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
1235 i++) {
1236 auto &async_prefix = async_prefixes[i];
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001237 (*vars)["AsyncPrefix"] = async_prefix.prefix;
1238 (*vars)["AsyncStart"] = async_prefix.start;
1239 (*vars)["AsyncMethodParams"] = async_prefix.method_params;
1240 (*vars)["AsyncCreateArgs"] = async_prefix.create_args;
1241 printer->Print(*vars,
1242 "::grpc::ClientAsyncWriter< $Request$>* "
1243 "$ns$$Service$::Stub::$AsyncPrefix$$Method$Raw("
1244 "::grpc::ClientContext* context, $Response$* response, "
1245 "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
1246 printer->Print(
1247 *vars,
1248 " return ::grpc::internal::ClientAsyncWriterFactory< $Request$>"
1249 "::Create(channel_.get(), cq, "
1250 "rpcmethod_$Method$_, "
1251 "context, response, $AsyncStart$$AsyncCreateArgs$);\n"
1252 "}\n\n");
1253 }
1254 } else if (ServerOnlyStreaming(method)) {
1255 printer->Print(
1256 *vars,
1257 "::grpc::ClientReader< $Response$>* "
1258 "$ns$$Service$::Stub::$Method$Raw("
1259 "::grpc::ClientContext* context, const $Request$& request) {\n");
1260 printer->Print(
1261 *vars,
1262 " return ::grpc::internal::ClientReaderFactory< $Response$>::Create("
1263 "channel_.get(), "
1264 "rpcmethod_$Method$_, "
1265 "context, request);\n"
1266 "}\n\n");
James Kuszmaul8e62b022022-03-22 09:33:25 -07001267 for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
1268 i++) {
1269 auto &async_prefix = async_prefixes[i];
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001270 (*vars)["AsyncPrefix"] = async_prefix.prefix;
1271 (*vars)["AsyncStart"] = async_prefix.start;
1272 (*vars)["AsyncMethodParams"] = async_prefix.method_params;
1273 (*vars)["AsyncCreateArgs"] = async_prefix.create_args;
1274 printer->Print(
1275 *vars,
1276 "::grpc::ClientAsyncReader< $Response$>* "
1277 "$ns$$Service$::Stub::$AsyncPrefix$$Method$Raw("
1278 "::grpc::ClientContext* context, const $Request$& request, "
1279 "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
1280 printer->Print(
1281 *vars,
1282 " return ::grpc::internal::ClientAsyncReaderFactory< $Response$>"
1283 "::Create(channel_.get(), cq, "
1284 "rpcmethod_$Method$_, "
1285 "context, request, $AsyncStart$$AsyncCreateArgs$);\n"
1286 "}\n\n");
1287 }
1288 } else if (method->BidiStreaming()) {
1289 printer->Print(
1290 *vars,
1291 "::grpc::ClientReaderWriter< $Request$, $Response$>* "
1292 "$ns$$Service$::Stub::$Method$Raw(::grpc::ClientContext* context) {\n");
1293 printer->Print(*vars,
1294 " return ::grpc::internal::ClientReaderWriterFactory< "
1295 "$Request$, $Response$>::Create("
1296 "channel_.get(), "
1297 "rpcmethod_$Method$_, "
1298 "context);\n"
1299 "}\n\n");
James Kuszmaul8e62b022022-03-22 09:33:25 -07001300 for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
1301 i++) {
1302 auto &async_prefix = async_prefixes[i];
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001303 (*vars)["AsyncPrefix"] = async_prefix.prefix;
1304 (*vars)["AsyncStart"] = async_prefix.start;
1305 (*vars)["AsyncMethodParams"] = async_prefix.method_params;
1306 (*vars)["AsyncCreateArgs"] = async_prefix.create_args;
1307 printer->Print(*vars,
1308 "::grpc::ClientAsyncReaderWriter< $Request$, $Response$>* "
1309 "$ns$$Service$::Stub::$AsyncPrefix$$Method$Raw(::grpc::"
1310 "ClientContext* context, "
1311 "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
1312 printer->Print(*vars,
1313 " return "
1314 "::grpc::internal::ClientAsyncReaderWriterFactory< "
1315 "$Request$, $Response$>::Create("
1316 "channel_.get(), cq, "
1317 "rpcmethod_$Method$_, "
1318 "context, $AsyncStart$$AsyncCreateArgs$);\n"
1319 "}\n\n");
1320 }
1321 }
1322}
1323
1324void PrintSourceServerMethod(grpc_generator::Printer *printer,
1325 const grpc_generator::Method *method,
1326 std::map<grpc::string, grpc::string> *vars) {
1327 (*vars)["Method"] = method->name();
1328 (*vars)["Request"] = method->input_type_name();
1329 (*vars)["Response"] = method->output_type_name();
1330 if (method->NoStreaming()) {
James Kuszmaul8e62b022022-03-22 09:33:25 -07001331 printer->Print(
1332 *vars,
1333 "::grpc::Status $ns$$Service$::Service::$Method$("
1334 "::grpc::ServerContext* /*context*/, "
1335 "const $Request$* /*request*/, $Response$* /*response*/) {\n");
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001336 printer->Print(
1337 " return ::grpc::Status("
1338 "::grpc::StatusCode::UNIMPLEMENTED, \"\");\n");
1339 printer->Print("}\n\n");
1340 } else if (ClientOnlyStreaming(method)) {
1341 printer->Print(*vars,
1342 "::grpc::Status $ns$$Service$::Service::$Method$("
James Kuszmaul8e62b022022-03-22 09:33:25 -07001343 "::grpc::ServerContext* /*context*/, "
1344 "::grpc::ServerReader< $Request$>* /*reader*/, "
1345 "$Response$* /*response*/) {\n");
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001346 printer->Print(
1347 " return ::grpc::Status("
1348 "::grpc::StatusCode::UNIMPLEMENTED, \"\");\n");
1349 printer->Print("}\n\n");
1350 } else if (ServerOnlyStreaming(method)) {
1351 printer->Print(*vars,
1352 "::grpc::Status $ns$$Service$::Service::$Method$("
James Kuszmaul8e62b022022-03-22 09:33:25 -07001353 "::grpc::ServerContext* /*context*/, "
1354 "const $Request$* /*request*/, "
1355 "::grpc::ServerWriter< $Response$>* /*writer*/) {\n");
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001356 printer->Print(
1357 " return ::grpc::Status("
1358 "::grpc::StatusCode::UNIMPLEMENTED, \"\");\n");
1359 printer->Print("}\n\n");
1360 } else if (method->BidiStreaming()) {
1361 printer->Print(*vars,
1362 "::grpc::Status $ns$$Service$::Service::$Method$("
James Kuszmaul8e62b022022-03-22 09:33:25 -07001363 "::grpc::ServerContext* /*context*/, "
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001364 "::grpc::ServerReaderWriter< $Response$, $Request$>* "
James Kuszmaul8e62b022022-03-22 09:33:25 -07001365 "/*stream*/) {\n");
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001366 printer->Print(
1367 " return ::grpc::Status("
1368 "::grpc::StatusCode::UNIMPLEMENTED, \"\");\n");
1369 printer->Print("}\n\n");
1370 }
1371}
1372
1373void PrintSourceService(grpc_generator::Printer *printer,
1374 const grpc_generator::Service *service,
1375 std::map<grpc::string, grpc::string> *vars) {
1376 (*vars)["Service"] = service->name();
1377
1378 if (service->method_count() > 0) {
1379 printer->Print(*vars,
1380 "static const char* $prefix$$Service$_method_names[] = {\n");
1381 for (int i = 0; i < service->method_count(); ++i) {
1382 (*vars)["Method"] = service->method(i).get()->name();
1383 printer->Print(*vars, " \"/$Package$$Service$/$Method$\",\n");
1384 }
1385 printer->Print(*vars, "};\n\n");
1386 }
1387
1388 printer->Print(*vars,
1389 "std::unique_ptr< $ns$$Service$::Stub> $ns$$Service$::NewStub("
1390 "const std::shared_ptr< ::grpc::ChannelInterface>& channel, "
James Kuszmaul8e62b022022-03-22 09:33:25 -07001391 "const ::grpc::StubOptions& /*options*/) {\n"
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001392 " std::unique_ptr< $ns$$Service$::Stub> stub(new "
1393 "$ns$$Service$::Stub(channel));\n"
1394 " return stub;\n"
1395 "}\n\n");
1396 printer->Print(*vars,
1397 "$ns$$Service$::Stub::Stub(const std::shared_ptr< "
1398 "::grpc::ChannelInterface>& channel)\n");
1399 printer->Indent();
1400 printer->Print(": channel_(channel)");
1401 for (int i = 0; i < service->method_count(); ++i) {
1402 auto method = service->method(i);
1403 (*vars)["Method"] = method->name();
1404 (*vars)["Idx"] = as_string(i);
1405 if (method->NoStreaming()) {
1406 (*vars)["StreamingType"] = "NORMAL_RPC";
1407 // NOTE: There is no reason to consider streamed-unary as a separate
1408 // category here since this part is setting up the client-side stub
1409 // and this appears as a NORMAL_RPC from the client-side.
1410 } else if (ClientOnlyStreaming(method.get())) {
1411 (*vars)["StreamingType"] = "CLIENT_STREAMING";
1412 } else if (ServerOnlyStreaming(method.get())) {
1413 (*vars)["StreamingType"] = "SERVER_STREAMING";
1414 } else {
1415 (*vars)["StreamingType"] = "BIDI_STREAMING";
1416 }
1417 printer->Print(*vars,
1418 ", rpcmethod_$Method$_("
1419 "$prefix$$Service$_method_names[$Idx$], "
1420 "::grpc::internal::RpcMethod::$StreamingType$, "
1421 "channel"
1422 ")\n");
1423 }
1424 printer->Print("{}\n\n");
1425 printer->Outdent();
1426
1427 for (int i = 0; i < service->method_count(); ++i) {
1428 (*vars)["Idx"] = as_string(i);
1429 PrintSourceClientMethod(printer, service->method(i).get(), vars);
1430 }
1431
1432 printer->Print(*vars, "$ns$$Service$::Service::Service() {\n");
1433 printer->Indent();
1434 for (int i = 0; i < service->method_count(); ++i) {
1435 auto method = service->method(i);
1436 (*vars)["Idx"] = as_string(i);
1437 (*vars)["Method"] = method->name();
1438 (*vars)["Request"] = method->input_type_name();
1439 (*vars)["Response"] = method->output_type_name();
1440 if (method->NoStreaming()) {
1441 printer->Print(
1442 *vars,
1443 "AddMethod(new ::grpc::internal::RpcServiceMethod(\n"
1444 " $prefix$$Service$_method_names[$Idx$],\n"
1445 " ::grpc::internal::RpcMethod::NORMAL_RPC,\n"
1446 " new ::grpc::internal::RpcMethodHandler< $ns$$Service$::Service, "
1447 "$Request$, "
1448 "$Response$>(\n"
1449 " std::mem_fn(&$ns$$Service$::Service::$Method$), this)));\n");
1450 } else if (ClientOnlyStreaming(method.get())) {
1451 printer->Print(
1452 *vars,
1453 "AddMethod(new ::grpc::internal::RpcServiceMethod(\n"
1454 " $prefix$$Service$_method_names[$Idx$],\n"
1455 " ::grpc::internal::RpcMethod::CLIENT_STREAMING,\n"
1456 " new ::grpc::internal::ClientStreamingHandler< "
1457 "$ns$$Service$::Service, $Request$, $Response$>(\n"
1458 " std::mem_fn(&$ns$$Service$::Service::$Method$), this)));\n");
1459 } else if (ServerOnlyStreaming(method.get())) {
1460 printer->Print(
1461 *vars,
1462 "AddMethod(new ::grpc::internal::RpcServiceMethod(\n"
1463 " $prefix$$Service$_method_names[$Idx$],\n"
1464 " ::grpc::internal::RpcMethod::SERVER_STREAMING,\n"
1465 " new ::grpc::internal::ServerStreamingHandler< "
1466 "$ns$$Service$::Service, $Request$, $Response$>(\n"
1467 " std::mem_fn(&$ns$$Service$::Service::$Method$), this)));\n");
1468 } else if (method->BidiStreaming()) {
1469 printer->Print(
1470 *vars,
1471 "AddMethod(new ::grpc::internal::RpcServiceMethod(\n"
1472 " $prefix$$Service$_method_names[$Idx$],\n"
1473 " ::grpc::internal::RpcMethod::BIDI_STREAMING,\n"
1474 " new ::grpc::internal::BidiStreamingHandler< "
1475 "$ns$$Service$::Service, $Request$, $Response$>(\n"
1476 " std::mem_fn(&$ns$$Service$::Service::$Method$), this)));\n");
1477 }
1478 }
1479 printer->Outdent();
1480 printer->Print(*vars, "}\n\n");
1481 printer->Print(*vars,
1482 "$ns$$Service$::Service::~Service() {\n"
1483 "}\n\n");
1484 for (int i = 0; i < service->method_count(); ++i) {
1485 (*vars)["Idx"] = as_string(i);
1486 PrintSourceServerMethod(printer, service->method(i).get(), vars);
1487 }
1488}
1489
1490grpc::string GetSourceServices(grpc_generator::File *file,
1491 const Parameters &params) {
1492 grpc::string output;
1493 {
1494 // Scope the output stream so it closes and finalizes output to the string.
1495 auto printer = file->CreatePrinter(&output);
1496 std::map<grpc::string, grpc::string> vars;
1497 // Package string is empty or ends with a dot. It is used to fully qualify
1498 // method names.
1499 vars["Package"] = file->package();
James Kuszmaul8e62b022022-03-22 09:33:25 -07001500 if (!file->package().empty()) { vars["Package"].append("."); }
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001501 if (!params.services_namespace.empty()) {
1502 vars["ns"] = params.services_namespace + "::";
1503 vars["prefix"] = params.services_namespace;
1504 } else {
1505 vars["ns"] = "";
1506 vars["prefix"] = "";
1507 }
1508
1509 for (int i = 0; i < file->service_count(); ++i) {
1510 PrintSourceService(printer.get(), file->service(i).get(), &vars);
1511 printer->Print("\n");
1512 }
1513 }
1514 return output;
1515}
1516
1517grpc::string GetSourceEpilogue(grpc_generator::File *file,
1518 const Parameters & /*params*/) {
1519 grpc::string temp;
1520
1521 if (!file->package().empty()) {
1522 std::vector<grpc::string> parts = file->package_parts();
1523
1524 for (auto part = parts.begin(); part != parts.end(); part++) {
1525 temp.append("} // namespace ");
1526 temp.append(*part);
1527 temp.append("\n");
1528 }
1529 temp.append("\n");
1530 }
1531
1532 return temp;
1533}
1534
1535// TODO(mmukhi): Make sure we need parameters or not.
1536grpc::string GetMockPrologue(grpc_generator::File *file,
1537 const Parameters & /*params*/) {
1538 grpc::string output;
1539 {
1540 // Scope the output stream so it closes and finalizes output to the string.
1541 auto printer = file->CreatePrinter(&output);
1542 std::map<grpc::string, grpc::string> vars;
1543
1544 vars["filename"] = file->filename();
1545 vars["filename_base"] = file->filename_without_ext();
1546 vars["message_header_ext"] = message_header_ext();
1547 vars["service_header_ext"] = service_header_ext();
1548
1549 printer->Print(vars, "// Generated by the gRPC C++ plugin.\n");
1550 printer->Print(vars,
1551 "// If you make any local change, they will be lost.\n");
1552 printer->Print(vars, "// source: $filename$\n\n");
1553
1554 printer->Print(vars, "#include \"$filename_base$$message_header_ext$\"\n");
1555 printer->Print(vars, "#include \"$filename_base$$service_header_ext$\"\n");
1556 printer->Print(vars, file->additional_headers().c_str());
1557 printer->Print(vars, "\n");
1558 }
1559 return output;
1560}
1561
1562// TODO(mmukhi): Add client-stream and completion-queue headers.
1563grpc::string GetMockIncludes(grpc_generator::File *file,
1564 const Parameters &params) {
1565 grpc::string output;
1566 {
1567 // Scope the output stream so it closes and finalizes output to the string.
1568 auto printer = file->CreatePrinter(&output);
1569 std::map<grpc::string, grpc::string> vars;
1570
1571 static const char *headers_strs[] = {
James Kuszmaul8e62b022022-03-22 09:33:25 -07001572 "grpcpp/impl/codegen/async_stream.h",
1573 "grpcpp/impl/codegen/sync_stream.h",
1574 "gmock/gmock.h",
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001575 };
1576 std::vector<grpc::string> headers(headers_strs, array_end(headers_strs));
1577 PrintIncludes(printer.get(), headers, params);
1578
1579 if (!file->package().empty()) {
1580 std::vector<grpc::string> parts = file->package_parts();
1581
1582 for (auto part = parts.begin(); part != parts.end(); part++) {
1583 vars["part"] = *part;
1584 printer->Print(vars, "namespace $part$ {\n");
1585 }
1586 }
1587
1588 printer->Print(vars, "\n");
1589 }
1590 return output;
1591}
1592
1593void PrintMockClientMethods(grpc_generator::Printer *printer,
1594 const grpc_generator::Method *method,
1595 std::map<grpc::string, grpc::string> *vars) {
1596 (*vars)["Method"] = method->name();
1597 (*vars)["Request"] = method->input_type_name();
1598 (*vars)["Response"] = method->output_type_name();
1599
1600 struct {
1601 grpc::string prefix;
1602 grpc::string method_params; // extra arguments to method
1603 int extra_method_param_count;
James Kuszmaul8e62b022022-03-22 09:33:25 -07001604 } async_prefixes[] = { { "Async", ", void* tag", 1 },
1605 { "PrepareAsync", "", 0 } };
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001606
1607 if (method->NoStreaming()) {
1608 printer->Print(
1609 *vars,
1610 "MOCK_METHOD3($Method$, ::grpc::Status(::grpc::ClientContext* context, "
1611 "const $Request$& request, $Response$* response));\n");
James Kuszmaul8e62b022022-03-22 09:33:25 -07001612 for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
1613 i++) {
1614 auto &async_prefix = async_prefixes[i];
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001615 (*vars)["AsyncPrefix"] = async_prefix.prefix;
1616 printer->Print(
1617 *vars,
1618 "MOCK_METHOD3($AsyncPrefix$$Method$Raw, "
1619 "::grpc::ClientAsyncResponseReaderInterface< $Response$>*"
1620 "(::grpc::ClientContext* context, const $Request$& request, "
1621 "::grpc::CompletionQueue* cq));\n");
1622 }
1623 } else if (ClientOnlyStreaming(method)) {
1624 printer->Print(
1625 *vars,
1626 "MOCK_METHOD2($Method$Raw, "
1627 "::grpc::ClientWriterInterface< $Request$>*"
1628 "(::grpc::ClientContext* context, $Response$* response));\n");
James Kuszmaul8e62b022022-03-22 09:33:25 -07001629 for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
1630 i++) {
1631 auto &async_prefix = async_prefixes[i];
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001632 (*vars)["AsyncPrefix"] = async_prefix.prefix;
1633 (*vars)["AsyncMethodParams"] = async_prefix.method_params;
1634 (*vars)["MockArgs"] =
James Kuszmaul8e62b022022-03-22 09:33:25 -07001635 flatbuffers::NumToString(3 + async_prefix.extra_method_param_count);
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001636 printer->Print(*vars,
1637 "MOCK_METHOD$MockArgs$($AsyncPrefix$$Method$Raw, "
1638 "::grpc::ClientAsyncWriterInterface< $Request$>*"
1639 "(::grpc::ClientContext* context, $Response$* response, "
1640 "::grpc::CompletionQueue* cq$AsyncMethodParams$));\n");
1641 }
1642 } else if (ServerOnlyStreaming(method)) {
1643 printer->Print(
1644 *vars,
1645 "MOCK_METHOD2($Method$Raw, "
1646 "::grpc::ClientReaderInterface< $Response$>*"
1647 "(::grpc::ClientContext* context, const $Request$& request));\n");
James Kuszmaul8e62b022022-03-22 09:33:25 -07001648 for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
1649 i++) {
1650 auto &async_prefix = async_prefixes[i];
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001651 (*vars)["AsyncPrefix"] = async_prefix.prefix;
1652 (*vars)["AsyncMethodParams"] = async_prefix.method_params;
1653 (*vars)["MockArgs"] =
1654 flatbuffers::NumToString(3 + async_prefix.extra_method_param_count);
1655 printer->Print(
1656 *vars,
1657 "MOCK_METHOD$MockArgs$($AsyncPrefix$$Method$Raw, "
1658 "::grpc::ClientAsyncReaderInterface< $Response$>*"
1659 "(::grpc::ClientContext* context, const $Request$& request, "
1660 "::grpc::CompletionQueue* cq$AsyncMethodParams$));\n");
1661 }
1662 } else if (method->BidiStreaming()) {
1663 printer->Print(
1664 *vars,
1665 "MOCK_METHOD1($Method$Raw, "
1666 "::grpc::ClientReaderWriterInterface< $Request$, $Response$>*"
1667 "(::grpc::ClientContext* context));\n");
James Kuszmaul8e62b022022-03-22 09:33:25 -07001668 for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
1669 i++) {
1670 auto &async_prefix = async_prefixes[i];
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001671 (*vars)["AsyncPrefix"] = async_prefix.prefix;
1672 (*vars)["AsyncMethodParams"] = async_prefix.method_params;
1673 (*vars)["MockArgs"] =
1674 flatbuffers::NumToString(2 + async_prefix.extra_method_param_count);
1675 printer->Print(
1676 *vars,
1677 "MOCK_METHOD$MockArgs$($AsyncPrefix$$Method$Raw, "
1678 "::grpc::ClientAsyncReaderWriterInterface<$Request$, $Response$>*"
1679 "(::grpc::ClientContext* context, ::grpc::CompletionQueue* cq"
1680 "$AsyncMethodParams$));\n");
1681 }
1682 }
1683}
1684
1685void PrintMockService(grpc_generator::Printer *printer,
1686 const grpc_generator::Service *service,
1687 std::map<grpc::string, grpc::string> *vars) {
1688 (*vars)["Service"] = service->name();
1689
1690 printer->Print(*vars,
1691 "class Mock$Service$Stub : public $Service$::StubInterface {\n"
1692 " public:\n");
1693 printer->Indent();
1694 for (int i = 0; i < service->method_count(); ++i) {
1695 PrintMockClientMethods(printer, service->method(i).get(), vars);
1696 }
1697 printer->Outdent();
1698 printer->Print("};\n");
1699}
1700
1701grpc::string GetMockServices(grpc_generator::File *file,
1702 const Parameters &params) {
1703 grpc::string output;
1704 {
1705 // Scope the output stream so it closes and finalizes output to the string.
1706 auto printer = file->CreatePrinter(&output);
1707 std::map<grpc::string, grpc::string> vars;
1708 // Package string is empty or ends with a dot. It is used to fully qualify
1709 // method names.
1710 vars["Package"] = file->package();
James Kuszmaul8e62b022022-03-22 09:33:25 -07001711 if (!file->package().empty()) { vars["Package"].append("."); }
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001712
1713 if (!params.services_namespace.empty()) {
1714 vars["services_namespace"] = params.services_namespace;
1715 printer->Print(vars, "\nnamespace $services_namespace$ {\n\n");
1716 }
1717
1718 for (int i = 0; i < file->service_count(); i++) {
1719 PrintMockService(printer.get(), file->service(i).get(), &vars);
1720 printer->Print("\n");
1721 }
1722
1723 if (!params.services_namespace.empty()) {
1724 printer->Print(vars, "} // namespace $services_namespace$\n\n");
1725 }
1726 }
1727 return output;
1728}
1729
1730grpc::string GetMockEpilogue(grpc_generator::File *file,
1731 const Parameters & /*params*/) {
1732 grpc::string temp;
1733
1734 if (!file->package().empty()) {
1735 std::vector<grpc::string> parts = file->package_parts();
1736
1737 for (auto part = parts.begin(); part != parts.end(); part++) {
1738 temp.append("} // namespace ");
1739 temp.append(*part);
1740 temp.append("\n");
1741 }
1742 temp.append("\n");
1743 }
1744
1745 return temp;
1746}
1747
1748} // namespace grpc_cpp_generator