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