blob: fd635f2fa5e8bf7b7b48380b82306f97534fd84f [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
Austin Schuh2dd86a92022-09-14 21:19:23 -070011static grpc::string service_header_ext() { return ".grpc.fb.h"; }
Austin Schuhe89fa2d2019-08-14 20:24:23 -070012
Austin Schuh2dd86a92022-09-14 21:19:23 -070013template<class T>
14static 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
Austin Schuh2dd86a92022-09-14 21:19:23 -070020static inline bool ClientOnlyStreaming(const grpc_generator::Method *method) {
Austin Schuhe89fa2d2019-08-14 20:24:23 -070021 return method->ClientStreaming() && !method->ServerStreaming();
22}
23
Austin Schuh2dd86a92022-09-14 21:19:23 -070024static inline bool ServerOnlyStreaming(const grpc_generator::Method *method) {
Austin Schuhe89fa2d2019-08-14 20:24:23 -070025 return !method->ClientStreaming() && method->ServerStreaming();
26}
27
Austin Schuh2dd86a92022-09-14 21:19:23 -070028static grpc::string FilenameIdentifier(const grpc::string &filename) {
Austin Schuhe89fa2d2019-08-14 20:24:23 -070029 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}
Austin Schuhe89fa2d2019-08-14 20:24:23 -070043
Austin Schuh2dd86a92022-09-14 21:19:23 -070044template<class T, size_t N>
45static T *array_end(T (&array)[N]) { return array + N; }
Austin Schuhe89fa2d2019-08-14 20:24:23 -070046
Austin Schuh2dd86a92022-09-14 21:19:23 -070047static void PrintIncludes(grpc_generator::Printer *printer,
Austin Schuhe89fa2d2019-08-14 20:24:23 -070048 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
Austin Schuh2dd86a92022-09-14 21:19:23 -070067} // namespace
68
Austin Schuhe89fa2d2019-08-14 20:24:23 -070069grpc::string GetHeaderPrologue(grpc_generator::File *file,
Austin Schuh2dd86a92022-09-14 21:19:23 -070070 const Parameters &params) {
Austin Schuhe89fa2d2019-08-14 20:24:23 -070071 grpc::string output;
72 {
73 // Scope the output stream so it closes and finalizes output to the string.
74 auto printer = file->CreatePrinter(&output);
75 std::map<grpc::string, grpc::string> vars;
76
77 vars["filename"] = file->filename();
78 vars["filename_identifier"] = FilenameIdentifier(file->filename());
79 vars["filename_base"] = file->filename_without_ext();
Austin Schuh2dd86a92022-09-14 21:19:23 -070080 vars["message_header_ext"] = params.message_header_extension;
Austin Schuhe89fa2d2019-08-14 20:24:23 -070081
82 printer->Print(vars, "// Generated by the gRPC C++ plugin.\n");
83 printer->Print(vars,
84 "// If you make any local change, they will be lost.\n");
85 printer->Print(vars, "// source: $filename$\n");
86 grpc::string leading_comments = file->GetLeadingComments("//");
87 if (!leading_comments.empty()) {
88 printer->Print(vars, "// Original file comments:\n");
89 printer->Print(leading_comments.c_str());
90 }
91 printer->Print(vars, "#ifndef GRPC_$filename_identifier$__INCLUDED\n");
92 printer->Print(vars, "#define GRPC_$filename_identifier$__INCLUDED\n");
93 printer->Print(vars, "\n");
94 printer->Print(vars, "#include \"$filename_base$$message_header_ext$\"\n");
95 printer->Print(vars, file->additional_headers().c_str());
96 printer->Print(vars, "\n");
97 }
98 return output;
99}
100
101grpc::string GetHeaderIncludes(grpc_generator::File *file,
102 const Parameters &params) {
103 grpc::string output;
104 {
105 // Scope the output stream so it closes and finalizes output to the string.
106 auto printer = file->CreatePrinter(&output);
107 std::map<grpc::string, grpc::string> vars;
108
109 static const char *headers_strs[] = {
James Kuszmaul8e62b022022-03-22 09:33:25 -0700110 "grpcpp/impl/codegen/async_stream.h",
111 "grpcpp/impl/codegen/async_unary_call.h",
112 "grpcpp/impl/codegen/method_handler.h",
113 "grpcpp/impl/codegen/proto_utils.h",
114 "grpcpp/impl/codegen/rpc_method.h",
115 "grpcpp/impl/codegen/service_type.h",
116 "grpcpp/impl/codegen/status.h",
117 "grpcpp/impl/codegen/stub_options.h",
118 "grpcpp/impl/codegen/sync_stream.h"
119 };
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700120 std::vector<grpc::string> headers(headers_strs, array_end(headers_strs));
121 PrintIncludes(printer.get(), headers, params);
122 printer->Print(vars, "\n");
123 printer->Print(vars, "namespace grpc {\n");
124 printer->Print(vars, "class CompletionQueue;\n");
125 printer->Print(vars, "class Channel;\n");
126 printer->Print(vars, "class ServerCompletionQueue;\n");
127 printer->Print(vars, "class ServerContext;\n");
128 printer->Print(vars, "} // namespace grpc\n\n");
129
130 if (!file->package().empty()) {
131 std::vector<grpc::string> parts = file->package_parts();
132
133 for (auto part = parts.begin(); part != parts.end(); part++) {
134 vars["part"] = *part;
135 printer->Print(vars, "namespace $part$ {\n");
136 }
137 printer->Print(vars, "\n");
138 }
139 }
140 return output;
141}
142
Austin Schuh2dd86a92022-09-14 21:19:23 -0700143
144namespace {
145
146static void PrintHeaderClientMethodInterfaces(
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700147 grpc_generator::Printer *printer, const grpc_generator::Method *method,
148 std::map<grpc::string, grpc::string> *vars, bool is_public) {
149 (*vars)["Method"] = method->name();
150 (*vars)["Request"] = method->input_type_name();
151 (*vars)["Response"] = method->output_type_name();
152
153 struct {
154 grpc::string prefix;
155 grpc::string method_params; // extra arguments to method
156 grpc::string raw_args; // extra arguments to raw version of method
James Kuszmaul8e62b022022-03-22 09:33:25 -0700157 } async_prefixes[] = { { "Async", ", void* tag", ", tag" },
158 { "PrepareAsync", "", "" } };
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700159
160 if (is_public) {
161 if (method->NoStreaming()) {
162 printer->Print(
163 *vars,
164 "virtual ::grpc::Status $Method$(::grpc::ClientContext* context, "
165 "const $Request$& request, $Response$* response) = 0;\n");
James Kuszmaul8e62b022022-03-22 09:33:25 -0700166 for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
167 i++) {
168 auto &async_prefix = async_prefixes[i];
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700169 (*vars)["AsyncPrefix"] = async_prefix.prefix;
170 printer->Print(
171 *vars,
172 "std::unique_ptr< "
173 "::grpc::ClientAsyncResponseReaderInterface< $Response$>> "
174 "$AsyncPrefix$$Method$(::grpc::ClientContext* context, "
175 "const $Request$& request, "
176 "::grpc::CompletionQueue* cq) {\n");
177 printer->Indent();
178 printer->Print(
179 *vars,
180 "return std::unique_ptr< "
181 "::grpc::ClientAsyncResponseReaderInterface< $Response$>>("
182 "$AsyncPrefix$$Method$Raw(context, request, cq));\n");
183 printer->Outdent();
184 printer->Print("}\n");
185 }
186 } else if (ClientOnlyStreaming(method)) {
187 printer->Print(
188 *vars,
189 "std::unique_ptr< ::grpc::ClientWriterInterface< $Request$>>"
190 " $Method$("
191 "::grpc::ClientContext* context, $Response$* response) {\n");
192 printer->Indent();
193 printer->Print(
194 *vars,
195 "return std::unique_ptr< ::grpc::ClientWriterInterface< $Request$>>"
196 "($Method$Raw(context, response));\n");
197 printer->Outdent();
198 printer->Print("}\n");
James Kuszmaul8e62b022022-03-22 09:33:25 -0700199 for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
200 i++) {
201 auto &async_prefix = async_prefixes[i];
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700202 (*vars)["AsyncPrefix"] = async_prefix.prefix;
203 (*vars)["AsyncMethodParams"] = async_prefix.method_params;
204 (*vars)["AsyncRawArgs"] = async_prefix.raw_args;
205 printer->Print(
206 *vars,
207 "std::unique_ptr< ::grpc::ClientAsyncWriterInterface< $Request$>>"
208 " $AsyncPrefix$$Method$(::grpc::ClientContext* context, "
209 "$Response$* "
210 "response, "
211 "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
212 printer->Indent();
213 printer->Print(*vars,
214 "return std::unique_ptr< "
215 "::grpc::ClientAsyncWriterInterface< $Request$>>("
216 "$AsyncPrefix$$Method$Raw(context, response, "
217 "cq$AsyncRawArgs$));\n");
218 printer->Outdent();
219 printer->Print("}\n");
220 }
221 } else if (ServerOnlyStreaming(method)) {
222 printer->Print(
223 *vars,
224 "std::unique_ptr< ::grpc::ClientReaderInterface< $Response$>>"
225 " $Method$(::grpc::ClientContext* context, const $Request$& request)"
226 " {\n");
227 printer->Indent();
228 printer->Print(
229 *vars,
230 "return std::unique_ptr< ::grpc::ClientReaderInterface< $Response$>>"
231 "($Method$Raw(context, request));\n");
232 printer->Outdent();
233 printer->Print("}\n");
James Kuszmaul8e62b022022-03-22 09:33:25 -0700234 for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
235 i++) {
236 auto &async_prefix = async_prefixes[i];
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700237 (*vars)["AsyncPrefix"] = async_prefix.prefix;
238 (*vars)["AsyncMethodParams"] = async_prefix.method_params;
239 (*vars)["AsyncRawArgs"] = async_prefix.raw_args;
240 printer->Print(
241 *vars,
242 "std::unique_ptr< ::grpc::ClientAsyncReaderInterface< $Response$>> "
243 "$AsyncPrefix$$Method$("
244 "::grpc::ClientContext* context, const $Request$& request, "
245 "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
246 printer->Indent();
247 printer->Print(
248 *vars,
249 "return std::unique_ptr< "
250 "::grpc::ClientAsyncReaderInterface< $Response$>>("
251 "$AsyncPrefix$$Method$Raw(context, request, cq$AsyncRawArgs$));\n");
252 printer->Outdent();
253 printer->Print("}\n");
254 }
255 } else if (method->BidiStreaming()) {
256 printer->Print(*vars,
257 "std::unique_ptr< ::grpc::ClientReaderWriterInterface< "
258 "$Request$, $Response$>> "
259 "$Method$(::grpc::ClientContext* context) {\n");
260 printer->Indent();
261 printer->Print(
262 *vars,
263 "return std::unique_ptr< "
264 "::grpc::ClientReaderWriterInterface< $Request$, $Response$>>("
265 "$Method$Raw(context));\n");
266 printer->Outdent();
267 printer->Print("}\n");
James Kuszmaul8e62b022022-03-22 09:33:25 -0700268 for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
269 i++) {
270 auto &async_prefix = async_prefixes[i];
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700271 (*vars)["AsyncPrefix"] = async_prefix.prefix;
272 (*vars)["AsyncMethodParams"] = async_prefix.method_params;
273 (*vars)["AsyncRawArgs"] = async_prefix.raw_args;
274 printer->Print(
275 *vars,
276 "std::unique_ptr< "
277 "::grpc::ClientAsyncReaderWriterInterface< $Request$, $Response$>> "
278 "$AsyncPrefix$$Method$(::grpc::ClientContext* context, "
279 "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
280 printer->Indent();
281 printer->Print(
282 *vars,
283 "return std::unique_ptr< "
284 "::grpc::ClientAsyncReaderWriterInterface< $Request$, $Response$>>("
285 "$AsyncPrefix$$Method$Raw(context, cq$AsyncRawArgs$));\n");
286 printer->Outdent();
287 printer->Print("}\n");
288 }
289 }
290 } else {
291 if (method->NoStreaming()) {
James Kuszmaul8e62b022022-03-22 09:33:25 -0700292 for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
293 i++) {
294 auto &async_prefix = async_prefixes[i];
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700295 (*vars)["AsyncPrefix"] = async_prefix.prefix;
296 printer->Print(
297 *vars,
298 "virtual ::grpc::ClientAsyncResponseReaderInterface< $Response$>* "
299 "$AsyncPrefix$$Method$Raw(::grpc::ClientContext* context, "
300 "const $Request$& request, "
301 "::grpc::CompletionQueue* cq) = 0;\n");
302 }
303 } else if (ClientOnlyStreaming(method)) {
304 printer->Print(
305 *vars,
306 "virtual ::grpc::ClientWriterInterface< $Request$>*"
307 " $Method$Raw("
308 "::grpc::ClientContext* context, $Response$* response) = 0;\n");
James Kuszmaul8e62b022022-03-22 09:33:25 -0700309 for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
310 i++) {
311 auto &async_prefix = async_prefixes[i];
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700312 (*vars)["AsyncPrefix"] = async_prefix.prefix;
313 (*vars)["AsyncMethodParams"] = async_prefix.method_params;
314 printer->Print(
315 *vars,
316 "virtual ::grpc::ClientAsyncWriterInterface< $Request$>*"
317 " $AsyncPrefix$$Method$Raw(::grpc::ClientContext* context, "
318 "$Response$* response, "
319 "::grpc::CompletionQueue* cq$AsyncMethodParams$) = 0;\n");
320 }
321 } else if (ServerOnlyStreaming(method)) {
322 printer->Print(
323 *vars,
324 "virtual ::grpc::ClientReaderInterface< $Response$>* "
325 "$Method$Raw("
326 "::grpc::ClientContext* context, const $Request$& request) = 0;\n");
James Kuszmaul8e62b022022-03-22 09:33:25 -0700327 for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
328 i++) {
329 auto &async_prefix = async_prefixes[i];
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700330 (*vars)["AsyncPrefix"] = async_prefix.prefix;
331 (*vars)["AsyncMethodParams"] = async_prefix.method_params;
332 printer->Print(
333 *vars,
334 "virtual ::grpc::ClientAsyncReaderInterface< $Response$>* "
335 "$AsyncPrefix$$Method$Raw("
336 "::grpc::ClientContext* context, const $Request$& request, "
337 "::grpc::CompletionQueue* cq$AsyncMethodParams$) = 0;\n");
338 }
339 } else if (method->BidiStreaming()) {
340 printer->Print(*vars,
341 "virtual ::grpc::ClientReaderWriterInterface< $Request$, "
342 "$Response$>* "
343 "$Method$Raw(::grpc::ClientContext* context) = 0;\n");
James Kuszmaul8e62b022022-03-22 09:33:25 -0700344 for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
345 i++) {
346 auto &async_prefix = async_prefixes[i];
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700347 (*vars)["AsyncPrefix"] = async_prefix.prefix;
348 (*vars)["AsyncMethodParams"] = async_prefix.method_params;
349 printer->Print(
350 *vars,
351 "virtual ::grpc::ClientAsyncReaderWriterInterface< "
352 "$Request$, $Response$>* "
353 "$AsyncPrefix$$Method$Raw(::grpc::ClientContext* context, "
354 "::grpc::CompletionQueue* cq$AsyncMethodParams$) = 0;\n");
355 }
356 }
357 }
358}
359
Austin Schuh2dd86a92022-09-14 21:19:23 -0700360
361
362static void PrintHeaderClientMethod(grpc_generator::Printer *printer,
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700363 const grpc_generator::Method *method,
364 std::map<grpc::string, grpc::string> *vars,
365 bool is_public) {
366 (*vars)["Method"] = method->name();
367 (*vars)["Request"] = method->input_type_name();
368 (*vars)["Response"] = method->output_type_name();
369 struct {
370 grpc::string prefix;
371 grpc::string method_params; // extra arguments to method
372 grpc::string raw_args; // extra arguments to raw version of method
James Kuszmaul8e62b022022-03-22 09:33:25 -0700373 } async_prefixes[] = { { "Async", ", void* tag", ", tag" },
374 { "PrepareAsync", "", "" } };
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700375
376 if (is_public) {
377 if (method->NoStreaming()) {
378 printer->Print(
379 *vars,
380 "::grpc::Status $Method$(::grpc::ClientContext* context, "
381 "const $Request$& request, $Response$* response) override;\n");
James Kuszmaul8e62b022022-03-22 09:33:25 -0700382 for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
383 i++) {
384 auto &async_prefix = async_prefixes[i];
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700385 (*vars)["AsyncPrefix"] = async_prefix.prefix;
386 printer->Print(
387 *vars,
388 "std::unique_ptr< ::grpc::ClientAsyncResponseReader< $Response$>> "
389 "$AsyncPrefix$$Method$(::grpc::ClientContext* context, "
390 "const $Request$& request, "
391 "::grpc::CompletionQueue* cq) {\n");
392 printer->Indent();
393 printer->Print(*vars,
394 "return std::unique_ptr< "
395 "::grpc::ClientAsyncResponseReader< $Response$>>("
396 "$AsyncPrefix$$Method$Raw(context, request, cq));\n");
397 printer->Outdent();
398 printer->Print("}\n");
399 }
400 } else if (ClientOnlyStreaming(method)) {
401 printer->Print(
402 *vars,
403 "std::unique_ptr< ::grpc::ClientWriter< $Request$>>"
404 " $Method$("
405 "::grpc::ClientContext* context, $Response$* response) {\n");
406 printer->Indent();
407 printer->Print(*vars,
408 "return std::unique_ptr< ::grpc::ClientWriter< $Request$>>"
409 "($Method$Raw(context, response));\n");
410 printer->Outdent();
411 printer->Print("}\n");
James Kuszmaul8e62b022022-03-22 09:33:25 -0700412 for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
413 i++) {
414 auto &async_prefix = async_prefixes[i];
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700415 (*vars)["AsyncPrefix"] = async_prefix.prefix;
416 (*vars)["AsyncMethodParams"] = async_prefix.method_params;
417 (*vars)["AsyncRawArgs"] = async_prefix.raw_args;
418 printer->Print(*vars,
419 "std::unique_ptr< ::grpc::ClientAsyncWriter< $Request$>>"
420 " $AsyncPrefix$$Method$(::grpc::ClientContext* context, "
421 "$Response$* response, "
422 "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
423 printer->Indent();
424 printer->Print(
425 *vars,
426 "return std::unique_ptr< ::grpc::ClientAsyncWriter< $Request$>>("
427 "$AsyncPrefix$$Method$Raw(context, response, "
428 "cq$AsyncRawArgs$));\n");
429 printer->Outdent();
430 printer->Print("}\n");
431 }
432 } else if (ServerOnlyStreaming(method)) {
433 printer->Print(
434 *vars,
435 "std::unique_ptr< ::grpc::ClientReader< $Response$>>"
436 " $Method$(::grpc::ClientContext* context, const $Request$& request)"
437 " {\n");
438 printer->Indent();
439 printer->Print(
440 *vars,
441 "return std::unique_ptr< ::grpc::ClientReader< $Response$>>"
442 "($Method$Raw(context, request));\n");
443 printer->Outdent();
444 printer->Print("}\n");
James Kuszmaul8e62b022022-03-22 09:33:25 -0700445 for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
446 i++) {
447 auto &async_prefix = async_prefixes[i];
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700448 (*vars)["AsyncPrefix"] = async_prefix.prefix;
449 (*vars)["AsyncMethodParams"] = async_prefix.method_params;
450 (*vars)["AsyncRawArgs"] = async_prefix.raw_args;
451 printer->Print(
452 *vars,
453 "std::unique_ptr< ::grpc::ClientAsyncReader< $Response$>> "
454 "$AsyncPrefix$$Method$("
455 "::grpc::ClientContext* context, const $Request$& request, "
456 "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
457 printer->Indent();
458 printer->Print(
459 *vars,
460 "return std::unique_ptr< ::grpc::ClientAsyncReader< $Response$>>("
461 "$AsyncPrefix$$Method$Raw(context, request, cq$AsyncRawArgs$));\n");
462 printer->Outdent();
463 printer->Print("}\n");
464 }
465 } else if (method->BidiStreaming()) {
466 printer->Print(
467 *vars,
468 "std::unique_ptr< ::grpc::ClientReaderWriter< $Request$, $Response$>>"
469 " $Method$(::grpc::ClientContext* context) {\n");
470 printer->Indent();
471 printer->Print(*vars,
472 "return std::unique_ptr< "
473 "::grpc::ClientReaderWriter< $Request$, $Response$>>("
474 "$Method$Raw(context));\n");
475 printer->Outdent();
476 printer->Print("}\n");
James Kuszmaul8e62b022022-03-22 09:33:25 -0700477 for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
478 i++) {
479 auto &async_prefix = async_prefixes[i];
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700480 (*vars)["AsyncPrefix"] = async_prefix.prefix;
481 (*vars)["AsyncMethodParams"] = async_prefix.method_params;
482 (*vars)["AsyncRawArgs"] = async_prefix.raw_args;
483 printer->Print(*vars,
484 "std::unique_ptr< ::grpc::ClientAsyncReaderWriter< "
485 "$Request$, $Response$>> "
486 "$AsyncPrefix$$Method$(::grpc::ClientContext* context, "
487 "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
488 printer->Indent();
489 printer->Print(
490 *vars,
491 "return std::unique_ptr< "
492 "::grpc::ClientAsyncReaderWriter< $Request$, $Response$>>("
493 "$AsyncPrefix$$Method$Raw(context, cq$AsyncRawArgs$));\n");
494 printer->Outdent();
495 printer->Print("}\n");
496 }
497 }
498 } else {
499 if (method->NoStreaming()) {
James Kuszmaul8e62b022022-03-22 09:33:25 -0700500 for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
501 i++) {
502 auto &async_prefix = async_prefixes[i];
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700503 (*vars)["AsyncPrefix"] = async_prefix.prefix;
504 printer->Print(
505 *vars,
506 "::grpc::ClientAsyncResponseReader< $Response$>* "
507 "$AsyncPrefix$$Method$Raw(::grpc::ClientContext* context, "
508 "const $Request$& request, "
509 "::grpc::CompletionQueue* cq) override;\n");
510 }
511 } else if (ClientOnlyStreaming(method)) {
512 printer->Print(*vars,
513 "::grpc::ClientWriter< $Request$>* $Method$Raw("
514 "::grpc::ClientContext* context, $Response$* response) "
515 "override;\n");
James Kuszmaul8e62b022022-03-22 09:33:25 -0700516 for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
517 i++) {
518 auto &async_prefix = async_prefixes[i];
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700519 (*vars)["AsyncPrefix"] = async_prefix.prefix;
520 (*vars)["AsyncMethodParams"] = async_prefix.method_params;
521 (*vars)["AsyncRawArgs"] = async_prefix.raw_args;
522 printer->Print(
523 *vars,
524 "::grpc::ClientAsyncWriter< $Request$>* $AsyncPrefix$$Method$Raw("
525 "::grpc::ClientContext* context, $Response$* response, "
526 "::grpc::CompletionQueue* cq$AsyncMethodParams$) override;\n");
527 }
528 } else if (ServerOnlyStreaming(method)) {
529 printer->Print(*vars,
530 "::grpc::ClientReader< $Response$>* $Method$Raw("
531 "::grpc::ClientContext* context, const $Request$& request)"
532 " override;\n");
James Kuszmaul8e62b022022-03-22 09:33:25 -0700533 for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
534 i++) {
535 auto &async_prefix = async_prefixes[i];
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700536 (*vars)["AsyncPrefix"] = async_prefix.prefix;
537 (*vars)["AsyncMethodParams"] = async_prefix.method_params;
538 (*vars)["AsyncRawArgs"] = async_prefix.raw_args;
539 printer->Print(
540 *vars,
541 "::grpc::ClientAsyncReader< $Response$>* $AsyncPrefix$$Method$Raw("
542 "::grpc::ClientContext* context, const $Request$& request, "
543 "::grpc::CompletionQueue* cq$AsyncMethodParams$) override;\n");
544 }
545 } else if (method->BidiStreaming()) {
546 printer->Print(*vars,
547 "::grpc::ClientReaderWriter< $Request$, $Response$>* "
548 "$Method$Raw(::grpc::ClientContext* context) override;\n");
James Kuszmaul8e62b022022-03-22 09:33:25 -0700549 for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
550 i++) {
551 auto &async_prefix = async_prefixes[i];
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700552 (*vars)["AsyncPrefix"] = async_prefix.prefix;
553 (*vars)["AsyncMethodParams"] = async_prefix.method_params;
554 (*vars)["AsyncRawArgs"] = async_prefix.raw_args;
555 printer->Print(
556 *vars,
557 "::grpc::ClientAsyncReaderWriter< $Request$, $Response$>* "
558 "$AsyncPrefix$$Method$Raw(::grpc::ClientContext* context, "
559 "::grpc::CompletionQueue* cq$AsyncMethodParams$) override;\n");
560 }
561 }
562 }
563}
564
Austin Schuh2dd86a92022-09-14 21:19:23 -0700565static void PrintHeaderClientMethodData(grpc_generator::Printer *printer,
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700566 const grpc_generator::Method *method,
567 std::map<grpc::string, grpc::string> *vars) {
568 (*vars)["Method"] = method->name();
569 printer->Print(*vars,
570 "const ::grpc::internal::RpcMethod rpcmethod_$Method$_;\n");
571}
572
Austin Schuh2dd86a92022-09-14 21:19:23 -0700573static void PrintHeaderServerMethodSync(grpc_generator::Printer *printer,
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700574 const grpc_generator::Method *method,
575 std::map<grpc::string, grpc::string> *vars) {
576 (*vars)["Method"] = method->name();
577 (*vars)["Request"] = method->input_type_name();
578 (*vars)["Response"] = method->output_type_name();
579 printer->Print(method->GetLeadingComments("//").c_str());
580 if (method->NoStreaming()) {
581 printer->Print(*vars,
582 "virtual ::grpc::Status $Method$("
583 "::grpc::ServerContext* context, const $Request$* request, "
584 "$Response$* response);\n");
585 } else if (ClientOnlyStreaming(method)) {
586 printer->Print(*vars,
587 "virtual ::grpc::Status $Method$("
588 "::grpc::ServerContext* context, "
589 "::grpc::ServerReader< $Request$>* reader, "
590 "$Response$* response);\n");
591 } else if (ServerOnlyStreaming(method)) {
592 printer->Print(*vars,
593 "virtual ::grpc::Status $Method$("
594 "::grpc::ServerContext* context, const $Request$* request, "
595 "::grpc::ServerWriter< $Response$>* writer);\n");
596 } else if (method->BidiStreaming()) {
597 printer->Print(
598 *vars,
599 "virtual ::grpc::Status $Method$("
600 "::grpc::ServerContext* context, "
601 "::grpc::ServerReaderWriter< $Response$, $Request$>* stream);"
602 "\n");
603 }
604 printer->Print(method->GetTrailingComments("//").c_str());
605}
606
Austin Schuh2dd86a92022-09-14 21:19:23 -0700607static void PrintHeaderServerMethodAsync(grpc_generator::Printer *printer,
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700608 const grpc_generator::Method *method,
609 std::map<grpc::string, grpc::string> *vars) {
610 (*vars)["Method"] = method->name();
611 (*vars)["Request"] = method->input_type_name();
612 (*vars)["Response"] = method->output_type_name();
613 printer->Print(*vars, "template <class BaseClass>\n");
614 printer->Print(*vars,
615 "class WithAsyncMethod_$Method$ : public BaseClass {\n");
616 printer->Print(
617 " private:\n"
James Kuszmaul8e62b022022-03-22 09:33:25 -0700618 " void BaseClassMustBeDerivedFromService(const Service */*service*/) "
619 "{}\n");
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700620 printer->Print(" public:\n");
621 printer->Indent();
622 printer->Print(*vars,
623 "WithAsyncMethod_$Method$() {\n"
624 " ::grpc::Service::MarkMethodAsync($Idx$);\n"
625 "}\n");
626 printer->Print(*vars,
627 "~WithAsyncMethod_$Method$() override {\n"
628 " BaseClassMustBeDerivedFromService(this);\n"
629 "}\n");
630 if (method->NoStreaming()) {
631 printer->Print(
632 *vars,
633 "// disable synchronous version of this method\n"
634 "::grpc::Status $Method$("
James Kuszmaul8e62b022022-03-22 09:33:25 -0700635 "::grpc::ServerContext* /*context*/, const $Request$* /*request*/, "
636 "$Response$* /*response*/) final override {\n"
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700637 " abort();\n"
638 " return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
639 "}\n");
640 printer->Print(
641 *vars,
642 "void Request$Method$("
643 "::grpc::ServerContext* context, $Request$* request, "
644 "::grpc::ServerAsyncResponseWriter< $Response$>* response, "
645 "::grpc::CompletionQueue* new_call_cq, "
646 "::grpc::ServerCompletionQueue* notification_cq, void *tag) {\n");
647 printer->Print(*vars,
648 " ::grpc::Service::RequestAsyncUnary($Idx$, context, "
649 "request, response, new_call_cq, notification_cq, tag);\n");
650 printer->Print("}\n");
651 } else if (ClientOnlyStreaming(method)) {
652 printer->Print(
653 *vars,
654 "// disable synchronous version of this method\n"
655 "::grpc::Status $Method$("
James Kuszmaul8e62b022022-03-22 09:33:25 -0700656 "::grpc::ServerContext* /*context*/, "
657 "::grpc::ServerReader< $Request$>* /*reader*/, "
Austin Schuh2dd86a92022-09-14 21:19:23 -0700658 "$Response$* /*response*/) final override {\n"
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700659 " abort();\n"
660 " return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
661 "}\n");
662 printer->Print(
663 *vars,
664 "void Request$Method$("
665 "::grpc::ServerContext* context, "
666 "::grpc::ServerAsyncReader< $Response$, $Request$>* reader, "
667 "::grpc::CompletionQueue* new_call_cq, "
668 "::grpc::ServerCompletionQueue* notification_cq, void *tag) {\n");
669 printer->Print(*vars,
670 " ::grpc::Service::RequestAsyncClientStreaming($Idx$, "
671 "context, reader, new_call_cq, notification_cq, tag);\n");
672 printer->Print("}\n");
673 } else if (ServerOnlyStreaming(method)) {
674 printer->Print(
675 *vars,
676 "// disable synchronous version of this method\n"
677 "::grpc::Status $Method$("
James Kuszmaul8e62b022022-03-22 09:33:25 -0700678 "::grpc::ServerContext* /*context*/, const $Request$* /*request*/, "
679 "::grpc::ServerWriter< $Response$>* /*writer*/) final override "
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700680 "{\n"
681 " abort();\n"
682 " return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
683 "}\n");
684 printer->Print(
685 *vars,
686 "void Request$Method$("
687 "::grpc::ServerContext* context, $Request$* request, "
688 "::grpc::ServerAsyncWriter< $Response$>* writer, "
689 "::grpc::CompletionQueue* new_call_cq, "
690 "::grpc::ServerCompletionQueue* notification_cq, void *tag) {\n");
691 printer->Print(
692 *vars,
693 " ::grpc::Service::RequestAsyncServerStreaming($Idx$, "
694 "context, request, writer, new_call_cq, notification_cq, tag);\n");
695 printer->Print("}\n");
696 } else if (method->BidiStreaming()) {
697 printer->Print(
698 *vars,
699 "// disable synchronous version of this method\n"
700 "::grpc::Status $Method$("
James Kuszmaul8e62b022022-03-22 09:33:25 -0700701 "::grpc::ServerContext* /*context*/, "
702 "::grpc::ServerReaderWriter< $Response$, $Request$>* /*stream*/) "
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700703 "final override {\n"
704 " abort();\n"
705 " return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
706 "}\n");
707 printer->Print(
708 *vars,
709 "void Request$Method$("
710 "::grpc::ServerContext* context, "
711 "::grpc::ServerAsyncReaderWriter< $Response$, $Request$>* stream, "
712 "::grpc::CompletionQueue* new_call_cq, "
713 "::grpc::ServerCompletionQueue* notification_cq, void *tag) {\n");
714 printer->Print(*vars,
715 " ::grpc::Service::RequestAsyncBidiStreaming($Idx$, "
716 "context, stream, new_call_cq, notification_cq, tag);\n");
717 printer->Print("}\n");
718 }
719 printer->Outdent();
720 printer->Print(*vars, "};\n");
721}
722
Austin Schuh2dd86a92022-09-14 21:19:23 -0700723static void PrintHeaderServerMethodStreamedUnary(
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700724 grpc_generator::Printer *printer, const grpc_generator::Method *method,
725 std::map<grpc::string, grpc::string> *vars) {
726 (*vars)["Method"] = method->name();
727 (*vars)["Request"] = method->input_type_name();
728 (*vars)["Response"] = method->output_type_name();
729 if (method->NoStreaming()) {
730 printer->Print(*vars, "template <class BaseClass>\n");
731 printer->Print(*vars,
732 "class WithStreamedUnaryMethod_$Method$ : "
733 "public BaseClass {\n");
734 printer->Print(
735 " private:\n"
James Kuszmaul8e62b022022-03-22 09:33:25 -0700736 " void BaseClassMustBeDerivedFromService(const Service */*service*/) "
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700737 "{}\n");
738 printer->Print(" public:\n");
739 printer->Indent();
740 printer->Print(*vars,
741 "WithStreamedUnaryMethod_$Method$() {\n"
742 " ::grpc::Service::MarkMethodStreamed($Idx$,\n"
743 " new ::grpc::internal::StreamedUnaryHandler< $Request$, "
744 "$Response$>(std::bind"
745 "(&WithStreamedUnaryMethod_$Method$<BaseClass>::"
746 "Streamed$Method$, this, std::placeholders::_1, "
747 "std::placeholders::_2)));\n"
748 "}\n");
749 printer->Print(*vars,
750 "~WithStreamedUnaryMethod_$Method$() override {\n"
751 " BaseClassMustBeDerivedFromService(this);\n"
752 "}\n");
753 printer->Print(
754 *vars,
755 "// disable regular version of this method\n"
756 "::grpc::Status $Method$("
James Kuszmaul8e62b022022-03-22 09:33:25 -0700757 "::grpc::ServerContext* /*context*/, const $Request$* /*request*/, "
758 "$Response$* /*response*/) final override {\n"
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700759 " abort();\n"
760 " return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
761 "}\n");
762 printer->Print(*vars,
763 "// replace default version of method with streamed unary\n"
764 "virtual ::grpc::Status Streamed$Method$("
765 "::grpc::ServerContext* context, "
766 "::grpc::ServerUnaryStreamer< "
767 "$Request$,$Response$>* server_unary_streamer)"
768 " = 0;\n");
769 printer->Outdent();
770 printer->Print(*vars, "};\n");
771 }
772}
773
Austin Schuh2dd86a92022-09-14 21:19:23 -0700774static void PrintHeaderServerMethodSplitStreaming(
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700775 grpc_generator::Printer *printer, const grpc_generator::Method *method,
776 std::map<grpc::string, grpc::string> *vars) {
777 (*vars)["Method"] = method->name();
778 (*vars)["Request"] = method->input_type_name();
779 (*vars)["Response"] = method->output_type_name();
780 if (ServerOnlyStreaming(method)) {
781 printer->Print(*vars, "template <class BaseClass>\n");
782 printer->Print(*vars,
783 "class WithSplitStreamingMethod_$Method$ : "
784 "public BaseClass {\n");
785 printer->Print(
786 " private:\n"
James Kuszmaul8e62b022022-03-22 09:33:25 -0700787 " void BaseClassMustBeDerivedFromService(const Service */*service*/) "
788 "{ }\n");
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700789 printer->Print(" public:\n");
790 printer->Indent();
791 printer->Print(
792 *vars,
793 "WithSplitStreamingMethod_$Method$() {\n"
794 " ::grpc::Service::MarkMethodStreamed($Idx$,\n"
795 " new ::grpc::internal::SplitServerStreamingHandler< $Request$, "
796 "$Response$>(std::bind"
797 "(&WithSplitStreamingMethod_$Method$<BaseClass>::"
798 "Streamed$Method$, this, std::placeholders::_1, "
799 "std::placeholders::_2)));\n"
800 "}\n");
801 printer->Print(*vars,
802 "~WithSplitStreamingMethod_$Method$() override {\n"
803 " BaseClassMustBeDerivedFromService(this);\n"
804 "}\n");
805 printer->Print(
806 *vars,
807 "// disable regular version of this method\n"
808 "::grpc::Status $Method$("
James Kuszmaul8e62b022022-03-22 09:33:25 -0700809 "::grpc::ServerContext* /*context*/, const $Request$* /*request*/, "
810 "::grpc::ServerWriter< $Response$>* /*writer*/) final override "
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700811 "{\n"
812 " abort();\n"
813 " return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
814 "}\n");
815 printer->Print(*vars,
816 "// replace default version of method with split streamed\n"
817 "virtual ::grpc::Status Streamed$Method$("
818 "::grpc::ServerContext* context, "
819 "::grpc::ServerSplitStreamer< "
820 "$Request$,$Response$>* server_split_streamer)"
821 " = 0;\n");
822 printer->Outdent();
823 printer->Print(*vars, "};\n");
824 }
825}
826
Austin Schuh2dd86a92022-09-14 21:19:23 -0700827static void PrintHeaderServerMethodGeneric(
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700828 grpc_generator::Printer *printer, const grpc_generator::Method *method,
829 std::map<grpc::string, grpc::string> *vars) {
830 (*vars)["Method"] = method->name();
831 (*vars)["Request"] = method->input_type_name();
832 (*vars)["Response"] = method->output_type_name();
833 printer->Print(*vars, "template <class BaseClass>\n");
834 printer->Print(*vars,
835 "class WithGenericMethod_$Method$ : public BaseClass {\n");
836 printer->Print(
837 " private:\n"
James Kuszmaul8e62b022022-03-22 09:33:25 -0700838 " void BaseClassMustBeDerivedFromService(const Service */*service*/) "
839 "{}\n");
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700840 printer->Print(" public:\n");
841 printer->Indent();
842 printer->Print(*vars,
843 "WithGenericMethod_$Method$() {\n"
844 " ::grpc::Service::MarkMethodGeneric($Idx$);\n"
845 "}\n");
846 printer->Print(*vars,
847 "~WithGenericMethod_$Method$() override {\n"
848 " BaseClassMustBeDerivedFromService(this);\n"
849 "}\n");
850 if (method->NoStreaming()) {
851 printer->Print(
852 *vars,
853 "// disable synchronous version of this method\n"
854 "::grpc::Status $Method$("
James Kuszmaul8e62b022022-03-22 09:33:25 -0700855 "::grpc::ServerContext* /*context*/, const $Request$* /*request*/, "
856 "$Response$* /*response*/) final override {\n"
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700857 " abort();\n"
858 " return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
859 "}\n");
860 } else if (ClientOnlyStreaming(method)) {
861 printer->Print(
862 *vars,
863 "// disable synchronous version of this method\n"
864 "::grpc::Status $Method$("
James Kuszmaul8e62b022022-03-22 09:33:25 -0700865 "::grpc::ServerContext* /*context*/, "
866 "::grpc::ServerReader< $Request$>* /*reader*/, "
867 "$Response$* /*response*/) final override {\n"
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700868 " abort();\n"
869 " return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
870 "}\n");
871 } else if (ServerOnlyStreaming(method)) {
872 printer->Print(
873 *vars,
874 "// disable synchronous version of this method\n"
875 "::grpc::Status $Method$("
James Kuszmaul8e62b022022-03-22 09:33:25 -0700876 "::grpc::ServerContext* /*context*/, const $Request$* /*request*/, "
877 "::grpc::ServerWriter< $Response$>* /*writer*/) final override "
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700878 "{\n"
879 " abort();\n"
880 " return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
881 "}\n");
882 } else if (method->BidiStreaming()) {
883 printer->Print(
884 *vars,
885 "// disable synchronous version of this method\n"
886 "::grpc::Status $Method$("
James Kuszmaul8e62b022022-03-22 09:33:25 -0700887 "::grpc::ServerContext* /*context*/, "
888 "::grpc::ServerReaderWriter< $Response$, $Request$>* /*stream*/) "
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700889 "final override {\n"
890 " abort();\n"
891 " return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
892 "}\n");
893 }
894 printer->Outdent();
895 printer->Print(*vars, "};\n");
896}
897
Austin Schuh2dd86a92022-09-14 21:19:23 -0700898static void PrintHeaderService(grpc_generator::Printer *printer,
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700899 const grpc_generator::Service *service,
900 std::map<grpc::string, grpc::string> *vars) {
901 (*vars)["Service"] = service->name();
902
903 printer->Print(service->GetLeadingComments("//").c_str());
904 printer->Print(*vars,
905 "class $Service$ final {\n"
906 " public:\n");
907 printer->Indent();
908
909 // Service metadata
910 printer->Print(*vars,
911 "static constexpr char const* service_full_name() {\n"
912 " return \"$Package$$Service$\";\n"
913 "}\n");
914
915 // Client side
916 printer->Print(
917 "class StubInterface {\n"
918 " public:\n");
919 printer->Indent();
920 printer->Print("virtual ~StubInterface() {}\n");
921 for (int i = 0; i < service->method_count(); ++i) {
922 printer->Print(service->method(i)->GetLeadingComments("//").c_str());
923 PrintHeaderClientMethodInterfaces(printer, service->method(i).get(), vars,
924 true);
925 printer->Print(service->method(i)->GetTrailingComments("//").c_str());
926 }
927 printer->Outdent();
928 printer->Print("private:\n");
929 printer->Indent();
930 for (int i = 0; i < service->method_count(); ++i) {
931 PrintHeaderClientMethodInterfaces(printer, service->method(i).get(), vars,
932 false);
933 }
934 printer->Outdent();
935 printer->Print("};\n");
936 printer->Print(
937 "class Stub final : public StubInterface"
938 " {\n public:\n");
939 printer->Indent();
940 printer->Print(
941 "Stub(const std::shared_ptr< ::grpc::ChannelInterface>& "
942 "channel);\n");
943 for (int i = 0; i < service->method_count(); ++i) {
944 PrintHeaderClientMethod(printer, service->method(i).get(), vars, true);
945 }
946 printer->Outdent();
947 printer->Print("\n private:\n");
948 printer->Indent();
949 printer->Print("std::shared_ptr< ::grpc::ChannelInterface> channel_;\n");
950 for (int i = 0; i < service->method_count(); ++i) {
951 PrintHeaderClientMethod(printer, service->method(i).get(), vars, false);
952 }
953 for (int i = 0; i < service->method_count(); ++i) {
954 PrintHeaderClientMethodData(printer, service->method(i).get(), vars);
955 }
956 printer->Outdent();
957 printer->Print("};\n");
958 printer->Print(
959 "static std::unique_ptr<Stub> NewStub(const std::shared_ptr< "
960 "::grpc::ChannelInterface>& channel, "
961 "const ::grpc::StubOptions& options = ::grpc::StubOptions());\n");
962
963 printer->Print("\n");
964
965 // Server side - base
966 printer->Print(
967 "class Service : public ::grpc::Service {\n"
968 " public:\n");
969 printer->Indent();
970 printer->Print("Service();\n");
971 printer->Print("virtual ~Service();\n");
972 for (int i = 0; i < service->method_count(); ++i) {
973 PrintHeaderServerMethodSync(printer, service->method(i).get(), vars);
974 }
975 printer->Outdent();
976 printer->Print("};\n");
977
978 // Server side - Asynchronous
979 for (int i = 0; i < service->method_count(); ++i) {
980 (*vars)["Idx"] = as_string(i);
981 PrintHeaderServerMethodAsync(printer, service->method(i).get(), vars);
982 }
983
984 printer->Print("typedef ");
985
986 for (int i = 0; i < service->method_count(); ++i) {
987 (*vars)["method_name"] = service->method(i).get()->name();
988 printer->Print(*vars, "WithAsyncMethod_$method_name$<");
989 }
990 printer->Print("Service");
James Kuszmaul8e62b022022-03-22 09:33:25 -0700991 for (int i = 0; i < service->method_count(); ++i) { printer->Print(" >"); }
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700992 printer->Print(" AsyncService;\n");
993
994 // Server side - Generic
995 for (int i = 0; i < service->method_count(); ++i) {
996 (*vars)["Idx"] = as_string(i);
997 PrintHeaderServerMethodGeneric(printer, service->method(i).get(), vars);
998 }
999
1000 // Server side - Streamed Unary
1001 for (int i = 0; i < service->method_count(); ++i) {
1002 (*vars)["Idx"] = as_string(i);
1003 PrintHeaderServerMethodStreamedUnary(printer, service->method(i).get(),
1004 vars);
1005 }
1006
1007 printer->Print("typedef ");
1008 for (int i = 0; i < service->method_count(); ++i) {
1009 (*vars)["method_name"] = service->method(i).get()->name();
1010 if (service->method(i)->NoStreaming()) {
1011 printer->Print(*vars, "WithStreamedUnaryMethod_$method_name$<");
1012 }
1013 }
1014 printer->Print("Service");
1015 for (int i = 0; i < service->method_count(); ++i) {
James Kuszmaul8e62b022022-03-22 09:33:25 -07001016 if (service->method(i)->NoStreaming()) { printer->Print(" >"); }
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001017 }
1018 printer->Print(" StreamedUnaryService;\n");
1019
1020 // Server side - controlled server-side streaming
1021 for (int i = 0; i < service->method_count(); ++i) {
1022 (*vars)["Idx"] = as_string(i);
1023 PrintHeaderServerMethodSplitStreaming(printer, service->method(i).get(),
1024 vars);
1025 }
1026
1027 printer->Print("typedef ");
1028 for (int i = 0; i < service->method_count(); ++i) {
1029 (*vars)["method_name"] = service->method(i).get()->name();
1030 auto method = service->method(i);
1031 if (ServerOnlyStreaming(method.get())) {
1032 printer->Print(*vars, "WithSplitStreamingMethod_$method_name$<");
1033 }
1034 }
1035 printer->Print("Service");
1036 for (int i = 0; i < service->method_count(); ++i) {
1037 auto method = service->method(i);
James Kuszmaul8e62b022022-03-22 09:33:25 -07001038 if (ServerOnlyStreaming(method.get())) { printer->Print(" >"); }
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001039 }
1040 printer->Print(" SplitStreamedService;\n");
1041
1042 // Server side - typedef for controlled both unary and server-side streaming
1043 printer->Print("typedef ");
1044 for (int i = 0; i < service->method_count(); ++i) {
1045 (*vars)["method_name"] = service->method(i).get()->name();
1046 auto method = service->method(i);
1047 if (ServerOnlyStreaming(method.get())) {
1048 printer->Print(*vars, "WithSplitStreamingMethod_$method_name$<");
1049 }
1050 if (service->method(i)->NoStreaming()) {
1051 printer->Print(*vars, "WithStreamedUnaryMethod_$method_name$<");
1052 }
1053 }
1054 printer->Print("Service");
1055 for (int i = 0; i < service->method_count(); ++i) {
1056 auto method = service->method(i);
1057 if (service->method(i)->NoStreaming() ||
1058 ServerOnlyStreaming(method.get())) {
1059 printer->Print(" >");
1060 }
1061 }
1062 printer->Print(" StreamedService;\n");
1063
1064 printer->Outdent();
1065 printer->Print("};\n");
1066 printer->Print(service->GetTrailingComments("//").c_str());
1067}
1068
Austin Schuh2dd86a92022-09-14 21:19:23 -07001069} // namespace
1070
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001071grpc::string GetHeaderServices(grpc_generator::File *file,
1072 const Parameters &params) {
1073 grpc::string output;
1074 {
1075 // Scope the output stream so it closes and finalizes output to the string.
1076 auto printer = file->CreatePrinter(&output);
1077 std::map<grpc::string, grpc::string> vars;
1078 // Package string is empty or ends with a dot. It is used to fully qualify
1079 // method names.
1080 vars["Package"] = file->package();
James Kuszmaul8e62b022022-03-22 09:33:25 -07001081 if (!file->package().empty()) { vars["Package"].append("."); }
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001082
1083 if (!params.services_namespace.empty()) {
1084 vars["services_namespace"] = params.services_namespace;
1085 printer->Print(vars, "\nnamespace $services_namespace$ {\n\n");
1086 }
1087
1088 for (int i = 0; i < file->service_count(); ++i) {
1089 PrintHeaderService(printer.get(), file->service(i).get(), &vars);
1090 printer->Print("\n");
1091 }
1092
1093 if (!params.services_namespace.empty()) {
1094 printer->Print(vars, "} // namespace $services_namespace$\n\n");
1095 }
1096 }
1097 return output;
1098}
1099
1100grpc::string GetHeaderEpilogue(grpc_generator::File *file,
1101 const Parameters & /*params*/) {
1102 grpc::string output;
1103 {
1104 // Scope the output stream so it closes and finalizes output to the string.
1105 auto printer = file->CreatePrinter(&output);
1106 std::map<grpc::string, grpc::string> vars;
1107
1108 vars["filename"] = file->filename();
1109 vars["filename_identifier"] = FilenameIdentifier(file->filename());
1110
1111 if (!file->package().empty()) {
1112 std::vector<grpc::string> parts = file->package_parts();
1113
1114 for (auto part = parts.rbegin(); part != parts.rend(); part++) {
1115 vars["part"] = *part;
1116 printer->Print(vars, "} // namespace $part$\n");
1117 }
1118 printer->Print(vars, "\n");
1119 }
1120
1121 printer->Print(vars, "\n");
1122 printer->Print(vars, "#endif // GRPC_$filename_identifier$__INCLUDED\n");
1123
1124 printer->Print(file->GetTrailingComments("//").c_str());
1125 }
1126 return output;
1127}
1128
1129grpc::string GetSourcePrologue(grpc_generator::File *file,
Austin Schuh2dd86a92022-09-14 21:19:23 -07001130 const Parameters &params) {
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001131 grpc::string output;
1132 {
1133 // Scope the output stream so it closes and finalizes output to the string.
1134 auto printer = file->CreatePrinter(&output);
1135 std::map<grpc::string, grpc::string> vars;
1136
1137 vars["filename"] = file->filename();
1138 vars["filename_base"] = file->filename_without_ext();
Austin Schuh2dd86a92022-09-14 21:19:23 -07001139 vars["message_header_ext"] = params.message_header_extension;
1140 vars["service_header_ext"] = service_header_ext();
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001141
1142 printer->Print(vars, "// Generated by the gRPC C++ plugin.\n");
1143 printer->Print(vars,
1144 "// If you make any local change, they will be lost.\n");
1145 printer->Print(vars, "// source: $filename$\n\n");
1146
1147 printer->Print(vars, "#include \"$filename_base$$message_header_ext$\"\n");
1148 printer->Print(vars, "#include \"$filename_base$$service_header_ext$\"\n");
1149 printer->Print(vars, "\n");
1150 }
1151 return output;
1152}
1153
1154grpc::string GetSourceIncludes(grpc_generator::File *file,
1155 const Parameters &params) {
1156 grpc::string output;
1157 {
1158 // Scope the output stream so it closes and finalizes output to the string.
1159 auto printer = file->CreatePrinter(&output);
1160 std::map<grpc::string, grpc::string> vars;
1161
1162 static const char *headers_strs[] = {
James Kuszmaul8e62b022022-03-22 09:33:25 -07001163 "grpcpp/impl/codegen/async_stream.h",
1164 "grpcpp/impl/codegen/async_unary_call.h",
1165 "grpcpp/impl/codegen/channel_interface.h",
1166 "grpcpp/impl/codegen/client_unary_call.h",
1167 "grpcpp/impl/codegen/method_handler.h",
1168 "grpcpp/impl/codegen/rpc_service_method.h",
1169 "grpcpp/impl/codegen/service_type.h",
1170 "grpcpp/impl/codegen/sync_stream.h"
1171 };
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001172 std::vector<grpc::string> headers(headers_strs, array_end(headers_strs));
1173 PrintIncludes(printer.get(), headers, params);
1174
1175 if (!file->package().empty()) {
1176 std::vector<grpc::string> parts = file->package_parts();
1177
1178 for (auto part = parts.begin(); part != parts.end(); part++) {
1179 vars["part"] = *part;
1180 printer->Print(vars, "namespace $part$ {\n");
1181 }
1182 }
1183
1184 printer->Print(vars, "\n");
1185 }
1186 return output;
1187}
1188
Austin Schuh2dd86a92022-09-14 21:19:23 -07001189
1190namespace {
1191
1192static void PrintSourceClientMethod(grpc_generator::Printer *printer,
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001193 const grpc_generator::Method *method,
1194 std::map<grpc::string, grpc::string> *vars) {
1195 (*vars)["Method"] = method->name();
1196 (*vars)["Request"] = method->input_type_name();
1197 (*vars)["Response"] = method->output_type_name();
1198 struct {
1199 grpc::string prefix;
1200 grpc::string start; // bool literal expressed as string
1201 grpc::string method_params; // extra arguments to method
1202 grpc::string create_args; // extra arguments to creator
James Kuszmaul8e62b022022-03-22 09:33:25 -07001203 } async_prefixes[] = { { "Async", "true", ", void* tag", ", tag" },
1204 { "PrepareAsync", "false", "", ", nullptr" } };
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001205 if (method->NoStreaming()) {
1206 printer->Print(*vars,
1207 "::grpc::Status $ns$$Service$::Stub::$Method$("
1208 "::grpc::ClientContext* context, "
1209 "const $Request$& request, $Response$* response) {\n");
1210 printer->Print(*vars,
1211 " return ::grpc::internal::BlockingUnaryCall"
1212 "(channel_.get(), rpcmethod_$Method$_, "
1213 "context, request, response);\n}\n\n");
James Kuszmaul8e62b022022-03-22 09:33:25 -07001214 for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
1215 i++) {
1216 auto &async_prefix = async_prefixes[i];
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001217 (*vars)["AsyncPrefix"] = async_prefix.prefix;
1218 (*vars)["AsyncStart"] = async_prefix.start;
1219 printer->Print(*vars,
1220 "::grpc::ClientAsyncResponseReader< $Response$>* "
1221 "$ns$$Service$::Stub::$AsyncPrefix$$Method$Raw(::grpc::"
1222 "ClientContext* context, "
1223 "const $Request$& request, "
1224 "::grpc::CompletionQueue* cq) {\n");
1225 printer->Print(
1226 *vars,
1227 " return "
1228 "::grpc::internal::ClientAsyncResponseReaderFactory< $Response$>"
1229 "::Create(channel_.get(), cq, "
1230 "rpcmethod_$Method$_, "
1231 "context, request, $AsyncStart$);\n"
1232 "}\n\n");
1233 }
1234 } else if (ClientOnlyStreaming(method)) {
1235 printer->Print(*vars,
1236 "::grpc::ClientWriter< $Request$>* "
1237 "$ns$$Service$::Stub::$Method$Raw("
1238 "::grpc::ClientContext* context, $Response$* response) {\n");
1239 printer->Print(
1240 *vars,
1241 " return ::grpc::internal::ClientWriterFactory< $Request$>::Create("
1242 "channel_.get(), "
1243 "rpcmethod_$Method$_, "
1244 "context, response);\n"
1245 "}\n\n");
James Kuszmaul8e62b022022-03-22 09:33:25 -07001246 for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
1247 i++) {
1248 auto &async_prefix = async_prefixes[i];
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001249 (*vars)["AsyncPrefix"] = async_prefix.prefix;
1250 (*vars)["AsyncStart"] = async_prefix.start;
1251 (*vars)["AsyncMethodParams"] = async_prefix.method_params;
1252 (*vars)["AsyncCreateArgs"] = async_prefix.create_args;
1253 printer->Print(*vars,
1254 "::grpc::ClientAsyncWriter< $Request$>* "
1255 "$ns$$Service$::Stub::$AsyncPrefix$$Method$Raw("
1256 "::grpc::ClientContext* context, $Response$* response, "
1257 "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
1258 printer->Print(
1259 *vars,
1260 " return ::grpc::internal::ClientAsyncWriterFactory< $Request$>"
1261 "::Create(channel_.get(), cq, "
1262 "rpcmethod_$Method$_, "
1263 "context, response, $AsyncStart$$AsyncCreateArgs$);\n"
1264 "}\n\n");
1265 }
1266 } else if (ServerOnlyStreaming(method)) {
1267 printer->Print(
1268 *vars,
1269 "::grpc::ClientReader< $Response$>* "
1270 "$ns$$Service$::Stub::$Method$Raw("
1271 "::grpc::ClientContext* context, const $Request$& request) {\n");
1272 printer->Print(
1273 *vars,
1274 " return ::grpc::internal::ClientReaderFactory< $Response$>::Create("
1275 "channel_.get(), "
1276 "rpcmethod_$Method$_, "
1277 "context, request);\n"
1278 "}\n\n");
James Kuszmaul8e62b022022-03-22 09:33:25 -07001279 for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
1280 i++) {
1281 auto &async_prefix = async_prefixes[i];
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001282 (*vars)["AsyncPrefix"] = async_prefix.prefix;
1283 (*vars)["AsyncStart"] = async_prefix.start;
1284 (*vars)["AsyncMethodParams"] = async_prefix.method_params;
1285 (*vars)["AsyncCreateArgs"] = async_prefix.create_args;
1286 printer->Print(
1287 *vars,
1288 "::grpc::ClientAsyncReader< $Response$>* "
1289 "$ns$$Service$::Stub::$AsyncPrefix$$Method$Raw("
1290 "::grpc::ClientContext* context, const $Request$& request, "
1291 "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
1292 printer->Print(
1293 *vars,
1294 " return ::grpc::internal::ClientAsyncReaderFactory< $Response$>"
1295 "::Create(channel_.get(), cq, "
1296 "rpcmethod_$Method$_, "
1297 "context, request, $AsyncStart$$AsyncCreateArgs$);\n"
1298 "}\n\n");
1299 }
1300 } else if (method->BidiStreaming()) {
1301 printer->Print(
1302 *vars,
1303 "::grpc::ClientReaderWriter< $Request$, $Response$>* "
1304 "$ns$$Service$::Stub::$Method$Raw(::grpc::ClientContext* context) {\n");
1305 printer->Print(*vars,
1306 " return ::grpc::internal::ClientReaderWriterFactory< "
1307 "$Request$, $Response$>::Create("
1308 "channel_.get(), "
1309 "rpcmethod_$Method$_, "
1310 "context);\n"
1311 "}\n\n");
James Kuszmaul8e62b022022-03-22 09:33:25 -07001312 for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
1313 i++) {
1314 auto &async_prefix = async_prefixes[i];
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001315 (*vars)["AsyncPrefix"] = async_prefix.prefix;
1316 (*vars)["AsyncStart"] = async_prefix.start;
1317 (*vars)["AsyncMethodParams"] = async_prefix.method_params;
1318 (*vars)["AsyncCreateArgs"] = async_prefix.create_args;
1319 printer->Print(*vars,
1320 "::grpc::ClientAsyncReaderWriter< $Request$, $Response$>* "
1321 "$ns$$Service$::Stub::$AsyncPrefix$$Method$Raw(::grpc::"
1322 "ClientContext* context, "
1323 "::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
1324 printer->Print(*vars,
1325 " return "
1326 "::grpc::internal::ClientAsyncReaderWriterFactory< "
1327 "$Request$, $Response$>::Create("
1328 "channel_.get(), cq, "
1329 "rpcmethod_$Method$_, "
1330 "context, $AsyncStart$$AsyncCreateArgs$);\n"
1331 "}\n\n");
1332 }
1333 }
1334}
1335
Austin Schuh2dd86a92022-09-14 21:19:23 -07001336static void PrintSourceServerMethod(grpc_generator::Printer *printer,
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001337 const grpc_generator::Method *method,
1338 std::map<grpc::string, grpc::string> *vars) {
1339 (*vars)["Method"] = method->name();
1340 (*vars)["Request"] = method->input_type_name();
1341 (*vars)["Response"] = method->output_type_name();
1342 if (method->NoStreaming()) {
James Kuszmaul8e62b022022-03-22 09:33:25 -07001343 printer->Print(
1344 *vars,
1345 "::grpc::Status $ns$$Service$::Service::$Method$("
1346 "::grpc::ServerContext* /*context*/, "
1347 "const $Request$* /*request*/, $Response$* /*response*/) {\n");
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001348 printer->Print(
1349 " return ::grpc::Status("
1350 "::grpc::StatusCode::UNIMPLEMENTED, \"\");\n");
1351 printer->Print("}\n\n");
1352 } else if (ClientOnlyStreaming(method)) {
1353 printer->Print(*vars,
1354 "::grpc::Status $ns$$Service$::Service::$Method$("
James Kuszmaul8e62b022022-03-22 09:33:25 -07001355 "::grpc::ServerContext* /*context*/, "
1356 "::grpc::ServerReader< $Request$>* /*reader*/, "
1357 "$Response$* /*response*/) {\n");
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001358 printer->Print(
1359 " return ::grpc::Status("
1360 "::grpc::StatusCode::UNIMPLEMENTED, \"\");\n");
1361 printer->Print("}\n\n");
1362 } else if (ServerOnlyStreaming(method)) {
1363 printer->Print(*vars,
1364 "::grpc::Status $ns$$Service$::Service::$Method$("
James Kuszmaul8e62b022022-03-22 09:33:25 -07001365 "::grpc::ServerContext* /*context*/, "
1366 "const $Request$* /*request*/, "
1367 "::grpc::ServerWriter< $Response$>* /*writer*/) {\n");
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001368 printer->Print(
1369 " return ::grpc::Status("
1370 "::grpc::StatusCode::UNIMPLEMENTED, \"\");\n");
1371 printer->Print("}\n\n");
1372 } else if (method->BidiStreaming()) {
1373 printer->Print(*vars,
1374 "::grpc::Status $ns$$Service$::Service::$Method$("
James Kuszmaul8e62b022022-03-22 09:33:25 -07001375 "::grpc::ServerContext* /*context*/, "
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001376 "::grpc::ServerReaderWriter< $Response$, $Request$>* "
James Kuszmaul8e62b022022-03-22 09:33:25 -07001377 "/*stream*/) {\n");
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001378 printer->Print(
1379 " return ::grpc::Status("
1380 "::grpc::StatusCode::UNIMPLEMENTED, \"\");\n");
1381 printer->Print("}\n\n");
1382 }
1383}
1384
Austin Schuh2dd86a92022-09-14 21:19:23 -07001385static void PrintSourceService(grpc_generator::Printer *printer,
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001386 const grpc_generator::Service *service,
1387 std::map<grpc::string, grpc::string> *vars) {
1388 (*vars)["Service"] = service->name();
1389
1390 if (service->method_count() > 0) {
1391 printer->Print(*vars,
1392 "static const char* $prefix$$Service$_method_names[] = {\n");
1393 for (int i = 0; i < service->method_count(); ++i) {
1394 (*vars)["Method"] = service->method(i).get()->name();
1395 printer->Print(*vars, " \"/$Package$$Service$/$Method$\",\n");
1396 }
1397 printer->Print(*vars, "};\n\n");
1398 }
1399
1400 printer->Print(*vars,
1401 "std::unique_ptr< $ns$$Service$::Stub> $ns$$Service$::NewStub("
1402 "const std::shared_ptr< ::grpc::ChannelInterface>& channel, "
James Kuszmaul8e62b022022-03-22 09:33:25 -07001403 "const ::grpc::StubOptions& /*options*/) {\n"
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001404 " std::unique_ptr< $ns$$Service$::Stub> stub(new "
1405 "$ns$$Service$::Stub(channel));\n"
1406 " return stub;\n"
1407 "}\n\n");
1408 printer->Print(*vars,
1409 "$ns$$Service$::Stub::Stub(const std::shared_ptr< "
1410 "::grpc::ChannelInterface>& channel)\n");
1411 printer->Indent();
1412 printer->Print(": channel_(channel)");
1413 for (int i = 0; i < service->method_count(); ++i) {
1414 auto method = service->method(i);
1415 (*vars)["Method"] = method->name();
1416 (*vars)["Idx"] = as_string(i);
1417 if (method->NoStreaming()) {
1418 (*vars)["StreamingType"] = "NORMAL_RPC";
1419 // NOTE: There is no reason to consider streamed-unary as a separate
1420 // category here since this part is setting up the client-side stub
1421 // and this appears as a NORMAL_RPC from the client-side.
1422 } else if (ClientOnlyStreaming(method.get())) {
1423 (*vars)["StreamingType"] = "CLIENT_STREAMING";
1424 } else if (ServerOnlyStreaming(method.get())) {
1425 (*vars)["StreamingType"] = "SERVER_STREAMING";
1426 } else {
1427 (*vars)["StreamingType"] = "BIDI_STREAMING";
1428 }
1429 printer->Print(*vars,
1430 ", rpcmethod_$Method$_("
1431 "$prefix$$Service$_method_names[$Idx$], "
1432 "::grpc::internal::RpcMethod::$StreamingType$, "
1433 "channel"
1434 ")\n");
1435 }
1436 printer->Print("{}\n\n");
1437 printer->Outdent();
1438
1439 for (int i = 0; i < service->method_count(); ++i) {
1440 (*vars)["Idx"] = as_string(i);
1441 PrintSourceClientMethod(printer, service->method(i).get(), vars);
1442 }
1443
1444 printer->Print(*vars, "$ns$$Service$::Service::Service() {\n");
1445 printer->Indent();
1446 for (int i = 0; i < service->method_count(); ++i) {
1447 auto method = service->method(i);
1448 (*vars)["Idx"] = as_string(i);
1449 (*vars)["Method"] = method->name();
1450 (*vars)["Request"] = method->input_type_name();
1451 (*vars)["Response"] = method->output_type_name();
1452 if (method->NoStreaming()) {
1453 printer->Print(
1454 *vars,
1455 "AddMethod(new ::grpc::internal::RpcServiceMethod(\n"
1456 " $prefix$$Service$_method_names[$Idx$],\n"
1457 " ::grpc::internal::RpcMethod::NORMAL_RPC,\n"
1458 " new ::grpc::internal::RpcMethodHandler< $ns$$Service$::Service, "
1459 "$Request$, "
1460 "$Response$>(\n"
1461 " std::mem_fn(&$ns$$Service$::Service::$Method$), this)));\n");
1462 } else if (ClientOnlyStreaming(method.get())) {
1463 printer->Print(
1464 *vars,
1465 "AddMethod(new ::grpc::internal::RpcServiceMethod(\n"
1466 " $prefix$$Service$_method_names[$Idx$],\n"
1467 " ::grpc::internal::RpcMethod::CLIENT_STREAMING,\n"
1468 " new ::grpc::internal::ClientStreamingHandler< "
1469 "$ns$$Service$::Service, $Request$, $Response$>(\n"
1470 " std::mem_fn(&$ns$$Service$::Service::$Method$), this)));\n");
1471 } else if (ServerOnlyStreaming(method.get())) {
1472 printer->Print(
1473 *vars,
1474 "AddMethod(new ::grpc::internal::RpcServiceMethod(\n"
1475 " $prefix$$Service$_method_names[$Idx$],\n"
1476 " ::grpc::internal::RpcMethod::SERVER_STREAMING,\n"
1477 " new ::grpc::internal::ServerStreamingHandler< "
1478 "$ns$$Service$::Service, $Request$, $Response$>(\n"
1479 " std::mem_fn(&$ns$$Service$::Service::$Method$), this)));\n");
1480 } else if (method->BidiStreaming()) {
1481 printer->Print(
1482 *vars,
1483 "AddMethod(new ::grpc::internal::RpcServiceMethod(\n"
1484 " $prefix$$Service$_method_names[$Idx$],\n"
1485 " ::grpc::internal::RpcMethod::BIDI_STREAMING,\n"
1486 " new ::grpc::internal::BidiStreamingHandler< "
1487 "$ns$$Service$::Service, $Request$, $Response$>(\n"
1488 " std::mem_fn(&$ns$$Service$::Service::$Method$), this)));\n");
1489 }
1490 }
1491 printer->Outdent();
1492 printer->Print(*vars, "}\n\n");
1493 printer->Print(*vars,
1494 "$ns$$Service$::Service::~Service() {\n"
1495 "}\n\n");
1496 for (int i = 0; i < service->method_count(); ++i) {
1497 (*vars)["Idx"] = as_string(i);
1498 PrintSourceServerMethod(printer, service->method(i).get(), vars);
1499 }
1500}
1501
Austin Schuh2dd86a92022-09-14 21:19:23 -07001502} // namespace
1503
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001504grpc::string GetSourceServices(grpc_generator::File *file,
1505 const Parameters &params) {
1506 grpc::string output;
1507 {
1508 // Scope the output stream so it closes and finalizes output to the string.
1509 auto printer = file->CreatePrinter(&output);
1510 std::map<grpc::string, grpc::string> vars;
1511 // Package string is empty or ends with a dot. It is used to fully qualify
1512 // method names.
1513 vars["Package"] = file->package();
James Kuszmaul8e62b022022-03-22 09:33:25 -07001514 if (!file->package().empty()) { vars["Package"].append("."); }
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001515 if (!params.services_namespace.empty()) {
1516 vars["ns"] = params.services_namespace + "::";
1517 vars["prefix"] = params.services_namespace;
1518 } else {
1519 vars["ns"] = "";
1520 vars["prefix"] = "";
1521 }
1522
1523 for (int i = 0; i < file->service_count(); ++i) {
1524 PrintSourceService(printer.get(), file->service(i).get(), &vars);
1525 printer->Print("\n");
1526 }
1527 }
1528 return output;
1529}
1530
1531grpc::string GetSourceEpilogue(grpc_generator::File *file,
1532 const Parameters & /*params*/) {
1533 grpc::string temp;
1534
1535 if (!file->package().empty()) {
1536 std::vector<grpc::string> parts = file->package_parts();
1537
1538 for (auto part = parts.begin(); part != parts.end(); part++) {
1539 temp.append("} // namespace ");
1540 temp.append(*part);
1541 temp.append("\n");
1542 }
1543 temp.append("\n");
1544 }
1545
1546 return temp;
1547}
1548
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001549grpc::string GetMockPrologue(grpc_generator::File *file,
Austin Schuh2dd86a92022-09-14 21:19:23 -07001550 const Parameters &params) {
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001551 grpc::string output;
1552 {
1553 // Scope the output stream so it closes and finalizes output to the string.
1554 auto printer = file->CreatePrinter(&output);
1555 std::map<grpc::string, grpc::string> vars;
1556
1557 vars["filename"] = file->filename();
1558 vars["filename_base"] = file->filename_without_ext();
Austin Schuh2dd86a92022-09-14 21:19:23 -07001559 vars["message_header_ext"] = params.message_header_extension;
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001560 vars["service_header_ext"] = service_header_ext();
1561
1562 printer->Print(vars, "// Generated by the gRPC C++ plugin.\n");
1563 printer->Print(vars,
1564 "// If you make any local change, they will be lost.\n");
1565 printer->Print(vars, "// source: $filename$\n\n");
1566
1567 printer->Print(vars, "#include \"$filename_base$$message_header_ext$\"\n");
1568 printer->Print(vars, "#include \"$filename_base$$service_header_ext$\"\n");
1569 printer->Print(vars, file->additional_headers().c_str());
1570 printer->Print(vars, "\n");
1571 }
1572 return output;
1573}
1574
1575// TODO(mmukhi): Add client-stream and completion-queue headers.
1576grpc::string GetMockIncludes(grpc_generator::File *file,
1577 const Parameters &params) {
1578 grpc::string output;
1579 {
1580 // Scope the output stream so it closes and finalizes output to the string.
1581 auto printer = file->CreatePrinter(&output);
1582 std::map<grpc::string, grpc::string> vars;
1583
1584 static const char *headers_strs[] = {
James Kuszmaul8e62b022022-03-22 09:33:25 -07001585 "grpcpp/impl/codegen/async_stream.h",
1586 "grpcpp/impl/codegen/sync_stream.h",
1587 "gmock/gmock.h",
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001588 };
1589 std::vector<grpc::string> headers(headers_strs, array_end(headers_strs));
1590 PrintIncludes(printer.get(), headers, params);
1591
1592 if (!file->package().empty()) {
1593 std::vector<grpc::string> parts = file->package_parts();
1594
1595 for (auto part = parts.begin(); part != parts.end(); part++) {
1596 vars["part"] = *part;
1597 printer->Print(vars, "namespace $part$ {\n");
1598 }
1599 }
1600
1601 printer->Print(vars, "\n");
1602 }
1603 return output;
1604}
1605
Austin Schuh2dd86a92022-09-14 21:19:23 -07001606
1607namespace {
1608
1609static void PrintMockClientMethods(grpc_generator::Printer *printer,
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001610 const grpc_generator::Method *method,
1611 std::map<grpc::string, grpc::string> *vars) {
1612 (*vars)["Method"] = method->name();
1613 (*vars)["Request"] = method->input_type_name();
1614 (*vars)["Response"] = method->output_type_name();
1615
1616 struct {
1617 grpc::string prefix;
1618 grpc::string method_params; // extra arguments to method
1619 int extra_method_param_count;
James Kuszmaul8e62b022022-03-22 09:33:25 -07001620 } async_prefixes[] = { { "Async", ", void* tag", 1 },
1621 { "PrepareAsync", "", 0 } };
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001622
1623 if (method->NoStreaming()) {
1624 printer->Print(
1625 *vars,
1626 "MOCK_METHOD3($Method$, ::grpc::Status(::grpc::ClientContext* context, "
1627 "const $Request$& request, $Response$* response));\n");
James Kuszmaul8e62b022022-03-22 09:33:25 -07001628 for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
1629 i++) {
1630 auto &async_prefix = async_prefixes[i];
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001631 (*vars)["AsyncPrefix"] = async_prefix.prefix;
1632 printer->Print(
1633 *vars,
1634 "MOCK_METHOD3($AsyncPrefix$$Method$Raw, "
1635 "::grpc::ClientAsyncResponseReaderInterface< $Response$>*"
1636 "(::grpc::ClientContext* context, const $Request$& request, "
1637 "::grpc::CompletionQueue* cq));\n");
1638 }
1639 } else if (ClientOnlyStreaming(method)) {
1640 printer->Print(
1641 *vars,
1642 "MOCK_METHOD2($Method$Raw, "
1643 "::grpc::ClientWriterInterface< $Request$>*"
1644 "(::grpc::ClientContext* context, $Response$* response));\n");
James Kuszmaul8e62b022022-03-22 09:33:25 -07001645 for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
1646 i++) {
1647 auto &async_prefix = async_prefixes[i];
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001648 (*vars)["AsyncPrefix"] = async_prefix.prefix;
1649 (*vars)["AsyncMethodParams"] = async_prefix.method_params;
1650 (*vars)["MockArgs"] =
James Kuszmaul8e62b022022-03-22 09:33:25 -07001651 flatbuffers::NumToString(3 + async_prefix.extra_method_param_count);
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001652 printer->Print(*vars,
1653 "MOCK_METHOD$MockArgs$($AsyncPrefix$$Method$Raw, "
1654 "::grpc::ClientAsyncWriterInterface< $Request$>*"
1655 "(::grpc::ClientContext* context, $Response$* response, "
1656 "::grpc::CompletionQueue* cq$AsyncMethodParams$));\n");
1657 }
1658 } else if (ServerOnlyStreaming(method)) {
1659 printer->Print(
1660 *vars,
1661 "MOCK_METHOD2($Method$Raw, "
1662 "::grpc::ClientReaderInterface< $Response$>*"
1663 "(::grpc::ClientContext* context, const $Request$& request));\n");
James Kuszmaul8e62b022022-03-22 09:33:25 -07001664 for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
1665 i++) {
1666 auto &async_prefix = async_prefixes[i];
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001667 (*vars)["AsyncPrefix"] = async_prefix.prefix;
1668 (*vars)["AsyncMethodParams"] = async_prefix.method_params;
1669 (*vars)["MockArgs"] =
1670 flatbuffers::NumToString(3 + async_prefix.extra_method_param_count);
1671 printer->Print(
1672 *vars,
1673 "MOCK_METHOD$MockArgs$($AsyncPrefix$$Method$Raw, "
1674 "::grpc::ClientAsyncReaderInterface< $Response$>*"
1675 "(::grpc::ClientContext* context, const $Request$& request, "
1676 "::grpc::CompletionQueue* cq$AsyncMethodParams$));\n");
1677 }
1678 } else if (method->BidiStreaming()) {
1679 printer->Print(
1680 *vars,
1681 "MOCK_METHOD1($Method$Raw, "
1682 "::grpc::ClientReaderWriterInterface< $Request$, $Response$>*"
1683 "(::grpc::ClientContext* context));\n");
James Kuszmaul8e62b022022-03-22 09:33:25 -07001684 for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
1685 i++) {
1686 auto &async_prefix = async_prefixes[i];
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001687 (*vars)["AsyncPrefix"] = async_prefix.prefix;
1688 (*vars)["AsyncMethodParams"] = async_prefix.method_params;
1689 (*vars)["MockArgs"] =
1690 flatbuffers::NumToString(2 + async_prefix.extra_method_param_count);
1691 printer->Print(
1692 *vars,
1693 "MOCK_METHOD$MockArgs$($AsyncPrefix$$Method$Raw, "
1694 "::grpc::ClientAsyncReaderWriterInterface<$Request$, $Response$>*"
1695 "(::grpc::ClientContext* context, ::grpc::CompletionQueue* cq"
1696 "$AsyncMethodParams$));\n");
1697 }
1698 }
1699}
1700
Austin Schuh2dd86a92022-09-14 21:19:23 -07001701static void PrintMockService(grpc_generator::Printer *printer,
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001702 const grpc_generator::Service *service,
1703 std::map<grpc::string, grpc::string> *vars) {
1704 (*vars)["Service"] = service->name();
1705
1706 printer->Print(*vars,
1707 "class Mock$Service$Stub : public $Service$::StubInterface {\n"
1708 " public:\n");
1709 printer->Indent();
1710 for (int i = 0; i < service->method_count(); ++i) {
1711 PrintMockClientMethods(printer, service->method(i).get(), vars);
1712 }
1713 printer->Outdent();
1714 printer->Print("};\n");
1715}
1716
Austin Schuh2dd86a92022-09-14 21:19:23 -07001717} // namespace
1718
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001719grpc::string GetMockServices(grpc_generator::File *file,
1720 const Parameters &params) {
1721 grpc::string output;
1722 {
1723 // Scope the output stream so it closes and finalizes output to the string.
1724 auto printer = file->CreatePrinter(&output);
1725 std::map<grpc::string, grpc::string> vars;
1726 // Package string is empty or ends with a dot. It is used to fully qualify
1727 // method names.
1728 vars["Package"] = file->package();
James Kuszmaul8e62b022022-03-22 09:33:25 -07001729 if (!file->package().empty()) { vars["Package"].append("."); }
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001730
1731 if (!params.services_namespace.empty()) {
1732 vars["services_namespace"] = params.services_namespace;
1733 printer->Print(vars, "\nnamespace $services_namespace$ {\n\n");
1734 }
1735
1736 for (int i = 0; i < file->service_count(); i++) {
1737 PrintMockService(printer.get(), file->service(i).get(), &vars);
1738 printer->Print("\n");
1739 }
1740
1741 if (!params.services_namespace.empty()) {
1742 printer->Print(vars, "} // namespace $services_namespace$\n\n");
1743 }
1744 }
1745 return output;
1746}
1747
1748grpc::string GetMockEpilogue(grpc_generator::File *file,
1749 const Parameters & /*params*/) {
1750 grpc::string temp;
1751
1752 if (!file->package().empty()) {
1753 std::vector<grpc::string> parts = file->package_parts();
1754
1755 for (auto part = parts.begin(); part != parts.end(); part++) {
1756 temp.append("} // namespace ");
1757 temp.append(*part);
1758 temp.append("\n");
1759 }
1760 temp.append("\n");
1761 }
1762
1763 return temp;
1764}
1765
1766} // namespace grpc_cpp_generator