mirror of
https://github.com/google/flatbuffers.git
synced 2026-06-10 23:17:27 +00:00
* grpc/compiler: Respect filename suffix and extension during code generation grpc compiler is not respecting filename suffix and extension passed to flatc CLI. This causes compiler to spit out incorrect code, which then cannot be compiled without modification. Following patch fixes the problem. Note, I ended up removing some code introduced #6954 ("Have grpc include file with correct filename-suffix given to flatc") in favour of keeping sanity of the generator code. Signed-off-by: Aman Priyadarshi <aman.eureka@gmail.com> * tests: Add filename-suffix and filename-ext test files * Test 1: Filename extension changed to "hpp". * Test 2: Filename suffix changed to "_suffix". * Test 3: Filename extension changed to "hpp" and suffix changed to "_suffix" Signed-off-by: Aman Priyadarshi <aman.eureka@gmail.com>
1747 lines
69 KiB
C++
1747 lines
69 KiB
C++
#include "src/compiler/cpp_generator.h"
|
|
|
|
#include <map>
|
|
#include <sstream>
|
|
|
|
#include "flatbuffers/util.h"
|
|
|
|
namespace grpc_cpp_generator {
|
|
namespace {
|
|
|
|
grpc::string service_header_ext() { return ".grpc.fb.h"; }
|
|
|
|
template<class T> grpc::string as_string(T x) {
|
|
std::ostringstream out;
|
|
out << x;
|
|
return out.str();
|
|
}
|
|
|
|
inline bool ClientOnlyStreaming(const grpc_generator::Method *method) {
|
|
return method->ClientStreaming() && !method->ServerStreaming();
|
|
}
|
|
|
|
inline bool ServerOnlyStreaming(const grpc_generator::Method *method) {
|
|
return !method->ClientStreaming() && method->ServerStreaming();
|
|
}
|
|
|
|
grpc::string FilenameIdentifier(const grpc::string &filename) {
|
|
grpc::string result;
|
|
for (unsigned i = 0; i < filename.size(); i++) {
|
|
char c = filename[i];
|
|
if (isalnum(c)) {
|
|
result.push_back(c);
|
|
} else {
|
|
static char hex[] = "0123456789abcdef";
|
|
result.push_back('_');
|
|
result.push_back(hex[(c >> 4) & 0xf]);
|
|
result.push_back(hex[c & 0xf]);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
} // namespace
|
|
|
|
template<class T, size_t N> T *array_end(T (&array)[N]) { return array + N; }
|
|
|
|
void PrintIncludes(grpc_generator::Printer *printer,
|
|
const std::vector<grpc::string> &headers,
|
|
const Parameters ¶ms) {
|
|
std::map<grpc::string, grpc::string> vars;
|
|
|
|
vars["l"] = params.use_system_headers ? '<' : '"';
|
|
vars["r"] = params.use_system_headers ? '>' : '"';
|
|
|
|
auto &s = params.grpc_search_path;
|
|
if (!s.empty()) {
|
|
vars["l"] += s;
|
|
if (s[s.size() - 1] != '/') { vars["l"] += '/'; }
|
|
}
|
|
|
|
for (auto i = headers.begin(); i != headers.end(); i++) {
|
|
vars["h"] = *i;
|
|
printer->Print(vars, "#include $l$$h$$r$\n");
|
|
}
|
|
}
|
|
|
|
grpc::string GetHeaderPrologue(grpc_generator::File *file,
|
|
const Parameters ¶ms) {
|
|
grpc::string output;
|
|
{
|
|
// Scope the output stream so it closes and finalizes output to the string.
|
|
auto printer = file->CreatePrinter(&output);
|
|
std::map<grpc::string, grpc::string> vars;
|
|
|
|
vars["filename"] = file->filename();
|
|
vars["filename_identifier"] = FilenameIdentifier(file->filename());
|
|
vars["filename_base"] = file->filename_without_ext();
|
|
vars["message_header_ext"] = params.message_header_extension;
|
|
|
|
printer->Print(vars, "// Generated by the gRPC C++ plugin.\n");
|
|
printer->Print(vars,
|
|
"// If you make any local change, they will be lost.\n");
|
|
printer->Print(vars, "// source: $filename$\n");
|
|
grpc::string leading_comments = file->GetLeadingComments("//");
|
|
if (!leading_comments.empty()) {
|
|
printer->Print(vars, "// Original file comments:\n");
|
|
printer->Print(leading_comments.c_str());
|
|
}
|
|
printer->Print(vars, "#ifndef GRPC_$filename_identifier$__INCLUDED\n");
|
|
printer->Print(vars, "#define GRPC_$filename_identifier$__INCLUDED\n");
|
|
printer->Print(vars, "\n");
|
|
printer->Print(vars, "#include \"$filename_base$$message_header_ext$\"\n");
|
|
printer->Print(vars, file->additional_headers().c_str());
|
|
printer->Print(vars, "\n");
|
|
}
|
|
return output;
|
|
}
|
|
|
|
grpc::string GetHeaderIncludes(grpc_generator::File *file,
|
|
const Parameters ¶ms) {
|
|
grpc::string output;
|
|
{
|
|
// Scope the output stream so it closes and finalizes output to the string.
|
|
auto printer = file->CreatePrinter(&output);
|
|
std::map<grpc::string, grpc::string> vars;
|
|
|
|
static const char *headers_strs[] = {
|
|
"grpcpp/impl/codegen/async_stream.h",
|
|
"grpcpp/impl/codegen/async_unary_call.h",
|
|
"grpcpp/impl/codegen/method_handler.h",
|
|
"grpcpp/impl/codegen/proto_utils.h",
|
|
"grpcpp/impl/codegen/rpc_method.h",
|
|
"grpcpp/impl/codegen/service_type.h",
|
|
"grpcpp/impl/codegen/status.h",
|
|
"grpcpp/impl/codegen/stub_options.h",
|
|
"grpcpp/impl/codegen/sync_stream.h"
|
|
};
|
|
std::vector<grpc::string> headers(headers_strs, array_end(headers_strs));
|
|
PrintIncludes(printer.get(), headers, params);
|
|
printer->Print(vars, "\n");
|
|
printer->Print(vars, "namespace grpc {\n");
|
|
printer->Print(vars, "class CompletionQueue;\n");
|
|
printer->Print(vars, "class Channel;\n");
|
|
printer->Print(vars, "class ServerCompletionQueue;\n");
|
|
printer->Print(vars, "class ServerContext;\n");
|
|
printer->Print(vars, "} // namespace grpc\n\n");
|
|
|
|
if (!file->package().empty()) {
|
|
std::vector<grpc::string> parts = file->package_parts();
|
|
|
|
for (auto part = parts.begin(); part != parts.end(); part++) {
|
|
vars["part"] = *part;
|
|
printer->Print(vars, "namespace $part$ {\n");
|
|
}
|
|
printer->Print(vars, "\n");
|
|
}
|
|
}
|
|
return output;
|
|
}
|
|
|
|
void PrintHeaderClientMethodInterfaces(
|
|
grpc_generator::Printer *printer, const grpc_generator::Method *method,
|
|
std::map<grpc::string, grpc::string> *vars, bool is_public) {
|
|
(*vars)["Method"] = method->name();
|
|
(*vars)["Request"] = method->input_type_name();
|
|
(*vars)["Response"] = method->output_type_name();
|
|
|
|
struct {
|
|
grpc::string prefix;
|
|
grpc::string method_params; // extra arguments to method
|
|
grpc::string raw_args; // extra arguments to raw version of method
|
|
} async_prefixes[] = { { "Async", ", void* tag", ", tag" },
|
|
{ "PrepareAsync", "", "" } };
|
|
|
|
if (is_public) {
|
|
if (method->NoStreaming()) {
|
|
printer->Print(
|
|
*vars,
|
|
"virtual ::grpc::Status $Method$(::grpc::ClientContext* context, "
|
|
"const $Request$& request, $Response$* response) = 0;\n");
|
|
for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
|
|
i++) {
|
|
auto &async_prefix = async_prefixes[i];
|
|
(*vars)["AsyncPrefix"] = async_prefix.prefix;
|
|
printer->Print(
|
|
*vars,
|
|
"std::unique_ptr< "
|
|
"::grpc::ClientAsyncResponseReaderInterface< $Response$>> "
|
|
"$AsyncPrefix$$Method$(::grpc::ClientContext* context, "
|
|
"const $Request$& request, "
|
|
"::grpc::CompletionQueue* cq) {\n");
|
|
printer->Indent();
|
|
printer->Print(
|
|
*vars,
|
|
"return std::unique_ptr< "
|
|
"::grpc::ClientAsyncResponseReaderInterface< $Response$>>("
|
|
"$AsyncPrefix$$Method$Raw(context, request, cq));\n");
|
|
printer->Outdent();
|
|
printer->Print("}\n");
|
|
}
|
|
} else if (ClientOnlyStreaming(method)) {
|
|
printer->Print(
|
|
*vars,
|
|
"std::unique_ptr< ::grpc::ClientWriterInterface< $Request$>>"
|
|
" $Method$("
|
|
"::grpc::ClientContext* context, $Response$* response) {\n");
|
|
printer->Indent();
|
|
printer->Print(
|
|
*vars,
|
|
"return std::unique_ptr< ::grpc::ClientWriterInterface< $Request$>>"
|
|
"($Method$Raw(context, response));\n");
|
|
printer->Outdent();
|
|
printer->Print("}\n");
|
|
for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
|
|
i++) {
|
|
auto &async_prefix = async_prefixes[i];
|
|
(*vars)["AsyncPrefix"] = async_prefix.prefix;
|
|
(*vars)["AsyncMethodParams"] = async_prefix.method_params;
|
|
(*vars)["AsyncRawArgs"] = async_prefix.raw_args;
|
|
printer->Print(
|
|
*vars,
|
|
"std::unique_ptr< ::grpc::ClientAsyncWriterInterface< $Request$>>"
|
|
" $AsyncPrefix$$Method$(::grpc::ClientContext* context, "
|
|
"$Response$* "
|
|
"response, "
|
|
"::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
|
|
printer->Indent();
|
|
printer->Print(*vars,
|
|
"return std::unique_ptr< "
|
|
"::grpc::ClientAsyncWriterInterface< $Request$>>("
|
|
"$AsyncPrefix$$Method$Raw(context, response, "
|
|
"cq$AsyncRawArgs$));\n");
|
|
printer->Outdent();
|
|
printer->Print("}\n");
|
|
}
|
|
} else if (ServerOnlyStreaming(method)) {
|
|
printer->Print(
|
|
*vars,
|
|
"std::unique_ptr< ::grpc::ClientReaderInterface< $Response$>>"
|
|
" $Method$(::grpc::ClientContext* context, const $Request$& request)"
|
|
" {\n");
|
|
printer->Indent();
|
|
printer->Print(
|
|
*vars,
|
|
"return std::unique_ptr< ::grpc::ClientReaderInterface< $Response$>>"
|
|
"($Method$Raw(context, request));\n");
|
|
printer->Outdent();
|
|
printer->Print("}\n");
|
|
for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
|
|
i++) {
|
|
auto &async_prefix = async_prefixes[i];
|
|
(*vars)["AsyncPrefix"] = async_prefix.prefix;
|
|
(*vars)["AsyncMethodParams"] = async_prefix.method_params;
|
|
(*vars)["AsyncRawArgs"] = async_prefix.raw_args;
|
|
printer->Print(
|
|
*vars,
|
|
"std::unique_ptr< ::grpc::ClientAsyncReaderInterface< $Response$>> "
|
|
"$AsyncPrefix$$Method$("
|
|
"::grpc::ClientContext* context, const $Request$& request, "
|
|
"::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
|
|
printer->Indent();
|
|
printer->Print(
|
|
*vars,
|
|
"return std::unique_ptr< "
|
|
"::grpc::ClientAsyncReaderInterface< $Response$>>("
|
|
"$AsyncPrefix$$Method$Raw(context, request, cq$AsyncRawArgs$));\n");
|
|
printer->Outdent();
|
|
printer->Print("}\n");
|
|
}
|
|
} else if (method->BidiStreaming()) {
|
|
printer->Print(*vars,
|
|
"std::unique_ptr< ::grpc::ClientReaderWriterInterface< "
|
|
"$Request$, $Response$>> "
|
|
"$Method$(::grpc::ClientContext* context) {\n");
|
|
printer->Indent();
|
|
printer->Print(
|
|
*vars,
|
|
"return std::unique_ptr< "
|
|
"::grpc::ClientReaderWriterInterface< $Request$, $Response$>>("
|
|
"$Method$Raw(context));\n");
|
|
printer->Outdent();
|
|
printer->Print("}\n");
|
|
for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
|
|
i++) {
|
|
auto &async_prefix = async_prefixes[i];
|
|
(*vars)["AsyncPrefix"] = async_prefix.prefix;
|
|
(*vars)["AsyncMethodParams"] = async_prefix.method_params;
|
|
(*vars)["AsyncRawArgs"] = async_prefix.raw_args;
|
|
printer->Print(
|
|
*vars,
|
|
"std::unique_ptr< "
|
|
"::grpc::ClientAsyncReaderWriterInterface< $Request$, $Response$>> "
|
|
"$AsyncPrefix$$Method$(::grpc::ClientContext* context, "
|
|
"::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
|
|
printer->Indent();
|
|
printer->Print(
|
|
*vars,
|
|
"return std::unique_ptr< "
|
|
"::grpc::ClientAsyncReaderWriterInterface< $Request$, $Response$>>("
|
|
"$AsyncPrefix$$Method$Raw(context, cq$AsyncRawArgs$));\n");
|
|
printer->Outdent();
|
|
printer->Print("}\n");
|
|
}
|
|
}
|
|
} else {
|
|
if (method->NoStreaming()) {
|
|
for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
|
|
i++) {
|
|
auto &async_prefix = async_prefixes[i];
|
|
(*vars)["AsyncPrefix"] = async_prefix.prefix;
|
|
printer->Print(
|
|
*vars,
|
|
"virtual ::grpc::ClientAsyncResponseReaderInterface< $Response$>* "
|
|
"$AsyncPrefix$$Method$Raw(::grpc::ClientContext* context, "
|
|
"const $Request$& request, "
|
|
"::grpc::CompletionQueue* cq) = 0;\n");
|
|
}
|
|
} else if (ClientOnlyStreaming(method)) {
|
|
printer->Print(
|
|
*vars,
|
|
"virtual ::grpc::ClientWriterInterface< $Request$>*"
|
|
" $Method$Raw("
|
|
"::grpc::ClientContext* context, $Response$* response) = 0;\n");
|
|
for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
|
|
i++) {
|
|
auto &async_prefix = async_prefixes[i];
|
|
(*vars)["AsyncPrefix"] = async_prefix.prefix;
|
|
(*vars)["AsyncMethodParams"] = async_prefix.method_params;
|
|
printer->Print(
|
|
*vars,
|
|
"virtual ::grpc::ClientAsyncWriterInterface< $Request$>*"
|
|
" $AsyncPrefix$$Method$Raw(::grpc::ClientContext* context, "
|
|
"$Response$* response, "
|
|
"::grpc::CompletionQueue* cq$AsyncMethodParams$) = 0;\n");
|
|
}
|
|
} else if (ServerOnlyStreaming(method)) {
|
|
printer->Print(
|
|
*vars,
|
|
"virtual ::grpc::ClientReaderInterface< $Response$>* "
|
|
"$Method$Raw("
|
|
"::grpc::ClientContext* context, const $Request$& request) = 0;\n");
|
|
for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
|
|
i++) {
|
|
auto &async_prefix = async_prefixes[i];
|
|
(*vars)["AsyncPrefix"] = async_prefix.prefix;
|
|
(*vars)["AsyncMethodParams"] = async_prefix.method_params;
|
|
printer->Print(
|
|
*vars,
|
|
"virtual ::grpc::ClientAsyncReaderInterface< $Response$>* "
|
|
"$AsyncPrefix$$Method$Raw("
|
|
"::grpc::ClientContext* context, const $Request$& request, "
|
|
"::grpc::CompletionQueue* cq$AsyncMethodParams$) = 0;\n");
|
|
}
|
|
} else if (method->BidiStreaming()) {
|
|
printer->Print(*vars,
|
|
"virtual ::grpc::ClientReaderWriterInterface< $Request$, "
|
|
"$Response$>* "
|
|
"$Method$Raw(::grpc::ClientContext* context) = 0;\n");
|
|
for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
|
|
i++) {
|
|
auto &async_prefix = async_prefixes[i];
|
|
(*vars)["AsyncPrefix"] = async_prefix.prefix;
|
|
(*vars)["AsyncMethodParams"] = async_prefix.method_params;
|
|
printer->Print(
|
|
*vars,
|
|
"virtual ::grpc::ClientAsyncReaderWriterInterface< "
|
|
"$Request$, $Response$>* "
|
|
"$AsyncPrefix$$Method$Raw(::grpc::ClientContext* context, "
|
|
"::grpc::CompletionQueue* cq$AsyncMethodParams$) = 0;\n");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void PrintHeaderClientMethod(grpc_generator::Printer *printer,
|
|
const grpc_generator::Method *method,
|
|
std::map<grpc::string, grpc::string> *vars,
|
|
bool is_public) {
|
|
(*vars)["Method"] = method->name();
|
|
(*vars)["Request"] = method->input_type_name();
|
|
(*vars)["Response"] = method->output_type_name();
|
|
struct {
|
|
grpc::string prefix;
|
|
grpc::string method_params; // extra arguments to method
|
|
grpc::string raw_args; // extra arguments to raw version of method
|
|
} async_prefixes[] = { { "Async", ", void* tag", ", tag" },
|
|
{ "PrepareAsync", "", "" } };
|
|
|
|
if (is_public) {
|
|
if (method->NoStreaming()) {
|
|
printer->Print(
|
|
*vars,
|
|
"::grpc::Status $Method$(::grpc::ClientContext* context, "
|
|
"const $Request$& request, $Response$* response) override;\n");
|
|
for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
|
|
i++) {
|
|
auto &async_prefix = async_prefixes[i];
|
|
(*vars)["AsyncPrefix"] = async_prefix.prefix;
|
|
printer->Print(
|
|
*vars,
|
|
"std::unique_ptr< ::grpc::ClientAsyncResponseReader< $Response$>> "
|
|
"$AsyncPrefix$$Method$(::grpc::ClientContext* context, "
|
|
"const $Request$& request, "
|
|
"::grpc::CompletionQueue* cq) {\n");
|
|
printer->Indent();
|
|
printer->Print(*vars,
|
|
"return std::unique_ptr< "
|
|
"::grpc::ClientAsyncResponseReader< $Response$>>("
|
|
"$AsyncPrefix$$Method$Raw(context, request, cq));\n");
|
|
printer->Outdent();
|
|
printer->Print("}\n");
|
|
}
|
|
} else if (ClientOnlyStreaming(method)) {
|
|
printer->Print(
|
|
*vars,
|
|
"std::unique_ptr< ::grpc::ClientWriter< $Request$>>"
|
|
" $Method$("
|
|
"::grpc::ClientContext* context, $Response$* response) {\n");
|
|
printer->Indent();
|
|
printer->Print(*vars,
|
|
"return std::unique_ptr< ::grpc::ClientWriter< $Request$>>"
|
|
"($Method$Raw(context, response));\n");
|
|
printer->Outdent();
|
|
printer->Print("}\n");
|
|
for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
|
|
i++) {
|
|
auto &async_prefix = async_prefixes[i];
|
|
(*vars)["AsyncPrefix"] = async_prefix.prefix;
|
|
(*vars)["AsyncMethodParams"] = async_prefix.method_params;
|
|
(*vars)["AsyncRawArgs"] = async_prefix.raw_args;
|
|
printer->Print(*vars,
|
|
"std::unique_ptr< ::grpc::ClientAsyncWriter< $Request$>>"
|
|
" $AsyncPrefix$$Method$(::grpc::ClientContext* context, "
|
|
"$Response$* response, "
|
|
"::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
|
|
printer->Indent();
|
|
printer->Print(
|
|
*vars,
|
|
"return std::unique_ptr< ::grpc::ClientAsyncWriter< $Request$>>("
|
|
"$AsyncPrefix$$Method$Raw(context, response, "
|
|
"cq$AsyncRawArgs$));\n");
|
|
printer->Outdent();
|
|
printer->Print("}\n");
|
|
}
|
|
} else if (ServerOnlyStreaming(method)) {
|
|
printer->Print(
|
|
*vars,
|
|
"std::unique_ptr< ::grpc::ClientReader< $Response$>>"
|
|
" $Method$(::grpc::ClientContext* context, const $Request$& request)"
|
|
" {\n");
|
|
printer->Indent();
|
|
printer->Print(
|
|
*vars,
|
|
"return std::unique_ptr< ::grpc::ClientReader< $Response$>>"
|
|
"($Method$Raw(context, request));\n");
|
|
printer->Outdent();
|
|
printer->Print("}\n");
|
|
for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
|
|
i++) {
|
|
auto &async_prefix = async_prefixes[i];
|
|
(*vars)["AsyncPrefix"] = async_prefix.prefix;
|
|
(*vars)["AsyncMethodParams"] = async_prefix.method_params;
|
|
(*vars)["AsyncRawArgs"] = async_prefix.raw_args;
|
|
printer->Print(
|
|
*vars,
|
|
"std::unique_ptr< ::grpc::ClientAsyncReader< $Response$>> "
|
|
"$AsyncPrefix$$Method$("
|
|
"::grpc::ClientContext* context, const $Request$& request, "
|
|
"::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
|
|
printer->Indent();
|
|
printer->Print(
|
|
*vars,
|
|
"return std::unique_ptr< ::grpc::ClientAsyncReader< $Response$>>("
|
|
"$AsyncPrefix$$Method$Raw(context, request, cq$AsyncRawArgs$));\n");
|
|
printer->Outdent();
|
|
printer->Print("}\n");
|
|
}
|
|
} else if (method->BidiStreaming()) {
|
|
printer->Print(
|
|
*vars,
|
|
"std::unique_ptr< ::grpc::ClientReaderWriter< $Request$, $Response$>>"
|
|
" $Method$(::grpc::ClientContext* context) {\n");
|
|
printer->Indent();
|
|
printer->Print(*vars,
|
|
"return std::unique_ptr< "
|
|
"::grpc::ClientReaderWriter< $Request$, $Response$>>("
|
|
"$Method$Raw(context));\n");
|
|
printer->Outdent();
|
|
printer->Print("}\n");
|
|
for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
|
|
i++) {
|
|
auto &async_prefix = async_prefixes[i];
|
|
(*vars)["AsyncPrefix"] = async_prefix.prefix;
|
|
(*vars)["AsyncMethodParams"] = async_prefix.method_params;
|
|
(*vars)["AsyncRawArgs"] = async_prefix.raw_args;
|
|
printer->Print(*vars,
|
|
"std::unique_ptr< ::grpc::ClientAsyncReaderWriter< "
|
|
"$Request$, $Response$>> "
|
|
"$AsyncPrefix$$Method$(::grpc::ClientContext* context, "
|
|
"::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
|
|
printer->Indent();
|
|
printer->Print(
|
|
*vars,
|
|
"return std::unique_ptr< "
|
|
"::grpc::ClientAsyncReaderWriter< $Request$, $Response$>>("
|
|
"$AsyncPrefix$$Method$Raw(context, cq$AsyncRawArgs$));\n");
|
|
printer->Outdent();
|
|
printer->Print("}\n");
|
|
}
|
|
}
|
|
} else {
|
|
if (method->NoStreaming()) {
|
|
for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
|
|
i++) {
|
|
auto &async_prefix = async_prefixes[i];
|
|
(*vars)["AsyncPrefix"] = async_prefix.prefix;
|
|
printer->Print(
|
|
*vars,
|
|
"::grpc::ClientAsyncResponseReader< $Response$>* "
|
|
"$AsyncPrefix$$Method$Raw(::grpc::ClientContext* context, "
|
|
"const $Request$& request, "
|
|
"::grpc::CompletionQueue* cq) override;\n");
|
|
}
|
|
} else if (ClientOnlyStreaming(method)) {
|
|
printer->Print(*vars,
|
|
"::grpc::ClientWriter< $Request$>* $Method$Raw("
|
|
"::grpc::ClientContext* context, $Response$* response) "
|
|
"override;\n");
|
|
for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
|
|
i++) {
|
|
auto &async_prefix = async_prefixes[i];
|
|
(*vars)["AsyncPrefix"] = async_prefix.prefix;
|
|
(*vars)["AsyncMethodParams"] = async_prefix.method_params;
|
|
(*vars)["AsyncRawArgs"] = async_prefix.raw_args;
|
|
printer->Print(
|
|
*vars,
|
|
"::grpc::ClientAsyncWriter< $Request$>* $AsyncPrefix$$Method$Raw("
|
|
"::grpc::ClientContext* context, $Response$* response, "
|
|
"::grpc::CompletionQueue* cq$AsyncMethodParams$) override;\n");
|
|
}
|
|
} else if (ServerOnlyStreaming(method)) {
|
|
printer->Print(*vars,
|
|
"::grpc::ClientReader< $Response$>* $Method$Raw("
|
|
"::grpc::ClientContext* context, const $Request$& request)"
|
|
" override;\n");
|
|
for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
|
|
i++) {
|
|
auto &async_prefix = async_prefixes[i];
|
|
(*vars)["AsyncPrefix"] = async_prefix.prefix;
|
|
(*vars)["AsyncMethodParams"] = async_prefix.method_params;
|
|
(*vars)["AsyncRawArgs"] = async_prefix.raw_args;
|
|
printer->Print(
|
|
*vars,
|
|
"::grpc::ClientAsyncReader< $Response$>* $AsyncPrefix$$Method$Raw("
|
|
"::grpc::ClientContext* context, const $Request$& request, "
|
|
"::grpc::CompletionQueue* cq$AsyncMethodParams$) override;\n");
|
|
}
|
|
} else if (method->BidiStreaming()) {
|
|
printer->Print(*vars,
|
|
"::grpc::ClientReaderWriter< $Request$, $Response$>* "
|
|
"$Method$Raw(::grpc::ClientContext* context) override;\n");
|
|
for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
|
|
i++) {
|
|
auto &async_prefix = async_prefixes[i];
|
|
(*vars)["AsyncPrefix"] = async_prefix.prefix;
|
|
(*vars)["AsyncMethodParams"] = async_prefix.method_params;
|
|
(*vars)["AsyncRawArgs"] = async_prefix.raw_args;
|
|
printer->Print(
|
|
*vars,
|
|
"::grpc::ClientAsyncReaderWriter< $Request$, $Response$>* "
|
|
"$AsyncPrefix$$Method$Raw(::grpc::ClientContext* context, "
|
|
"::grpc::CompletionQueue* cq$AsyncMethodParams$) override;\n");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void PrintHeaderClientMethodData(grpc_generator::Printer *printer,
|
|
const grpc_generator::Method *method,
|
|
std::map<grpc::string, grpc::string> *vars) {
|
|
(*vars)["Method"] = method->name();
|
|
printer->Print(*vars,
|
|
"const ::grpc::internal::RpcMethod rpcmethod_$Method$_;\n");
|
|
}
|
|
|
|
void PrintHeaderServerMethodSync(grpc_generator::Printer *printer,
|
|
const grpc_generator::Method *method,
|
|
std::map<grpc::string, grpc::string> *vars) {
|
|
(*vars)["Method"] = method->name();
|
|
(*vars)["Request"] = method->input_type_name();
|
|
(*vars)["Response"] = method->output_type_name();
|
|
printer->Print(method->GetLeadingComments("//").c_str());
|
|
if (method->NoStreaming()) {
|
|
printer->Print(*vars,
|
|
"virtual ::grpc::Status $Method$("
|
|
"::grpc::ServerContext* context, const $Request$* request, "
|
|
"$Response$* response);\n");
|
|
} else if (ClientOnlyStreaming(method)) {
|
|
printer->Print(*vars,
|
|
"virtual ::grpc::Status $Method$("
|
|
"::grpc::ServerContext* context, "
|
|
"::grpc::ServerReader< $Request$>* reader, "
|
|
"$Response$* response);\n");
|
|
} else if (ServerOnlyStreaming(method)) {
|
|
printer->Print(*vars,
|
|
"virtual ::grpc::Status $Method$("
|
|
"::grpc::ServerContext* context, const $Request$* request, "
|
|
"::grpc::ServerWriter< $Response$>* writer);\n");
|
|
} else if (method->BidiStreaming()) {
|
|
printer->Print(
|
|
*vars,
|
|
"virtual ::grpc::Status $Method$("
|
|
"::grpc::ServerContext* context, "
|
|
"::grpc::ServerReaderWriter< $Response$, $Request$>* stream);"
|
|
"\n");
|
|
}
|
|
printer->Print(method->GetTrailingComments("//").c_str());
|
|
}
|
|
|
|
void PrintHeaderServerMethodAsync(grpc_generator::Printer *printer,
|
|
const grpc_generator::Method *method,
|
|
std::map<grpc::string, grpc::string> *vars) {
|
|
(*vars)["Method"] = method->name();
|
|
(*vars)["Request"] = method->input_type_name();
|
|
(*vars)["Response"] = method->output_type_name();
|
|
printer->Print(*vars, "template <class BaseClass>\n");
|
|
printer->Print(*vars,
|
|
"class WithAsyncMethod_$Method$ : public BaseClass {\n");
|
|
printer->Print(
|
|
" private:\n"
|
|
" void BaseClassMustBeDerivedFromService(const Service */*service*/) "
|
|
"{}\n");
|
|
printer->Print(" public:\n");
|
|
printer->Indent();
|
|
printer->Print(*vars,
|
|
"WithAsyncMethod_$Method$() {\n"
|
|
" ::grpc::Service::MarkMethodAsync($Idx$);\n"
|
|
"}\n");
|
|
printer->Print(*vars,
|
|
"~WithAsyncMethod_$Method$() override {\n"
|
|
" BaseClassMustBeDerivedFromService(this);\n"
|
|
"}\n");
|
|
if (method->NoStreaming()) {
|
|
printer->Print(
|
|
*vars,
|
|
"// disable synchronous version of this method\n"
|
|
"::grpc::Status $Method$("
|
|
"::grpc::ServerContext* /*context*/, const $Request$* /*request*/, "
|
|
"$Response$* /*response*/) final override {\n"
|
|
" abort();\n"
|
|
" return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
|
|
"}\n");
|
|
printer->Print(
|
|
*vars,
|
|
"void Request$Method$("
|
|
"::grpc::ServerContext* context, $Request$* request, "
|
|
"::grpc::ServerAsyncResponseWriter< $Response$>* response, "
|
|
"::grpc::CompletionQueue* new_call_cq, "
|
|
"::grpc::ServerCompletionQueue* notification_cq, void *tag) {\n");
|
|
printer->Print(*vars,
|
|
" ::grpc::Service::RequestAsyncUnary($Idx$, context, "
|
|
"request, response, new_call_cq, notification_cq, tag);\n");
|
|
printer->Print("}\n");
|
|
} else if (ClientOnlyStreaming(method)) {
|
|
printer->Print(
|
|
*vars,
|
|
"// disable synchronous version of this method\n"
|
|
"::grpc::Status $Method$("
|
|
"::grpc::ServerContext* /*context*/, "
|
|
"::grpc::ServerReader< $Request$>* /*reader*/, "
|
|
"$Response$* /*response*/) final override {\n"
|
|
" abort();\n"
|
|
" return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
|
|
"}\n");
|
|
printer->Print(
|
|
*vars,
|
|
"void Request$Method$("
|
|
"::grpc::ServerContext* context, "
|
|
"::grpc::ServerAsyncReader< $Response$, $Request$>* reader, "
|
|
"::grpc::CompletionQueue* new_call_cq, "
|
|
"::grpc::ServerCompletionQueue* notification_cq, void *tag) {\n");
|
|
printer->Print(*vars,
|
|
" ::grpc::Service::RequestAsyncClientStreaming($Idx$, "
|
|
"context, reader, new_call_cq, notification_cq, tag);\n");
|
|
printer->Print("}\n");
|
|
} else if (ServerOnlyStreaming(method)) {
|
|
printer->Print(
|
|
*vars,
|
|
"// disable synchronous version of this method\n"
|
|
"::grpc::Status $Method$("
|
|
"::grpc::ServerContext* /*context*/, const $Request$* /*request*/, "
|
|
"::grpc::ServerWriter< $Response$>* /*writer*/) final override "
|
|
"{\n"
|
|
" abort();\n"
|
|
" return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
|
|
"}\n");
|
|
printer->Print(
|
|
*vars,
|
|
"void Request$Method$("
|
|
"::grpc::ServerContext* context, $Request$* request, "
|
|
"::grpc::ServerAsyncWriter< $Response$>* writer, "
|
|
"::grpc::CompletionQueue* new_call_cq, "
|
|
"::grpc::ServerCompletionQueue* notification_cq, void *tag) {\n");
|
|
printer->Print(
|
|
*vars,
|
|
" ::grpc::Service::RequestAsyncServerStreaming($Idx$, "
|
|
"context, request, writer, new_call_cq, notification_cq, tag);\n");
|
|
printer->Print("}\n");
|
|
} else if (method->BidiStreaming()) {
|
|
printer->Print(
|
|
*vars,
|
|
"// disable synchronous version of this method\n"
|
|
"::grpc::Status $Method$("
|
|
"::grpc::ServerContext* /*context*/, "
|
|
"::grpc::ServerReaderWriter< $Response$, $Request$>* /*stream*/) "
|
|
"final override {\n"
|
|
" abort();\n"
|
|
" return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
|
|
"}\n");
|
|
printer->Print(
|
|
*vars,
|
|
"void Request$Method$("
|
|
"::grpc::ServerContext* context, "
|
|
"::grpc::ServerAsyncReaderWriter< $Response$, $Request$>* stream, "
|
|
"::grpc::CompletionQueue* new_call_cq, "
|
|
"::grpc::ServerCompletionQueue* notification_cq, void *tag) {\n");
|
|
printer->Print(*vars,
|
|
" ::grpc::Service::RequestAsyncBidiStreaming($Idx$, "
|
|
"context, stream, new_call_cq, notification_cq, tag);\n");
|
|
printer->Print("}\n");
|
|
}
|
|
printer->Outdent();
|
|
printer->Print(*vars, "};\n");
|
|
}
|
|
|
|
void PrintHeaderServerMethodStreamedUnary(
|
|
grpc_generator::Printer *printer, const grpc_generator::Method *method,
|
|
std::map<grpc::string, grpc::string> *vars) {
|
|
(*vars)["Method"] = method->name();
|
|
(*vars)["Request"] = method->input_type_name();
|
|
(*vars)["Response"] = method->output_type_name();
|
|
if (method->NoStreaming()) {
|
|
printer->Print(*vars, "template <class BaseClass>\n");
|
|
printer->Print(*vars,
|
|
"class WithStreamedUnaryMethod_$Method$ : "
|
|
"public BaseClass {\n");
|
|
printer->Print(
|
|
" private:\n"
|
|
" void BaseClassMustBeDerivedFromService(const Service */*service*/) "
|
|
"{}\n");
|
|
printer->Print(" public:\n");
|
|
printer->Indent();
|
|
printer->Print(*vars,
|
|
"WithStreamedUnaryMethod_$Method$() {\n"
|
|
" ::grpc::Service::MarkMethodStreamed($Idx$,\n"
|
|
" new ::grpc::internal::StreamedUnaryHandler< $Request$, "
|
|
"$Response$>(std::bind"
|
|
"(&WithStreamedUnaryMethod_$Method$<BaseClass>::"
|
|
"Streamed$Method$, this, std::placeholders::_1, "
|
|
"std::placeholders::_2)));\n"
|
|
"}\n");
|
|
printer->Print(*vars,
|
|
"~WithStreamedUnaryMethod_$Method$() override {\n"
|
|
" BaseClassMustBeDerivedFromService(this);\n"
|
|
"}\n");
|
|
printer->Print(
|
|
*vars,
|
|
"// disable regular version of this method\n"
|
|
"::grpc::Status $Method$("
|
|
"::grpc::ServerContext* /*context*/, const $Request$* /*request*/, "
|
|
"$Response$* /*response*/) final override {\n"
|
|
" abort();\n"
|
|
" return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
|
|
"}\n");
|
|
printer->Print(*vars,
|
|
"// replace default version of method with streamed unary\n"
|
|
"virtual ::grpc::Status Streamed$Method$("
|
|
"::grpc::ServerContext* context, "
|
|
"::grpc::ServerUnaryStreamer< "
|
|
"$Request$,$Response$>* server_unary_streamer)"
|
|
" = 0;\n");
|
|
printer->Outdent();
|
|
printer->Print(*vars, "};\n");
|
|
}
|
|
}
|
|
|
|
void PrintHeaderServerMethodSplitStreaming(
|
|
grpc_generator::Printer *printer, const grpc_generator::Method *method,
|
|
std::map<grpc::string, grpc::string> *vars) {
|
|
(*vars)["Method"] = method->name();
|
|
(*vars)["Request"] = method->input_type_name();
|
|
(*vars)["Response"] = method->output_type_name();
|
|
if (ServerOnlyStreaming(method)) {
|
|
printer->Print(*vars, "template <class BaseClass>\n");
|
|
printer->Print(*vars,
|
|
"class WithSplitStreamingMethod_$Method$ : "
|
|
"public BaseClass {\n");
|
|
printer->Print(
|
|
" private:\n"
|
|
" void BaseClassMustBeDerivedFromService(const Service */*service*/) "
|
|
"{ }\n");
|
|
printer->Print(" public:\n");
|
|
printer->Indent();
|
|
printer->Print(
|
|
*vars,
|
|
"WithSplitStreamingMethod_$Method$() {\n"
|
|
" ::grpc::Service::MarkMethodStreamed($Idx$,\n"
|
|
" new ::grpc::internal::SplitServerStreamingHandler< $Request$, "
|
|
"$Response$>(std::bind"
|
|
"(&WithSplitStreamingMethod_$Method$<BaseClass>::"
|
|
"Streamed$Method$, this, std::placeholders::_1, "
|
|
"std::placeholders::_2)));\n"
|
|
"}\n");
|
|
printer->Print(*vars,
|
|
"~WithSplitStreamingMethod_$Method$() override {\n"
|
|
" BaseClassMustBeDerivedFromService(this);\n"
|
|
"}\n");
|
|
printer->Print(
|
|
*vars,
|
|
"// disable regular version of this method\n"
|
|
"::grpc::Status $Method$("
|
|
"::grpc::ServerContext* /*context*/, const $Request$* /*request*/, "
|
|
"::grpc::ServerWriter< $Response$>* /*writer*/) final override "
|
|
"{\n"
|
|
" abort();\n"
|
|
" return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
|
|
"}\n");
|
|
printer->Print(*vars,
|
|
"// replace default version of method with split streamed\n"
|
|
"virtual ::grpc::Status Streamed$Method$("
|
|
"::grpc::ServerContext* context, "
|
|
"::grpc::ServerSplitStreamer< "
|
|
"$Request$,$Response$>* server_split_streamer)"
|
|
" = 0;\n");
|
|
printer->Outdent();
|
|
printer->Print(*vars, "};\n");
|
|
}
|
|
}
|
|
|
|
void PrintHeaderServerMethodGeneric(
|
|
grpc_generator::Printer *printer, const grpc_generator::Method *method,
|
|
std::map<grpc::string, grpc::string> *vars) {
|
|
(*vars)["Method"] = method->name();
|
|
(*vars)["Request"] = method->input_type_name();
|
|
(*vars)["Response"] = method->output_type_name();
|
|
printer->Print(*vars, "template <class BaseClass>\n");
|
|
printer->Print(*vars,
|
|
"class WithGenericMethod_$Method$ : public BaseClass {\n");
|
|
printer->Print(
|
|
" private:\n"
|
|
" void BaseClassMustBeDerivedFromService(const Service */*service*/) "
|
|
"{}\n");
|
|
printer->Print(" public:\n");
|
|
printer->Indent();
|
|
printer->Print(*vars,
|
|
"WithGenericMethod_$Method$() {\n"
|
|
" ::grpc::Service::MarkMethodGeneric($Idx$);\n"
|
|
"}\n");
|
|
printer->Print(*vars,
|
|
"~WithGenericMethod_$Method$() override {\n"
|
|
" BaseClassMustBeDerivedFromService(this);\n"
|
|
"}\n");
|
|
if (method->NoStreaming()) {
|
|
printer->Print(
|
|
*vars,
|
|
"// disable synchronous version of this method\n"
|
|
"::grpc::Status $Method$("
|
|
"::grpc::ServerContext* /*context*/, const $Request$* /*request*/, "
|
|
"$Response$* /*response*/) final override {\n"
|
|
" abort();\n"
|
|
" return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
|
|
"}\n");
|
|
} else if (ClientOnlyStreaming(method)) {
|
|
printer->Print(
|
|
*vars,
|
|
"// disable synchronous version of this method\n"
|
|
"::grpc::Status $Method$("
|
|
"::grpc::ServerContext* /*context*/, "
|
|
"::grpc::ServerReader< $Request$>* /*reader*/, "
|
|
"$Response$* /*response*/) final override {\n"
|
|
" abort();\n"
|
|
" return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
|
|
"}\n");
|
|
} else if (ServerOnlyStreaming(method)) {
|
|
printer->Print(
|
|
*vars,
|
|
"// disable synchronous version of this method\n"
|
|
"::grpc::Status $Method$("
|
|
"::grpc::ServerContext* /*context*/, const $Request$* /*request*/, "
|
|
"::grpc::ServerWriter< $Response$>* /*writer*/) final override "
|
|
"{\n"
|
|
" abort();\n"
|
|
" return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
|
|
"}\n");
|
|
} else if (method->BidiStreaming()) {
|
|
printer->Print(
|
|
*vars,
|
|
"// disable synchronous version of this method\n"
|
|
"::grpc::Status $Method$("
|
|
"::grpc::ServerContext* /*context*/, "
|
|
"::grpc::ServerReaderWriter< $Response$, $Request$>* /*stream*/) "
|
|
"final override {\n"
|
|
" abort();\n"
|
|
" return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"
|
|
"}\n");
|
|
}
|
|
printer->Outdent();
|
|
printer->Print(*vars, "};\n");
|
|
}
|
|
|
|
void PrintHeaderService(grpc_generator::Printer *printer,
|
|
const grpc_generator::Service *service,
|
|
std::map<grpc::string, grpc::string> *vars) {
|
|
(*vars)["Service"] = service->name();
|
|
|
|
printer->Print(service->GetLeadingComments("//").c_str());
|
|
printer->Print(*vars,
|
|
"class $Service$ final {\n"
|
|
" public:\n");
|
|
printer->Indent();
|
|
|
|
// Service metadata
|
|
printer->Print(*vars,
|
|
"static constexpr char const* service_full_name() {\n"
|
|
" return \"$Package$$Service$\";\n"
|
|
"}\n");
|
|
|
|
// Client side
|
|
printer->Print(
|
|
"class StubInterface {\n"
|
|
" public:\n");
|
|
printer->Indent();
|
|
printer->Print("virtual ~StubInterface() {}\n");
|
|
for (int i = 0; i < service->method_count(); ++i) {
|
|
printer->Print(service->method(i)->GetLeadingComments("//").c_str());
|
|
PrintHeaderClientMethodInterfaces(printer, service->method(i).get(), vars,
|
|
true);
|
|
printer->Print(service->method(i)->GetTrailingComments("//").c_str());
|
|
}
|
|
printer->Outdent();
|
|
printer->Print("private:\n");
|
|
printer->Indent();
|
|
for (int i = 0; i < service->method_count(); ++i) {
|
|
PrintHeaderClientMethodInterfaces(printer, service->method(i).get(), vars,
|
|
false);
|
|
}
|
|
printer->Outdent();
|
|
printer->Print("};\n");
|
|
printer->Print(
|
|
"class Stub final : public StubInterface"
|
|
" {\n public:\n");
|
|
printer->Indent();
|
|
printer->Print(
|
|
"Stub(const std::shared_ptr< ::grpc::ChannelInterface>& "
|
|
"channel);\n");
|
|
for (int i = 0; i < service->method_count(); ++i) {
|
|
PrintHeaderClientMethod(printer, service->method(i).get(), vars, true);
|
|
}
|
|
printer->Outdent();
|
|
printer->Print("\n private:\n");
|
|
printer->Indent();
|
|
printer->Print("std::shared_ptr< ::grpc::ChannelInterface> channel_;\n");
|
|
for (int i = 0; i < service->method_count(); ++i) {
|
|
PrintHeaderClientMethod(printer, service->method(i).get(), vars, false);
|
|
}
|
|
for (int i = 0; i < service->method_count(); ++i) {
|
|
PrintHeaderClientMethodData(printer, service->method(i).get(), vars);
|
|
}
|
|
printer->Outdent();
|
|
printer->Print("};\n");
|
|
printer->Print(
|
|
"static std::unique_ptr<Stub> NewStub(const std::shared_ptr< "
|
|
"::grpc::ChannelInterface>& channel, "
|
|
"const ::grpc::StubOptions& options = ::grpc::StubOptions());\n");
|
|
|
|
printer->Print("\n");
|
|
|
|
// Server side - base
|
|
printer->Print(
|
|
"class Service : public ::grpc::Service {\n"
|
|
" public:\n");
|
|
printer->Indent();
|
|
printer->Print("Service();\n");
|
|
printer->Print("virtual ~Service();\n");
|
|
for (int i = 0; i < service->method_count(); ++i) {
|
|
PrintHeaderServerMethodSync(printer, service->method(i).get(), vars);
|
|
}
|
|
printer->Outdent();
|
|
printer->Print("};\n");
|
|
|
|
// Server side - Asynchronous
|
|
for (int i = 0; i < service->method_count(); ++i) {
|
|
(*vars)["Idx"] = as_string(i);
|
|
PrintHeaderServerMethodAsync(printer, service->method(i).get(), vars);
|
|
}
|
|
|
|
printer->Print("typedef ");
|
|
|
|
for (int i = 0; i < service->method_count(); ++i) {
|
|
(*vars)["method_name"] = service->method(i).get()->name();
|
|
printer->Print(*vars, "WithAsyncMethod_$method_name$<");
|
|
}
|
|
printer->Print("Service");
|
|
for (int i = 0; i < service->method_count(); ++i) { printer->Print(" >"); }
|
|
printer->Print(" AsyncService;\n");
|
|
|
|
// Server side - Generic
|
|
for (int i = 0; i < service->method_count(); ++i) {
|
|
(*vars)["Idx"] = as_string(i);
|
|
PrintHeaderServerMethodGeneric(printer, service->method(i).get(), vars);
|
|
}
|
|
|
|
// Server side - Streamed Unary
|
|
for (int i = 0; i < service->method_count(); ++i) {
|
|
(*vars)["Idx"] = as_string(i);
|
|
PrintHeaderServerMethodStreamedUnary(printer, service->method(i).get(),
|
|
vars);
|
|
}
|
|
|
|
printer->Print("typedef ");
|
|
for (int i = 0; i < service->method_count(); ++i) {
|
|
(*vars)["method_name"] = service->method(i).get()->name();
|
|
if (service->method(i)->NoStreaming()) {
|
|
printer->Print(*vars, "WithStreamedUnaryMethod_$method_name$<");
|
|
}
|
|
}
|
|
printer->Print("Service");
|
|
for (int i = 0; i < service->method_count(); ++i) {
|
|
if (service->method(i)->NoStreaming()) { printer->Print(" >"); }
|
|
}
|
|
printer->Print(" StreamedUnaryService;\n");
|
|
|
|
// Server side - controlled server-side streaming
|
|
for (int i = 0; i < service->method_count(); ++i) {
|
|
(*vars)["Idx"] = as_string(i);
|
|
PrintHeaderServerMethodSplitStreaming(printer, service->method(i).get(),
|
|
vars);
|
|
}
|
|
|
|
printer->Print("typedef ");
|
|
for (int i = 0; i < service->method_count(); ++i) {
|
|
(*vars)["method_name"] = service->method(i).get()->name();
|
|
auto method = service->method(i);
|
|
if (ServerOnlyStreaming(method.get())) {
|
|
printer->Print(*vars, "WithSplitStreamingMethod_$method_name$<");
|
|
}
|
|
}
|
|
printer->Print("Service");
|
|
for (int i = 0; i < service->method_count(); ++i) {
|
|
auto method = service->method(i);
|
|
if (ServerOnlyStreaming(method.get())) { printer->Print(" >"); }
|
|
}
|
|
printer->Print(" SplitStreamedService;\n");
|
|
|
|
// Server side - typedef for controlled both unary and server-side streaming
|
|
printer->Print("typedef ");
|
|
for (int i = 0; i < service->method_count(); ++i) {
|
|
(*vars)["method_name"] = service->method(i).get()->name();
|
|
auto method = service->method(i);
|
|
if (ServerOnlyStreaming(method.get())) {
|
|
printer->Print(*vars, "WithSplitStreamingMethod_$method_name$<");
|
|
}
|
|
if (service->method(i)->NoStreaming()) {
|
|
printer->Print(*vars, "WithStreamedUnaryMethod_$method_name$<");
|
|
}
|
|
}
|
|
printer->Print("Service");
|
|
for (int i = 0; i < service->method_count(); ++i) {
|
|
auto method = service->method(i);
|
|
if (service->method(i)->NoStreaming() ||
|
|
ServerOnlyStreaming(method.get())) {
|
|
printer->Print(" >");
|
|
}
|
|
}
|
|
printer->Print(" StreamedService;\n");
|
|
|
|
printer->Outdent();
|
|
printer->Print("};\n");
|
|
printer->Print(service->GetTrailingComments("//").c_str());
|
|
}
|
|
|
|
grpc::string GetHeaderServices(grpc_generator::File *file,
|
|
const Parameters ¶ms) {
|
|
grpc::string output;
|
|
{
|
|
// Scope the output stream so it closes and finalizes output to the string.
|
|
auto printer = file->CreatePrinter(&output);
|
|
std::map<grpc::string, grpc::string> vars;
|
|
// Package string is empty or ends with a dot. It is used to fully qualify
|
|
// method names.
|
|
vars["Package"] = file->package();
|
|
if (!file->package().empty()) { vars["Package"].append("."); }
|
|
|
|
if (!params.services_namespace.empty()) {
|
|
vars["services_namespace"] = params.services_namespace;
|
|
printer->Print(vars, "\nnamespace $services_namespace$ {\n\n");
|
|
}
|
|
|
|
for (int i = 0; i < file->service_count(); ++i) {
|
|
PrintHeaderService(printer.get(), file->service(i).get(), &vars);
|
|
printer->Print("\n");
|
|
}
|
|
|
|
if (!params.services_namespace.empty()) {
|
|
printer->Print(vars, "} // namespace $services_namespace$\n\n");
|
|
}
|
|
}
|
|
return output;
|
|
}
|
|
|
|
grpc::string GetHeaderEpilogue(grpc_generator::File *file,
|
|
const Parameters & /*params*/) {
|
|
grpc::string output;
|
|
{
|
|
// Scope the output stream so it closes and finalizes output to the string.
|
|
auto printer = file->CreatePrinter(&output);
|
|
std::map<grpc::string, grpc::string> vars;
|
|
|
|
vars["filename"] = file->filename();
|
|
vars["filename_identifier"] = FilenameIdentifier(file->filename());
|
|
|
|
if (!file->package().empty()) {
|
|
std::vector<grpc::string> parts = file->package_parts();
|
|
|
|
for (auto part = parts.rbegin(); part != parts.rend(); part++) {
|
|
vars["part"] = *part;
|
|
printer->Print(vars, "} // namespace $part$\n");
|
|
}
|
|
printer->Print(vars, "\n");
|
|
}
|
|
|
|
printer->Print(vars, "\n");
|
|
printer->Print(vars, "#endif // GRPC_$filename_identifier$__INCLUDED\n");
|
|
|
|
printer->Print(file->GetTrailingComments("//").c_str());
|
|
}
|
|
return output;
|
|
}
|
|
|
|
grpc::string GetSourcePrologue(grpc_generator::File *file,
|
|
const Parameters ¶ms) {
|
|
grpc::string output;
|
|
{
|
|
// Scope the output stream so it closes and finalizes output to the string.
|
|
auto printer = file->CreatePrinter(&output);
|
|
std::map<grpc::string, grpc::string> vars;
|
|
|
|
vars["filename"] = file->filename();
|
|
vars["filename_base"] = file->filename_without_ext();
|
|
vars["message_header_ext"] = params.message_header_extension;
|
|
vars["service_header_ext"] = service_header_ext();
|
|
|
|
printer->Print(vars, "// Generated by the gRPC C++ plugin.\n");
|
|
printer->Print(vars,
|
|
"// If you make any local change, they will be lost.\n");
|
|
printer->Print(vars, "// source: $filename$\n\n");
|
|
|
|
printer->Print(vars, "#include \"$filename_base$$message_header_ext$\"\n");
|
|
printer->Print(vars, "#include \"$filename_base$$service_header_ext$\"\n");
|
|
printer->Print(vars, "\n");
|
|
}
|
|
return output;
|
|
}
|
|
|
|
grpc::string GetSourceIncludes(grpc_generator::File *file,
|
|
const Parameters ¶ms) {
|
|
grpc::string output;
|
|
{
|
|
// Scope the output stream so it closes and finalizes output to the string.
|
|
auto printer = file->CreatePrinter(&output);
|
|
std::map<grpc::string, grpc::string> vars;
|
|
|
|
static const char *headers_strs[] = {
|
|
"grpcpp/impl/codegen/async_stream.h",
|
|
"grpcpp/impl/codegen/async_unary_call.h",
|
|
"grpcpp/impl/codegen/channel_interface.h",
|
|
"grpcpp/impl/codegen/client_unary_call.h",
|
|
"grpcpp/impl/codegen/method_handler.h",
|
|
"grpcpp/impl/codegen/rpc_service_method.h",
|
|
"grpcpp/impl/codegen/service_type.h",
|
|
"grpcpp/impl/codegen/sync_stream.h"
|
|
};
|
|
std::vector<grpc::string> headers(headers_strs, array_end(headers_strs));
|
|
PrintIncludes(printer.get(), headers, params);
|
|
|
|
if (!file->package().empty()) {
|
|
std::vector<grpc::string> parts = file->package_parts();
|
|
|
|
for (auto part = parts.begin(); part != parts.end(); part++) {
|
|
vars["part"] = *part;
|
|
printer->Print(vars, "namespace $part$ {\n");
|
|
}
|
|
}
|
|
|
|
printer->Print(vars, "\n");
|
|
}
|
|
return output;
|
|
}
|
|
|
|
void PrintSourceClientMethod(grpc_generator::Printer *printer,
|
|
const grpc_generator::Method *method,
|
|
std::map<grpc::string, grpc::string> *vars) {
|
|
(*vars)["Method"] = method->name();
|
|
(*vars)["Request"] = method->input_type_name();
|
|
(*vars)["Response"] = method->output_type_name();
|
|
struct {
|
|
grpc::string prefix;
|
|
grpc::string start; // bool literal expressed as string
|
|
grpc::string method_params; // extra arguments to method
|
|
grpc::string create_args; // extra arguments to creator
|
|
} async_prefixes[] = { { "Async", "true", ", void* tag", ", tag" },
|
|
{ "PrepareAsync", "false", "", ", nullptr" } };
|
|
if (method->NoStreaming()) {
|
|
printer->Print(*vars,
|
|
"::grpc::Status $ns$$Service$::Stub::$Method$("
|
|
"::grpc::ClientContext* context, "
|
|
"const $Request$& request, $Response$* response) {\n");
|
|
printer->Print(*vars,
|
|
" return ::grpc::internal::BlockingUnaryCall"
|
|
"(channel_.get(), rpcmethod_$Method$_, "
|
|
"context, request, response);\n}\n\n");
|
|
for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
|
|
i++) {
|
|
auto &async_prefix = async_prefixes[i];
|
|
(*vars)["AsyncPrefix"] = async_prefix.prefix;
|
|
(*vars)["AsyncStart"] = async_prefix.start;
|
|
printer->Print(*vars,
|
|
"::grpc::ClientAsyncResponseReader< $Response$>* "
|
|
"$ns$$Service$::Stub::$AsyncPrefix$$Method$Raw(::grpc::"
|
|
"ClientContext* context, "
|
|
"const $Request$& request, "
|
|
"::grpc::CompletionQueue* cq) {\n");
|
|
printer->Print(
|
|
*vars,
|
|
" return "
|
|
"::grpc::internal::ClientAsyncResponseReaderFactory< $Response$>"
|
|
"::Create(channel_.get(), cq, "
|
|
"rpcmethod_$Method$_, "
|
|
"context, request, $AsyncStart$);\n"
|
|
"}\n\n");
|
|
}
|
|
} else if (ClientOnlyStreaming(method)) {
|
|
printer->Print(*vars,
|
|
"::grpc::ClientWriter< $Request$>* "
|
|
"$ns$$Service$::Stub::$Method$Raw("
|
|
"::grpc::ClientContext* context, $Response$* response) {\n");
|
|
printer->Print(
|
|
*vars,
|
|
" return ::grpc::internal::ClientWriterFactory< $Request$>::Create("
|
|
"channel_.get(), "
|
|
"rpcmethod_$Method$_, "
|
|
"context, response);\n"
|
|
"}\n\n");
|
|
for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
|
|
i++) {
|
|
auto &async_prefix = async_prefixes[i];
|
|
(*vars)["AsyncPrefix"] = async_prefix.prefix;
|
|
(*vars)["AsyncStart"] = async_prefix.start;
|
|
(*vars)["AsyncMethodParams"] = async_prefix.method_params;
|
|
(*vars)["AsyncCreateArgs"] = async_prefix.create_args;
|
|
printer->Print(*vars,
|
|
"::grpc::ClientAsyncWriter< $Request$>* "
|
|
"$ns$$Service$::Stub::$AsyncPrefix$$Method$Raw("
|
|
"::grpc::ClientContext* context, $Response$* response, "
|
|
"::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
|
|
printer->Print(
|
|
*vars,
|
|
" return ::grpc::internal::ClientAsyncWriterFactory< $Request$>"
|
|
"::Create(channel_.get(), cq, "
|
|
"rpcmethod_$Method$_, "
|
|
"context, response, $AsyncStart$$AsyncCreateArgs$);\n"
|
|
"}\n\n");
|
|
}
|
|
} else if (ServerOnlyStreaming(method)) {
|
|
printer->Print(
|
|
*vars,
|
|
"::grpc::ClientReader< $Response$>* "
|
|
"$ns$$Service$::Stub::$Method$Raw("
|
|
"::grpc::ClientContext* context, const $Request$& request) {\n");
|
|
printer->Print(
|
|
*vars,
|
|
" return ::grpc::internal::ClientReaderFactory< $Response$>::Create("
|
|
"channel_.get(), "
|
|
"rpcmethod_$Method$_, "
|
|
"context, request);\n"
|
|
"}\n\n");
|
|
for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
|
|
i++) {
|
|
auto &async_prefix = async_prefixes[i];
|
|
(*vars)["AsyncPrefix"] = async_prefix.prefix;
|
|
(*vars)["AsyncStart"] = async_prefix.start;
|
|
(*vars)["AsyncMethodParams"] = async_prefix.method_params;
|
|
(*vars)["AsyncCreateArgs"] = async_prefix.create_args;
|
|
printer->Print(
|
|
*vars,
|
|
"::grpc::ClientAsyncReader< $Response$>* "
|
|
"$ns$$Service$::Stub::$AsyncPrefix$$Method$Raw("
|
|
"::grpc::ClientContext* context, const $Request$& request, "
|
|
"::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
|
|
printer->Print(
|
|
*vars,
|
|
" return ::grpc::internal::ClientAsyncReaderFactory< $Response$>"
|
|
"::Create(channel_.get(), cq, "
|
|
"rpcmethod_$Method$_, "
|
|
"context, request, $AsyncStart$$AsyncCreateArgs$);\n"
|
|
"}\n\n");
|
|
}
|
|
} else if (method->BidiStreaming()) {
|
|
printer->Print(
|
|
*vars,
|
|
"::grpc::ClientReaderWriter< $Request$, $Response$>* "
|
|
"$ns$$Service$::Stub::$Method$Raw(::grpc::ClientContext* context) {\n");
|
|
printer->Print(*vars,
|
|
" return ::grpc::internal::ClientReaderWriterFactory< "
|
|
"$Request$, $Response$>::Create("
|
|
"channel_.get(), "
|
|
"rpcmethod_$Method$_, "
|
|
"context);\n"
|
|
"}\n\n");
|
|
for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
|
|
i++) {
|
|
auto &async_prefix = async_prefixes[i];
|
|
(*vars)["AsyncPrefix"] = async_prefix.prefix;
|
|
(*vars)["AsyncStart"] = async_prefix.start;
|
|
(*vars)["AsyncMethodParams"] = async_prefix.method_params;
|
|
(*vars)["AsyncCreateArgs"] = async_prefix.create_args;
|
|
printer->Print(*vars,
|
|
"::grpc::ClientAsyncReaderWriter< $Request$, $Response$>* "
|
|
"$ns$$Service$::Stub::$AsyncPrefix$$Method$Raw(::grpc::"
|
|
"ClientContext* context, "
|
|
"::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
|
|
printer->Print(*vars,
|
|
" return "
|
|
"::grpc::internal::ClientAsyncReaderWriterFactory< "
|
|
"$Request$, $Response$>::Create("
|
|
"channel_.get(), cq, "
|
|
"rpcmethod_$Method$_, "
|
|
"context, $AsyncStart$$AsyncCreateArgs$);\n"
|
|
"}\n\n");
|
|
}
|
|
}
|
|
}
|
|
|
|
void PrintSourceServerMethod(grpc_generator::Printer *printer,
|
|
const grpc_generator::Method *method,
|
|
std::map<grpc::string, grpc::string> *vars) {
|
|
(*vars)["Method"] = method->name();
|
|
(*vars)["Request"] = method->input_type_name();
|
|
(*vars)["Response"] = method->output_type_name();
|
|
if (method->NoStreaming()) {
|
|
printer->Print(
|
|
*vars,
|
|
"::grpc::Status $ns$$Service$::Service::$Method$("
|
|
"::grpc::ServerContext* /*context*/, "
|
|
"const $Request$* /*request*/, $Response$* /*response*/) {\n");
|
|
printer->Print(
|
|
" return ::grpc::Status("
|
|
"::grpc::StatusCode::UNIMPLEMENTED, \"\");\n");
|
|
printer->Print("}\n\n");
|
|
} else if (ClientOnlyStreaming(method)) {
|
|
printer->Print(*vars,
|
|
"::grpc::Status $ns$$Service$::Service::$Method$("
|
|
"::grpc::ServerContext* /*context*/, "
|
|
"::grpc::ServerReader< $Request$>* /*reader*/, "
|
|
"$Response$* /*response*/) {\n");
|
|
printer->Print(
|
|
" return ::grpc::Status("
|
|
"::grpc::StatusCode::UNIMPLEMENTED, \"\");\n");
|
|
printer->Print("}\n\n");
|
|
} else if (ServerOnlyStreaming(method)) {
|
|
printer->Print(*vars,
|
|
"::grpc::Status $ns$$Service$::Service::$Method$("
|
|
"::grpc::ServerContext* /*context*/, "
|
|
"const $Request$* /*request*/, "
|
|
"::grpc::ServerWriter< $Response$>* /*writer*/) {\n");
|
|
printer->Print(
|
|
" return ::grpc::Status("
|
|
"::grpc::StatusCode::UNIMPLEMENTED, \"\");\n");
|
|
printer->Print("}\n\n");
|
|
} else if (method->BidiStreaming()) {
|
|
printer->Print(*vars,
|
|
"::grpc::Status $ns$$Service$::Service::$Method$("
|
|
"::grpc::ServerContext* /*context*/, "
|
|
"::grpc::ServerReaderWriter< $Response$, $Request$>* "
|
|
"/*stream*/) {\n");
|
|
printer->Print(
|
|
" return ::grpc::Status("
|
|
"::grpc::StatusCode::UNIMPLEMENTED, \"\");\n");
|
|
printer->Print("}\n\n");
|
|
}
|
|
}
|
|
|
|
void PrintSourceService(grpc_generator::Printer *printer,
|
|
const grpc_generator::Service *service,
|
|
std::map<grpc::string, grpc::string> *vars) {
|
|
(*vars)["Service"] = service->name();
|
|
|
|
if (service->method_count() > 0) {
|
|
printer->Print(*vars,
|
|
"static const char* $prefix$$Service$_method_names[] = {\n");
|
|
for (int i = 0; i < service->method_count(); ++i) {
|
|
(*vars)["Method"] = service->method(i).get()->name();
|
|
printer->Print(*vars, " \"/$Package$$Service$/$Method$\",\n");
|
|
}
|
|
printer->Print(*vars, "};\n\n");
|
|
}
|
|
|
|
printer->Print(*vars,
|
|
"std::unique_ptr< $ns$$Service$::Stub> $ns$$Service$::NewStub("
|
|
"const std::shared_ptr< ::grpc::ChannelInterface>& channel, "
|
|
"const ::grpc::StubOptions& /*options*/) {\n"
|
|
" std::unique_ptr< $ns$$Service$::Stub> stub(new "
|
|
"$ns$$Service$::Stub(channel));\n"
|
|
" return stub;\n"
|
|
"}\n\n");
|
|
printer->Print(*vars,
|
|
"$ns$$Service$::Stub::Stub(const std::shared_ptr< "
|
|
"::grpc::ChannelInterface>& channel)\n");
|
|
printer->Indent();
|
|
printer->Print(": channel_(channel)");
|
|
for (int i = 0; i < service->method_count(); ++i) {
|
|
auto method = service->method(i);
|
|
(*vars)["Method"] = method->name();
|
|
(*vars)["Idx"] = as_string(i);
|
|
if (method->NoStreaming()) {
|
|
(*vars)["StreamingType"] = "NORMAL_RPC";
|
|
// NOTE: There is no reason to consider streamed-unary as a separate
|
|
// category here since this part is setting up the client-side stub
|
|
// and this appears as a NORMAL_RPC from the client-side.
|
|
} else if (ClientOnlyStreaming(method.get())) {
|
|
(*vars)["StreamingType"] = "CLIENT_STREAMING";
|
|
} else if (ServerOnlyStreaming(method.get())) {
|
|
(*vars)["StreamingType"] = "SERVER_STREAMING";
|
|
} else {
|
|
(*vars)["StreamingType"] = "BIDI_STREAMING";
|
|
}
|
|
printer->Print(*vars,
|
|
", rpcmethod_$Method$_("
|
|
"$prefix$$Service$_method_names[$Idx$], "
|
|
"::grpc::internal::RpcMethod::$StreamingType$, "
|
|
"channel"
|
|
")\n");
|
|
}
|
|
printer->Print("{}\n\n");
|
|
printer->Outdent();
|
|
|
|
for (int i = 0; i < service->method_count(); ++i) {
|
|
(*vars)["Idx"] = as_string(i);
|
|
PrintSourceClientMethod(printer, service->method(i).get(), vars);
|
|
}
|
|
|
|
printer->Print(*vars, "$ns$$Service$::Service::Service() {\n");
|
|
printer->Indent();
|
|
for (int i = 0; i < service->method_count(); ++i) {
|
|
auto method = service->method(i);
|
|
(*vars)["Idx"] = as_string(i);
|
|
(*vars)["Method"] = method->name();
|
|
(*vars)["Request"] = method->input_type_name();
|
|
(*vars)["Response"] = method->output_type_name();
|
|
if (method->NoStreaming()) {
|
|
printer->Print(
|
|
*vars,
|
|
"AddMethod(new ::grpc::internal::RpcServiceMethod(\n"
|
|
" $prefix$$Service$_method_names[$Idx$],\n"
|
|
" ::grpc::internal::RpcMethod::NORMAL_RPC,\n"
|
|
" new ::grpc::internal::RpcMethodHandler< $ns$$Service$::Service, "
|
|
"$Request$, "
|
|
"$Response$>(\n"
|
|
" std::mem_fn(&$ns$$Service$::Service::$Method$), this)));\n");
|
|
} else if (ClientOnlyStreaming(method.get())) {
|
|
printer->Print(
|
|
*vars,
|
|
"AddMethod(new ::grpc::internal::RpcServiceMethod(\n"
|
|
" $prefix$$Service$_method_names[$Idx$],\n"
|
|
" ::grpc::internal::RpcMethod::CLIENT_STREAMING,\n"
|
|
" new ::grpc::internal::ClientStreamingHandler< "
|
|
"$ns$$Service$::Service, $Request$, $Response$>(\n"
|
|
" std::mem_fn(&$ns$$Service$::Service::$Method$), this)));\n");
|
|
} else if (ServerOnlyStreaming(method.get())) {
|
|
printer->Print(
|
|
*vars,
|
|
"AddMethod(new ::grpc::internal::RpcServiceMethod(\n"
|
|
" $prefix$$Service$_method_names[$Idx$],\n"
|
|
" ::grpc::internal::RpcMethod::SERVER_STREAMING,\n"
|
|
" new ::grpc::internal::ServerStreamingHandler< "
|
|
"$ns$$Service$::Service, $Request$, $Response$>(\n"
|
|
" std::mem_fn(&$ns$$Service$::Service::$Method$), this)));\n");
|
|
} else if (method->BidiStreaming()) {
|
|
printer->Print(
|
|
*vars,
|
|
"AddMethod(new ::grpc::internal::RpcServiceMethod(\n"
|
|
" $prefix$$Service$_method_names[$Idx$],\n"
|
|
" ::grpc::internal::RpcMethod::BIDI_STREAMING,\n"
|
|
" new ::grpc::internal::BidiStreamingHandler< "
|
|
"$ns$$Service$::Service, $Request$, $Response$>(\n"
|
|
" std::mem_fn(&$ns$$Service$::Service::$Method$), this)));\n");
|
|
}
|
|
}
|
|
printer->Outdent();
|
|
printer->Print(*vars, "}\n\n");
|
|
printer->Print(*vars,
|
|
"$ns$$Service$::Service::~Service() {\n"
|
|
"}\n\n");
|
|
for (int i = 0; i < service->method_count(); ++i) {
|
|
(*vars)["Idx"] = as_string(i);
|
|
PrintSourceServerMethod(printer, service->method(i).get(), vars);
|
|
}
|
|
}
|
|
|
|
grpc::string GetSourceServices(grpc_generator::File *file,
|
|
const Parameters ¶ms) {
|
|
grpc::string output;
|
|
{
|
|
// Scope the output stream so it closes and finalizes output to the string.
|
|
auto printer = file->CreatePrinter(&output);
|
|
std::map<grpc::string, grpc::string> vars;
|
|
// Package string is empty or ends with a dot. It is used to fully qualify
|
|
// method names.
|
|
vars["Package"] = file->package();
|
|
if (!file->package().empty()) { vars["Package"].append("."); }
|
|
if (!params.services_namespace.empty()) {
|
|
vars["ns"] = params.services_namespace + "::";
|
|
vars["prefix"] = params.services_namespace;
|
|
} else {
|
|
vars["ns"] = "";
|
|
vars["prefix"] = "";
|
|
}
|
|
|
|
for (int i = 0; i < file->service_count(); ++i) {
|
|
PrintSourceService(printer.get(), file->service(i).get(), &vars);
|
|
printer->Print("\n");
|
|
}
|
|
}
|
|
return output;
|
|
}
|
|
|
|
grpc::string GetSourceEpilogue(grpc_generator::File *file,
|
|
const Parameters & /*params*/) {
|
|
grpc::string temp;
|
|
|
|
if (!file->package().empty()) {
|
|
std::vector<grpc::string> parts = file->package_parts();
|
|
|
|
for (auto part = parts.begin(); part != parts.end(); part++) {
|
|
temp.append("} // namespace ");
|
|
temp.append(*part);
|
|
temp.append("\n");
|
|
}
|
|
temp.append("\n");
|
|
}
|
|
|
|
return temp;
|
|
}
|
|
|
|
grpc::string GetMockPrologue(grpc_generator::File *file,
|
|
const Parameters ¶ms) {
|
|
grpc::string output;
|
|
{
|
|
// Scope the output stream so it closes and finalizes output to the string.
|
|
auto printer = file->CreatePrinter(&output);
|
|
std::map<grpc::string, grpc::string> vars;
|
|
|
|
vars["filename"] = file->filename();
|
|
vars["filename_base"] = file->filename_without_ext();
|
|
vars["message_header_ext"] = params.message_header_extension;
|
|
vars["service_header_ext"] = service_header_ext();
|
|
|
|
printer->Print(vars, "// Generated by the gRPC C++ plugin.\n");
|
|
printer->Print(vars,
|
|
"// If you make any local change, they will be lost.\n");
|
|
printer->Print(vars, "// source: $filename$\n\n");
|
|
|
|
printer->Print(vars, "#include \"$filename_base$$message_header_ext$\"\n");
|
|
printer->Print(vars, "#include \"$filename_base$$service_header_ext$\"\n");
|
|
printer->Print(vars, file->additional_headers().c_str());
|
|
printer->Print(vars, "\n");
|
|
}
|
|
return output;
|
|
}
|
|
|
|
// TODO(mmukhi): Add client-stream and completion-queue headers.
|
|
grpc::string GetMockIncludes(grpc_generator::File *file,
|
|
const Parameters ¶ms) {
|
|
grpc::string output;
|
|
{
|
|
// Scope the output stream so it closes and finalizes output to the string.
|
|
auto printer = file->CreatePrinter(&output);
|
|
std::map<grpc::string, grpc::string> vars;
|
|
|
|
static const char *headers_strs[] = {
|
|
"grpcpp/impl/codegen/async_stream.h",
|
|
"grpcpp/impl/codegen/sync_stream.h",
|
|
"gmock/gmock.h",
|
|
};
|
|
std::vector<grpc::string> headers(headers_strs, array_end(headers_strs));
|
|
PrintIncludes(printer.get(), headers, params);
|
|
|
|
if (!file->package().empty()) {
|
|
std::vector<grpc::string> parts = file->package_parts();
|
|
|
|
for (auto part = parts.begin(); part != parts.end(); part++) {
|
|
vars["part"] = *part;
|
|
printer->Print(vars, "namespace $part$ {\n");
|
|
}
|
|
}
|
|
|
|
printer->Print(vars, "\n");
|
|
}
|
|
return output;
|
|
}
|
|
|
|
void PrintMockClientMethods(grpc_generator::Printer *printer,
|
|
const grpc_generator::Method *method,
|
|
std::map<grpc::string, grpc::string> *vars) {
|
|
(*vars)["Method"] = method->name();
|
|
(*vars)["Request"] = method->input_type_name();
|
|
(*vars)["Response"] = method->output_type_name();
|
|
|
|
struct {
|
|
grpc::string prefix;
|
|
grpc::string method_params; // extra arguments to method
|
|
int extra_method_param_count;
|
|
} async_prefixes[] = { { "Async", ", void* tag", 1 },
|
|
{ "PrepareAsync", "", 0 } };
|
|
|
|
if (method->NoStreaming()) {
|
|
printer->Print(
|
|
*vars,
|
|
"MOCK_METHOD3($Method$, ::grpc::Status(::grpc::ClientContext* context, "
|
|
"const $Request$& request, $Response$* response));\n");
|
|
for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
|
|
i++) {
|
|
auto &async_prefix = async_prefixes[i];
|
|
(*vars)["AsyncPrefix"] = async_prefix.prefix;
|
|
printer->Print(
|
|
*vars,
|
|
"MOCK_METHOD3($AsyncPrefix$$Method$Raw, "
|
|
"::grpc::ClientAsyncResponseReaderInterface< $Response$>*"
|
|
"(::grpc::ClientContext* context, const $Request$& request, "
|
|
"::grpc::CompletionQueue* cq));\n");
|
|
}
|
|
} else if (ClientOnlyStreaming(method)) {
|
|
printer->Print(
|
|
*vars,
|
|
"MOCK_METHOD2($Method$Raw, "
|
|
"::grpc::ClientWriterInterface< $Request$>*"
|
|
"(::grpc::ClientContext* context, $Response$* response));\n");
|
|
for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
|
|
i++) {
|
|
auto &async_prefix = async_prefixes[i];
|
|
(*vars)["AsyncPrefix"] = async_prefix.prefix;
|
|
(*vars)["AsyncMethodParams"] = async_prefix.method_params;
|
|
(*vars)["MockArgs"] =
|
|
flatbuffers::NumToString(3 + async_prefix.extra_method_param_count);
|
|
printer->Print(*vars,
|
|
"MOCK_METHOD$MockArgs$($AsyncPrefix$$Method$Raw, "
|
|
"::grpc::ClientAsyncWriterInterface< $Request$>*"
|
|
"(::grpc::ClientContext* context, $Response$* response, "
|
|
"::grpc::CompletionQueue* cq$AsyncMethodParams$));\n");
|
|
}
|
|
} else if (ServerOnlyStreaming(method)) {
|
|
printer->Print(
|
|
*vars,
|
|
"MOCK_METHOD2($Method$Raw, "
|
|
"::grpc::ClientReaderInterface< $Response$>*"
|
|
"(::grpc::ClientContext* context, const $Request$& request));\n");
|
|
for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
|
|
i++) {
|
|
auto &async_prefix = async_prefixes[i];
|
|
(*vars)["AsyncPrefix"] = async_prefix.prefix;
|
|
(*vars)["AsyncMethodParams"] = async_prefix.method_params;
|
|
(*vars)["MockArgs"] =
|
|
flatbuffers::NumToString(3 + async_prefix.extra_method_param_count);
|
|
printer->Print(
|
|
*vars,
|
|
"MOCK_METHOD$MockArgs$($AsyncPrefix$$Method$Raw, "
|
|
"::grpc::ClientAsyncReaderInterface< $Response$>*"
|
|
"(::grpc::ClientContext* context, const $Request$& request, "
|
|
"::grpc::CompletionQueue* cq$AsyncMethodParams$));\n");
|
|
}
|
|
} else if (method->BidiStreaming()) {
|
|
printer->Print(
|
|
*vars,
|
|
"MOCK_METHOD1($Method$Raw, "
|
|
"::grpc::ClientReaderWriterInterface< $Request$, $Response$>*"
|
|
"(::grpc::ClientContext* context));\n");
|
|
for (size_t i = 0; i < sizeof(async_prefixes) / sizeof(async_prefixes[0]);
|
|
i++) {
|
|
auto &async_prefix = async_prefixes[i];
|
|
(*vars)["AsyncPrefix"] = async_prefix.prefix;
|
|
(*vars)["AsyncMethodParams"] = async_prefix.method_params;
|
|
(*vars)["MockArgs"] =
|
|
flatbuffers::NumToString(2 + async_prefix.extra_method_param_count);
|
|
printer->Print(
|
|
*vars,
|
|
"MOCK_METHOD$MockArgs$($AsyncPrefix$$Method$Raw, "
|
|
"::grpc::ClientAsyncReaderWriterInterface<$Request$, $Response$>*"
|
|
"(::grpc::ClientContext* context, ::grpc::CompletionQueue* cq"
|
|
"$AsyncMethodParams$));\n");
|
|
}
|
|
}
|
|
}
|
|
|
|
void PrintMockService(grpc_generator::Printer *printer,
|
|
const grpc_generator::Service *service,
|
|
std::map<grpc::string, grpc::string> *vars) {
|
|
(*vars)["Service"] = service->name();
|
|
|
|
printer->Print(*vars,
|
|
"class Mock$Service$Stub : public $Service$::StubInterface {\n"
|
|
" public:\n");
|
|
printer->Indent();
|
|
for (int i = 0; i < service->method_count(); ++i) {
|
|
PrintMockClientMethods(printer, service->method(i).get(), vars);
|
|
}
|
|
printer->Outdent();
|
|
printer->Print("};\n");
|
|
}
|
|
|
|
grpc::string GetMockServices(grpc_generator::File *file,
|
|
const Parameters ¶ms) {
|
|
grpc::string output;
|
|
{
|
|
// Scope the output stream so it closes and finalizes output to the string.
|
|
auto printer = file->CreatePrinter(&output);
|
|
std::map<grpc::string, grpc::string> vars;
|
|
// Package string is empty or ends with a dot. It is used to fully qualify
|
|
// method names.
|
|
vars["Package"] = file->package();
|
|
if (!file->package().empty()) { vars["Package"].append("."); }
|
|
|
|
if (!params.services_namespace.empty()) {
|
|
vars["services_namespace"] = params.services_namespace;
|
|
printer->Print(vars, "\nnamespace $services_namespace$ {\n\n");
|
|
}
|
|
|
|
for (int i = 0; i < file->service_count(); i++) {
|
|
PrintMockService(printer.get(), file->service(i).get(), &vars);
|
|
printer->Print("\n");
|
|
}
|
|
|
|
if (!params.services_namespace.empty()) {
|
|
printer->Print(vars, "} // namespace $services_namespace$\n\n");
|
|
}
|
|
}
|
|
return output;
|
|
}
|
|
|
|
grpc::string GetMockEpilogue(grpc_generator::File *file,
|
|
const Parameters & /*params*/) {
|
|
grpc::string temp;
|
|
|
|
if (!file->package().empty()) {
|
|
std::vector<grpc::string> parts = file->package_parts();
|
|
|
|
for (auto part = parts.begin(); part != parts.end(); part++) {
|
|
temp.append("} // namespace ");
|
|
temp.append(*part);
|
|
temp.append("\n");
|
|
}
|
|
temp.append("\n");
|
|
}
|
|
|
|
return temp;
|
|
}
|
|
|
|
} // namespace grpc_cpp_generator
|