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