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 message_header_ext() { return "_generated.h"; } 45 grpc::string service_header_ext() { 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> &headers, 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 GetHeaderPrologue(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 leading_comments = 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 GetHeaderIncludes(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 *headers_strs[] = { 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(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 PrintHeaderClientMethodInterfaces( 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 PrintHeaderClientMethod(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 PrintHeaderClientMethodData(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 PrintHeaderServerMethodSync(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 PrintHeaderServerMethodAsync(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 PrintHeaderServerMethodStreamedUnary( 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 PrintHeaderServerMethodSplitStreaming( 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 PrintHeaderServerMethodGeneric( 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 PrintHeaderService(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 GetHeaderServices(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 GetHeaderEpilogue(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 *headers_strs[] = { 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(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 *headers_strs[] = { 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(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 extra_method_param_count; 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