diff options
author | max42 <max42@yandex-team.com> | 2023-06-30 03:37:03 +0300 |
---|---|---|
committer | max42 <max42@yandex-team.com> | 2023-06-30 03:37:03 +0300 |
commit | fac2bd72b4b31ec3238292caf8fb2a8aaa6d6c4a (patch) | |
tree | b8cbc1deb00309c7f1a7ab6df520a76cf0b5c6d7 /contrib/libs/flatbuffers/grpc/src/compiler | |
parent | 7bf166b1a7ed0af927f230022b245af618e998c1 (diff) | |
download | ydb-fac2bd72b4b31ec3238292caf8fb2a8aaa6d6c4a.tar.gz |
YT-19324: move YT provider to ydb/library/yql
This commit is formed by the following script: https://paste.yandex-team.ru/6f92e4b8-efc5-4d34-948b-15ee2accd7e7/text.
This commit has zero effect on all projects that depend on YQL.
The summary of changes:
- `yql/providers/yt -> ydb/library/yql/providers/yt `- the whole implementation of YT provider is moved into YDB code base for further export as a part of YT YQL plugin shared library;
- `yql/providers/stat/{expr_nodes,uploader} -> ydb/library/yql/providers/stat/{expr_nodes,uploader}` - a small interface without implementation and the description of stat expr nodes;
- `yql/core/extract_predicate/ut -> ydb/library/yql/core/extract_predicate/ut`;
- `yql/core/{ut,ut_common} -> ydb/library/yql/core/{ut,ut_common}`;
- `yql/core` is gone;
- `yql/library/url_preprocessing -> ydb/library/yql/core/url_preprocessing`.
**NB**: all new targets inside `ydb/` are under `IF (NOT CMAKE_EXPORT)` clause which disables them from open-source cmake generation and ya make build. They will be enabled in the subsequent commits.
Diffstat (limited to 'contrib/libs/flatbuffers/grpc/src/compiler')
14 files changed, 5122 insertions, 0 deletions
diff --git a/contrib/libs/flatbuffers/grpc/src/compiler/config.h b/contrib/libs/flatbuffers/grpc/src/compiler/config.h new file mode 100644 index 0000000000..4adc594377 --- /dev/null +++ b/contrib/libs/flatbuffers/grpc/src/compiler/config.h @@ -0,0 +1,40 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef SRC_COMPILER_CONFIG_H +#define SRC_COMPILER_CONFIG_H + +// This file is here only because schema_interface.h, which is copied from gRPC, +// includes it. There is nothing for Flatbuffers to configure. + +#endif // SRC_COMPILER_CONFIG_H diff --git a/contrib/libs/flatbuffers/grpc/src/compiler/cpp_generator.cc b/contrib/libs/flatbuffers/grpc/src/compiler/cpp_generator.cc new file mode 100644 index 0000000000..8dd408830c --- /dev/null +++ b/contrib/libs/flatbuffers/grpc/src/compiler/cpp_generator.cc @@ -0,0 +1,1780 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include <map> + +#include "src/compiler/cpp_generator.h" +#include "flatbuffers/util.h" + +#include <sstream> + +namespace grpc_cpp_generator { +namespace { + +grpc::string message_header_ext() { return "_generated.h"; } +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 & /*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()); + vars["filename_base"] = file->filename_without_ext(); + vars["message_header_ext"] = message_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"); + 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 & /*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_base"] = file->filename_without_ext(); + vars["message_header_ext"] = message_header_ext(); + 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(" (void) context;\n"); + printer->Print(" (void) request;\n"); + printer->Print(" (void) 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(" (void) context;\n"); + printer->Print(" (void) reader;\n"); + printer->Print(" (void) 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(" (void) context;\n"); + printer->Print(" (void) request;\n"); + printer->Print(" (void) 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(" (void) context;\n"); + printer->Print(" (void) 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; +} + +// TODO(mmukhi): Make sure we need parameters or not. +grpc::string GetMockPrologue(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_base"] = file->filename_without_ext(); + vars["message_header_ext"] = message_header_ext(); + 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 diff --git a/contrib/libs/flatbuffers/grpc/src/compiler/cpp_generator.h b/contrib/libs/flatbuffers/grpc/src/compiler/cpp_generator.h new file mode 100644 index 0000000000..6119ebe289 --- /dev/null +++ b/contrib/libs/flatbuffers/grpc/src/compiler/cpp_generator.h @@ -0,0 +1,138 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef GRPC_INTERNAL_COMPILER_CPP_GENERATOR_H +#define GRPC_INTERNAL_COMPILER_CPP_GENERATOR_H + +// cpp_generator.h/.cc do not directly depend on GRPC/ProtoBuf, such that they +// can be used to generate code for other serialization systems, such as +// FlatBuffers. + +#include <memory> +#include <vector> + +#include "src/compiler/config.h" +#include "src/compiler/schema_interface.h" + +#ifndef GRPC_CUSTOM_STRING +#include <string> +#define GRPC_CUSTOM_STRING std::string +#endif + +namespace grpc { + +typedef GRPC_CUSTOM_STRING string; + +} // namespace grpc + +namespace grpc_cpp_generator { + +// Contains all the parameters that are parsed from the command line. +struct Parameters { + // Puts the service into a namespace + grpc::string services_namespace; + // Use system includes (<>) or local includes ("") + bool use_system_headers; + // Prefix to any grpc include + grpc::string grpc_search_path; + // Generate GMOCK code to facilitate unit testing. + bool generate_mock_code; +}; + +// Return the prologue of the generated header file. +grpc::string GetHeaderPrologue(grpc_generator::File *file, + const Parameters ¶ms); + +// Return the includes needed for generated header file. +grpc::string GetHeaderIncludes(grpc_generator::File *file, + const Parameters ¶ms); + +// Return the includes needed for generated source file. +grpc::string GetSourceIncludes(grpc_generator::File *file, + const Parameters ¶ms); + +// Return the epilogue of the generated header file. +grpc::string GetHeaderEpilogue(grpc_generator::File *file, + const Parameters ¶ms); + +// Return the prologue of the generated source file. +grpc::string GetSourcePrologue(grpc_generator::File *file, + const Parameters ¶ms); + +// Return the services for generated header file. +grpc::string GetHeaderServices(grpc_generator::File *file, + const Parameters ¶ms); + +// Return the services for generated source file. +grpc::string GetSourceServices(grpc_generator::File *file, + const Parameters ¶ms); + +// Return the epilogue of the generated source file. +grpc::string GetSourceEpilogue(grpc_generator::File *file, + const Parameters ¶ms); + +// Return the prologue of the generated mock file. +grpc::string GetMockPrologue(grpc_generator::File *file, + const Parameters ¶ms); + +// Return the includes needed for generated mock file. +grpc::string GetMockIncludes(grpc_generator::File *file, + const Parameters ¶ms); + +// Return the services for generated mock file. +grpc::string GetMockServices(grpc_generator::File *file, + const Parameters ¶ms); + +// Return the epilogue of generated mock file. +grpc::string GetMockEpilogue(grpc_generator::File *file, + const Parameters ¶ms); + +// Return the prologue of the generated mock file. +grpc::string GetMockPrologue(grpc_generator::File *file, + const Parameters ¶ms); + +// Return the includes needed for generated mock file. +grpc::string GetMockIncludes(grpc_generator::File *file, + const Parameters ¶ms); + +// Return the services for generated mock file. +grpc::string GetMockServices(grpc_generator::File *file, + const Parameters ¶ms); + +// Return the epilogue of generated mock file. +grpc::string GetMockEpilogue(grpc_generator::File *file, + const Parameters ¶ms); + +} // namespace grpc_cpp_generator + +#endif // GRPC_INTERNAL_COMPILER_CPP_GENERATOR_H diff --git a/contrib/libs/flatbuffers/grpc/src/compiler/go_generator.cc b/contrib/libs/flatbuffers/grpc/src/compiler/go_generator.cc new file mode 100644 index 0000000000..d646451aa6 --- /dev/null +++ b/contrib/libs/flatbuffers/grpc/src/compiler/go_generator.cc @@ -0,0 +1,501 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation AN/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include <map> +#include <cctype> +#include <sstream> + +#include "src/compiler/go_generator.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(); +} + +namespace grpc_go_generator { + +// Returns string with first letter to lowerCase +grpc::string unexportName(grpc::string s) { + if (s.empty()) + return s; + s[0] = static_cast<char>(std::tolower(s[0])); + return s; +} + +// Returns string with first letter to uppercase +grpc::string exportName(grpc::string s) { + if (s.empty()) + return s; + s[0] = static_cast<char>(std::toupper(s[0])); + return s; +} + +void GenerateError(grpc_generator::Printer *printer, + std::map<grpc::string, grpc::string> vars, + const bool multiple_return = true) { + printer->Print(vars, "if $Error_Check$ {\n"); + printer->Indent(); + vars["Return"] = multiple_return ? "nil, err" : "err"; + printer->Print(vars, "return $Return$\n"); + printer->Outdent(); + printer->Print("}\n"); +} + +// Generates imports for the service +void GenerateImports(grpc_generator::File *file, grpc_generator::Printer *printer, + std::map<grpc::string, grpc::string> vars) { + vars["filename"] = file->filename(); + printer->Print("//Generated by gRPC Go plugin\n"); + printer->Print("//If you make any local changes, they will be lost\n"); + printer->Print(vars, "//source: $filename$\n\n"); + printer->Print(vars, "package $Package$\n\n"); + printer->Print("import (\n"); + printer->Indent(); + printer->Print(vars, "$context$ \"context\"\n"); + printer->Print("flatbuffers \"github.com/google/flatbuffers/go\"\n"); + printer->Print(vars, "$grpc$ \"google.golang.org/grpc\"\n"); + printer->Print("\"google.golang.org/grpc/codes\"\n"); + printer->Print("\"google.golang.org/grpc/status\"\n"); + printer->Outdent(); + printer->Print(")\n\n"); +} + +// Generates Server method signature source +void GenerateServerMethodSignature(const grpc_generator::Method *method, grpc_generator::Printer *printer, + std::map<grpc::string, grpc::string> vars) { + vars["Method"] = exportName(method->name()); + vars["Request"] = method->get_input_type_name(); + vars["Response"] = (vars["CustomMethodIO"] == "") ? method->get_output_type_name() : vars["CustomMethodIO"]; + if (method->NoStreaming()) { + printer->Print(vars, "$Method$($context$.Context, *$Request$) (*$Response$, error)$Ending$"); + } else if (ServerOnlyStreaming(method)) { + printer->Print(vars, "$Method$(*$Request$, $Service$_$Method$Server) error$Ending$"); + } else { + printer->Print(vars, "$Method$($Service$_$Method$Server) error$Ending$"); + } +} + +void GenerateServerMethod(const grpc_generator::Method *method, grpc_generator::Printer *printer, + std::map<grpc::string, grpc::string> vars) { + vars["Method"] = exportName(method->name()); + vars["Request"] = method->get_input_type_name(); + vars["Response"] = (vars["CustomMethodIO"] == "") ? method->get_output_type_name() : vars["CustomMethodIO"]; + vars["FullMethodName"] = "/" + vars["ServicePrefix"] + vars["Service"] + "/" + vars["Method"]; + vars["Handler"] = "_" + vars["Service"] + "_" + vars["Method"] + "_Handler"; + if (method->NoStreaming()) { + printer->Print(vars, "func $Handler$(srv interface{}, ctx $context$.Context,\n\tdec func(interface{}) error, interceptor $grpc$.UnaryServerInterceptor) (interface{}, error) {\n"); + printer->Indent(); + printer->Print(vars, "in := new($Request$)\n"); + vars["Error_Check"] = "err := dec(in); err != nil"; + GenerateError(printer, vars); + printer->Print("if interceptor == nil {\n"); + printer->Indent(); + printer->Print(vars, "return srv.($Service$Server).$Method$(ctx, in)\n"); + printer->Outdent(); + printer->Print("}\n"); + printer->Print(vars, "info := &$grpc$.UnaryServerInfo{\n"); + printer->Indent(); + printer->Print("Server: srv,\n"); + printer->Print(vars, "FullMethod: \"$FullMethodName$\",\n"); + printer->Outdent(); + printer->Print("}\n"); + printer->Outdent(); + printer->Print("\n"); + printer->Indent(); + printer->Print(vars, "handler := func(ctx $context$.Context, req interface{}) (interface{}, error) {\n"); + printer->Indent(); + printer->Print(vars, "return srv.($Service$Server).$Method$(ctx, req.(*$Request$))\n"); + printer->Outdent(); + printer->Print("}\n"); + printer->Print("return interceptor(ctx, in, info, handler)\n"); + printer->Outdent(); + printer->Print("}\n"); + return; + } + vars["StreamType"] = vars["ServiceUnexported"] + vars["Method"] + "Server"; + printer->Print(vars, "func $Handler$(srv interface{}, stream $grpc$.ServerStream) error {\n"); + printer->Indent(); + if (ServerOnlyStreaming(method)) { + printer->Print(vars, "m := new($Request$)\n"); + vars["Error_Check"] = "err := stream.RecvMsg(m); err != nil"; + GenerateError(printer, vars, false); + printer->Print(vars, "return srv.($Service$Server).$Method$(m, &$StreamType${stream})\n"); + } else { + printer->Print(vars, "return srv.($Service$Server).$Method$(&$StreamType${stream})\n"); + } + printer->Outdent(); + printer->Print("}\n\n"); + + bool genSend = method->BidiStreaming() || ServerOnlyStreaming(method); + bool genRecv = method->BidiStreaming() || ClientOnlyStreaming(method); + bool genSendAndClose = ClientOnlyStreaming(method); + + printer->Print(vars, "type $Service$_$Method$Server interface {\n"); + printer->Indent(); + if (genSend) { + printer->Print(vars, "Send(*$Response$) error\n"); + } + if (genRecv) { + printer->Print(vars, "Recv() (*$Request$, error)\n"); + } + if (genSendAndClose) { + printer->Print(vars, "SendAndClose(*$Response$) error\n"); + } + printer->Print(vars, "$grpc$.ServerStream\n"); + printer->Outdent(); + printer->Print("}\n\n"); + + printer->Print(vars, "type $StreamType$ struct {\n"); + printer->Indent(); + printer->Print(vars, "$grpc$.ServerStream\n"); + printer->Outdent(); + printer->Print("}\n\n"); + + if (genSend) { + printer->Print(vars, "func (x *$StreamType$) Send(m *$Response$) error {\n"); + printer->Indent(); + printer->Print("return x.ServerStream.SendMsg(m)\n"); + printer->Outdent(); + printer->Print("}\n\n"); + } + if (genRecv) { + printer->Print(vars, "func (x *$StreamType$) Recv() (*$Request$, error) {\n"); + printer->Indent(); + printer->Print(vars, "m := new($Request$)\n"); + vars["Error_Check"] = "err := x.ServerStream.RecvMsg(m); err != nil"; + GenerateError(printer, vars); + printer->Print("return m, nil\n"); + printer->Outdent(); + printer->Print("}\n\n"); + } + if (genSendAndClose) { + printer->Print(vars, "func (x *$StreamType$) SendAndClose(m *$Response$) error {\n"); + printer->Indent(); + printer->Print("return x.ServerStream.SendMsg(m)\n"); + printer->Outdent(); + printer->Print("}\n\n"); + } + +} + +// Generates Client method signature source +void GenerateClientMethodSignature(const grpc_generator::Method *method, grpc_generator::Printer *printer, + std::map<grpc::string, grpc::string> vars) { + vars["Method"] = exportName(method->name()); + vars["Request"] = ", in *" + ((vars["CustomMethodIO"] == "") ? method->get_input_type_name() : vars["CustomMethodIO"]); + if (ClientOnlyStreaming(method) || method->BidiStreaming()) { + vars["Request"] = ""; + } + vars["Response"] = "*" + method->get_output_type_name(); + if (ClientOnlyStreaming(method) || method->BidiStreaming() || ServerOnlyStreaming(method)) { + vars["Response"] = vars["Service"] + "_" + vars["Method"] + "Client" ; + } + printer->Print(vars, "$Method$(ctx $context$.Context$Request$,\n\topts ...$grpc$.CallOption) ($Response$, error)$Ending$"); +} + +// Generates Client method source +void GenerateClientMethod(const grpc_generator::Method *method, grpc_generator::Printer *printer, + std::map<grpc::string, grpc::string> vars) { + printer->Print(vars, "func (c *$ServiceUnexported$Client) "); + vars["Ending"] = " {\n"; + GenerateClientMethodSignature(method, printer, vars); + printer->Indent(); + vars["Method"] = exportName(method->name()); + vars["Request"] = (vars["CustomMethodIO"] == "") ? method->get_input_type_name() : vars["CustomMethodIO"]; + vars["Response"] = method->get_output_type_name(); + vars["FullMethodName"] = "/" + vars["ServicePrefix"] + vars["Service"] + "/" + vars["Method"]; + if (method->NoStreaming()) { + printer->Print(vars, "out := new($Response$)\n"); + printer->Print(vars, "err := c.cc.Invoke(ctx, \"$FullMethodName$\", in, out, opts...)\n"); + vars["Error_Check"] = "err != nil"; + GenerateError(printer, vars); + printer->Print("return out, nil\n"); + printer->Outdent(); + printer->Print("}\n\n"); + return; + } + vars["StreamType"] = vars["ServiceUnexported"] + vars["Method"] + "Client"; + printer->Print(vars, "stream, err := c.cc.NewStream(ctx, &$MethodDesc$, \"$FullMethodName$\", opts...)\n"); + vars["Error_Check"] = "err != nil"; + GenerateError(printer, vars); + + printer->Print(vars, "x := &$StreamType${stream}\n"); + if (ServerOnlyStreaming(method)) { + vars["Error_Check"] = "err := x.ClientStream.SendMsg(in); err != nil"; + GenerateError(printer, vars); + vars["Error_Check"] = "err := x.ClientStream.CloseSend(); err != nil"; + GenerateError(printer, vars); + } + printer->Print("return x, nil\n"); + printer->Outdent(); + printer->Print("}\n\n"); + + bool genSend = method->BidiStreaming() || ClientOnlyStreaming(method); + bool genRecv = method->BidiStreaming() || ServerOnlyStreaming(method); + bool genCloseAndRecv = ClientOnlyStreaming(method); + + //Stream interface + printer->Print(vars, "type $Service$_$Method$Client interface {\n"); + printer->Indent(); + if (genSend) { + printer->Print(vars, "Send(*$Request$) error\n"); + } + if (genRecv) { + printer->Print(vars, "Recv() (*$Response$, error)\n"); + } + if (genCloseAndRecv) { + printer->Print(vars, "CloseAndRecv() (*$Response$, error)\n"); + } + printer->Print(vars, "$grpc$.ClientStream\n"); + printer->Outdent(); + printer->Print("}\n\n"); + + //Stream Client + printer->Print(vars, "type $StreamType$ struct {\n"); + printer->Indent(); + printer->Print(vars, "$grpc$.ClientStream\n"); + printer->Outdent(); + printer->Print("}\n\n"); + + if (genSend) { + printer->Print(vars, "func (x *$StreamType$) Send(m *$Request$) error {\n"); + printer->Indent(); + printer->Print("return x.ClientStream.SendMsg(m)\n"); + printer->Outdent(); + printer->Print("}\n\n"); + } + + if (genRecv) { + printer->Print(vars, "func (x *$StreamType$) Recv() (*$Response$, error) {\n"); + printer->Indent(); + printer->Print(vars, "m := new($Response$)\n"); + vars["Error_Check"] = "err := x.ClientStream.RecvMsg(m); err != nil"; + GenerateError(printer, vars); + printer->Print("return m, nil\n"); + printer->Outdent(); + printer->Print("}\n\n"); + } + + if (genCloseAndRecv) { + printer->Print(vars, "func (x *$StreamType$) CloseAndRecv() (*$Response$, error) {\n"); + printer->Indent(); + vars["Error_Check"] = "err := x.ClientStream.CloseSend(); err != nil"; + GenerateError(printer, vars); + printer->Print(vars, "m := new($Response$)\n"); + vars["Error_Check"] = "err := x.ClientStream.RecvMsg(m); err != nil"; + GenerateError(printer, vars); + printer->Print("return m, nil\n"); + printer->Outdent(); + printer->Print("}\n\n"); + } +} + +// Generates client API for the service +void GenerateService(const grpc_generator::Service *service, grpc_generator::Printer* printer, + std::map<grpc::string, grpc::string> vars) { + vars["Service"] = exportName(service->name()); + // Client Interface + printer->Print(vars, "// Client API for $Service$ service\n"); + printer->Print(vars, "type $Service$Client interface {\n"); + printer->Indent(); + vars["Ending"] = "\n"; + for (int i = 0; i < service->method_count(); i++) { + GenerateClientMethodSignature(service->method(i).get(), printer, vars); + } + printer->Outdent(); + printer->Print("}\n\n"); + + // Client structure + vars["ServiceUnexported"] = unexportName(vars["Service"]); + printer->Print(vars, "type $ServiceUnexported$Client struct {\n"); + printer->Indent(); + printer->Print(vars, "cc $grpc$.ClientConnInterface\n"); + printer->Outdent(); + printer->Print("}\n\n"); + + // NewClient + printer->Print(vars, "func New$Service$Client(cc $grpc$.ClientConnInterface) $Service$Client {\n"); + printer->Indent(); + printer->Print(vars, "return &$ServiceUnexported$Client{cc}"); + printer->Outdent(); + printer->Print("\n}\n\n"); + + int unary_methods = 0, streaming_methods = 0; + vars["ServiceDesc"] = "_" + vars["Service"] + "_serviceDesc"; + for (int i = 0; i < service->method_count(); i++) { + auto method = service->method(i); + if (method->NoStreaming()) { + vars["MethodDesc"] = vars["ServiceDesc"] + ".Method[" + as_string(unary_methods) + "]"; + unary_methods++; + } else { + vars["MethodDesc"] = vars["ServiceDesc"] + ".Streams[" + as_string(streaming_methods) + "]"; + streaming_methods++; + } + GenerateClientMethod(method.get(), printer, vars); + } + + //Server Interface + printer->Print(vars, "// Server API for $Service$ service\n"); + printer->Print(vars, "type $Service$Server interface {\n"); + printer->Indent(); + vars["Ending"] = "\n"; + for (int i = 0; i < service->method_count(); i++) { + GenerateServerMethodSignature(service->method(i).get(), printer, vars); + } + printer->Print(vars, "mustEmbedUnimplemented$Service$Server()\n"); + printer->Outdent(); + printer->Print("}\n\n"); + + printer->Print(vars, "type Unimplemented$Service$Server struct {\n"); + printer->Print("}\n\n"); + + vars["Ending"] = " {\n"; + for (int i = 0; i < service->method_count(); i++) { + auto method = service->method(i); + vars["Method"] = exportName(method->name()); + vars["Nil"] = method->NoStreaming() ? "nil, " : ""; + printer->Print(vars, "func (Unimplemented$Service$Server) "); + GenerateServerMethodSignature(method.get(), printer, vars); + printer->Indent(); + printer->Print(vars, "return $Nil$status.Errorf(codes.Unimplemented, \"method $Method$ not implemented\")\n"); + printer->Outdent(); + printer->Print("}\n"); + printer->Print("\n"); + } + + printer->Print(vars, "func (Unimplemented$Service$Server) mustEmbedUnimplemented$Service$Server() {}"); + printer->Print("\n\n"); + + printer->Print(vars, "type Unsafe$Service$Server interface {\n"); + printer->Indent(); + printer->Print(vars, "mustEmbedUnimplemented$Service$Server()\n"); + printer->Outdent(); + printer->Print("}\n\n"); + // Server registration. + printer->Print(vars, "func Register$Service$Server(s $grpc$.ServiceRegistrar, srv $Service$Server) {\n"); + printer->Indent(); + printer->Print(vars, "s.RegisterService(&$ServiceDesc$, srv)\n"); + printer->Outdent(); + printer->Print("}\n\n"); + + for (int i = 0; i < service->method_count(); i++) { + GenerateServerMethod(service->method(i).get(), printer, vars); + } + + + //Service Descriptor + printer->Print(vars, "var $ServiceDesc$ = $grpc$.ServiceDesc{\n"); + printer->Indent(); + printer->Print(vars, "ServiceName: \"$ServicePrefix$$Service$\",\n"); + printer->Print(vars, "HandlerType: (*$Service$Server)(nil),\n"); + printer->Print(vars, "Methods: []$grpc$.MethodDesc{\n"); + printer->Indent(); + for (int i = 0; i < service->method_count(); i++) { + auto method = service->method(i); + vars["Method"] = exportName(method->name()); + vars["Handler"] = "_" + vars["Service"] + "_" + vars["Method"] + "_Handler"; + if (method->NoStreaming()) { + printer->Print("{\n"); + printer->Indent(); + printer->Print(vars, "MethodName: \"$Method$\",\n"); + printer->Print(vars, "Handler: $Handler$,\n"); + printer->Outdent(); + printer->Print("},\n"); + } + } + printer->Outdent(); + printer->Print("},\n"); + printer->Print(vars, "Streams: []$grpc$.StreamDesc{\n"); + printer->Indent(); + for (int i = 0; i < service->method_count(); i++) { + auto method = service->method(i); + vars["Method"] = exportName(method->name()); + vars["Handler"] = "_" + vars["Service"] + "_" + vars["Method"] + "_Handler"; + if (!method->NoStreaming()) { + printer->Print("{\n"); + printer->Indent(); + printer->Print(vars, "StreamName: \"$Method$\",\n"); + printer->Print(vars, "Handler: $Handler$,\n"); + if (ClientOnlyStreaming(method.get())) { + printer->Print("ClientStreams: true,\n"); + } else if (ServerOnlyStreaming(method.get())) { + printer->Print("ServerStreams: true,\n"); + } else { + printer->Print("ServerStreams: true,\n"); + printer->Print("ClientStreams: true,\n"); + } + printer->Outdent(); + printer->Print("},\n"); + } + } + printer->Outdent(); + printer->Print("},\n"); + printer->Outdent(); + printer->Print("}\n"); + +} + + +// Returns source for the service +grpc::string GenerateServiceSource(grpc_generator::File *file, + const grpc_generator::Service *service, + grpc_go_generator::Parameters *parameters) { + grpc::string out; + auto p = file->CreatePrinter(&out, '\t'); + p->SetIndentationSize(1); + auto printer = p.get(); + std::map<grpc::string, grpc::string> vars; + vars["Package"] = parameters->package_name; + vars["ServicePrefix"] = parameters->service_prefix; + if (!parameters->service_prefix.empty()) + vars["ServicePrefix"].append("."); + vars["grpc"] = "grpc"; + vars["context"] = "context"; + GenerateImports(file, printer, vars); + if (parameters->custom_method_io_type != "") { + vars["CustomMethodIO"] = parameters->custom_method_io_type; + } + GenerateService(service, printer, vars); + return out; +} +}// Namespace grpc_go_generator diff --git a/contrib/libs/flatbuffers/grpc/src/compiler/go_generator.h b/contrib/libs/flatbuffers/grpc/src/compiler/go_generator.h new file mode 100644 index 0000000000..baa94e0599 --- /dev/null +++ b/contrib/libs/flatbuffers/grpc/src/compiler/go_generator.h @@ -0,0 +1,64 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef GRPC_INTERNAL_COMPILER_GO_GENERATOR_H +#define GRPC_INTERNAL_COMPILER_GO_GENERATOR_H + +//go generator is used to generate GRPC code for serialization system, such as flatbuffers +#include <memory> +#include <vector> + +#include "src/compiler/schema_interface.h" + +namespace grpc_go_generator { + +struct Parameters { + //Defines the custom parameter types for methods + //eg: flatbuffers uses flatbuffers.Builder as input for the client and output for the server + grpc::string custom_method_io_type; + + //Package name for the service + grpc::string package_name; + + //Prefix for RPC Calls + grpc::string service_prefix; +}; + +// Return the source of the generated service file. +grpc::string GenerateServiceSource(grpc_generator::File *file, + const grpc_generator::Service *service, + grpc_go_generator::Parameters *parameters); + +} + +#endif // GRPC_INTERNAL_COMPILER_GO_GENERATOR_H diff --git a/contrib/libs/flatbuffers/grpc/src/compiler/java_generator.cc b/contrib/libs/flatbuffers/grpc/src/compiler/java_generator.cc new file mode 100644 index 0000000000..d2cf5ccc14 --- /dev/null +++ b/contrib/libs/flatbuffers/grpc/src/compiler/java_generator.cc @@ -0,0 +1,1135 @@ +/* + * Copyright 2016 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "src/compiler/java_generator.h" + +#include <algorithm> +#include <iostream> +#include <iterator> +#include <map> +#include <utility> +#include <vector> + +// just to get flatbuffer_version_string() +#include <flatbuffers/flatbuffers.h> +#include <flatbuffers/util.h> +#define to_string flatbuffers::NumToString + +// Stringify helpers used solely to cast GRPC_VERSION +#ifndef STR +#define STR(s) #s +#endif + +#ifndef XSTR +#define XSTR(s) STR(s) +#endif + + +typedef grpc_generator::Printer Printer; +typedef std::map<grpc::string, grpc::string> VARS; +typedef grpc_generator::Service ServiceDescriptor; +typedef grpc_generator::CommentHolder + DescriptorType; // base class of all 'descriptors' +typedef grpc_generator::Method MethodDescriptor; + +namespace grpc_java_generator { +typedef std::string string; +// Generates imports for the service +void GenerateImports(grpc_generator::File* file, + grpc_generator::Printer* printer, VARS& vars) { + vars["filename"] = file->filename(); + printer->Print( + vars, + "//Generated by flatc compiler (version $flatc_version$)\n"); + printer->Print("//If you make any local changes, they will be lost\n"); + printer->Print(vars, "//source: $filename$.fbs\n\n"); + printer->Print(vars, "package $Package$;\n\n"); + vars["Package"] = vars["Package"] + "."; + if (!file->additional_headers().empty()) { + printer->Print(file->additional_headers().c_str()); + printer->Print("\n\n"); + } +} + +// Adjust a method name prefix identifier to follow the JavaBean spec: +// - decapitalize the first letter +// - remove embedded underscores & capitalize the following letter +static string MixedLower(const string& word) { + string w; + w += static_cast<string::value_type>(tolower(word[0])); + bool after_underscore = false; + for (size_t i = 1; i < word.length(); ++i) { + if (word[i] == '_') { + after_underscore = true; + } else { + w += after_underscore ? static_cast<string::value_type>(toupper(word[i])) + : word[i]; + after_underscore = false; + } + } + return w; +} + +// Converts to the identifier to the ALL_UPPER_CASE format. +// - An underscore is inserted where a lower case letter is followed by an +// upper case letter. +// - All letters are converted to upper case +static string ToAllUpperCase(const string& word) { + string w; + for (size_t i = 0; i < word.length(); ++i) { + w += static_cast<string::value_type>(toupper(word[i])); + if ((i < word.length() - 1) && islower(word[i]) && isupper(word[i + 1])) { + w += '_'; + } + } + return w; +} + +static inline string LowerMethodName(const MethodDescriptor* method) { + return MixedLower(method->name()); +} + +static inline string MethodPropertiesFieldName(const MethodDescriptor* method) { + return "METHOD_" + ToAllUpperCase(method->name()); +} + +static inline string MethodPropertiesGetterName( + const MethodDescriptor* method) { + return MixedLower("get_" + method->name() + "_method"); +} + +static inline string MethodIdFieldName(const MethodDescriptor* method) { + return "METHODID_" + ToAllUpperCase(method->name()); +} + +static inline string JavaClassName(VARS& vars, const string& name) { + // string name = google::protobuf::compiler::java::ClassName(desc); + return vars["Package"] + name; +} + +static inline string ServiceClassName(const string& service_name) { + return service_name + "Grpc"; +} + +// TODO(nmittler): Remove once protobuf includes javadoc methods in +// distribution. +template <typename ITR> +static void GrpcSplitStringToIteratorUsing(const string& full, + const char* delim, ITR& result) { + // Optimize the common case where delim is a single character. + if (delim[0] != '\0' && delim[1] == '\0') { + char c = delim[0]; + const char* p = full.data(); + const char* end = p + full.size(); + while (p != end) { + if (*p == c) { + ++p; + } else { + const char* start = p; + while (++p != end && *p != c) + ; + *result++ = string(start, p - start); + } + } + return; + } + + string::size_type begin_index, end_index; + begin_index = full.find_first_not_of(delim); + while (begin_index != string::npos) { + end_index = full.find_first_of(delim, begin_index); + if (end_index == string::npos) { + *result++ = full.substr(begin_index); + return; + } + *result++ = full.substr(begin_index, (end_index - begin_index)); + begin_index = full.find_first_not_of(delim, end_index); + } +} + +static void GrpcSplitStringUsing(const string& full, const char* delim, + std::vector<string>* result) { + std::back_insert_iterator<std::vector<string>> it(*result); + GrpcSplitStringToIteratorUsing(full, delim, it); +} + +static std::vector<string> GrpcSplit(const string& full, const char* delim) { + std::vector<string> result; + GrpcSplitStringUsing(full, delim, &result); + return result; +} + +// TODO(nmittler): Remove once protobuf includes javadoc methods in +// distribution. +static string GrpcEscapeJavadoc(const string& input) { + string result; + result.reserve(input.size() * 2); + + char prev = '*'; + + for (string::size_type i = 0; i < input.size(); i++) { + char c = input[i]; + switch (c) { + case '*': + // Avoid "/*". + if (prev == '/') { + result.append("*"); + } else { + result.push_back(c); + } + break; + case '/': + // Avoid "*/". + if (prev == '*') { + result.append("/"); + } else { + result.push_back(c); + } + break; + case '@': + // '@' starts javadoc tags including the @deprecated tag, which will + // cause a compile-time error if inserted before a declaration that + // does not have a corresponding @Deprecated annotation. + result.append("@"); + break; + case '<': + // Avoid interpretation as HTML. + result.append("<"); + break; + case '>': + // Avoid interpretation as HTML. + result.append(">"); + break; + case '&': + // Avoid interpretation as HTML. + result.append("&"); + break; + case '\\': + // Java interprets Unicode escape sequences anywhere! + result.append("\"); + break; + default: + result.push_back(c); + break; + } + + prev = c; + } + + return result; +} + +static std::vector<string> GrpcGetDocLines(const string& comments) { + if (!comments.empty()) { + // TODO(kenton): Ideally we should parse the comment text as Markdown and + // write it back as HTML, but this requires a Markdown parser. For now + // we just use <pre> to get fixed-width text formatting. + + // If the comment itself contains block comment start or end markers, + // HTML-escape them so that they don't accidentally close the doc comment. + string escapedComments = GrpcEscapeJavadoc(comments); + + std::vector<string> lines = GrpcSplit(escapedComments, "\n"); + while (!lines.empty() && lines.back().empty()) { + lines.pop_back(); + } + return lines; + } + return std::vector<string>(); +} + +static std::vector<string> GrpcGetDocLinesForDescriptor( + const DescriptorType* descriptor) { + return descriptor->GetAllComments(); + // return GrpcGetDocLines(descriptor->GetLeadingComments("///")); +} + +static void GrpcWriteDocCommentBody(Printer* printer, VARS& vars, + const std::vector<string>& lines, + bool surroundWithPreTag) { + if (!lines.empty()) { + if (surroundWithPreTag) { + printer->Print(" * <pre>\n"); + } + + for (size_t i = 0; i < lines.size(); i++) { + // Most lines should start with a space. Watch out for lines that start + // with a /, since putting that right after the leading asterisk will + // close the comment. + vars["line"] = lines[i]; + if (!lines[i].empty() && lines[i][0] == '/') { + printer->Print(vars, " * $line$\n"); + } else { + printer->Print(vars, " *$line$\n"); + } + } + + if (surroundWithPreTag) { + printer->Print(" * </pre>\n"); + } + } +} + +static void GrpcWriteDocComment(Printer* printer, VARS& vars, + const string& comments) { + printer->Print("/**\n"); + std::vector<string> lines = GrpcGetDocLines(comments); + GrpcWriteDocCommentBody(printer, vars, lines, false); + printer->Print(" */\n"); +} + +static void GrpcWriteServiceDocComment(Printer* printer, VARS& vars, + const ServiceDescriptor* service) { + printer->Print("/**\n"); + std::vector<string> lines = GrpcGetDocLinesForDescriptor(service); + GrpcWriteDocCommentBody(printer, vars, lines, true); + printer->Print(" */\n"); +} + +void GrpcWriteMethodDocComment(Printer* printer, VARS& vars, + const MethodDescriptor* method) { + printer->Print("/**\n"); + std::vector<string> lines = GrpcGetDocLinesForDescriptor(method); + GrpcWriteDocCommentBody(printer, vars, lines, true); + printer->Print(" */\n"); +} + +//outputs static singleton extractor for type stored in "extr_type" and "extr_type_name" vars +static void PrintTypeExtractor(Printer* p, VARS& vars) { + p->Print( + vars, + "private static volatile FlatbuffersUtils.FBExtactor<$extr_type$> " + "extractorOf$extr_type_name$;\n" + "private static FlatbuffersUtils.FBExtactor<$extr_type$> " + "getExtractorOf$extr_type_name$() {\n" + " if (extractorOf$extr_type_name$ != null) return " + "extractorOf$extr_type_name$;\n" + " synchronized ($service_class_name$.class) {\n" + " if (extractorOf$extr_type_name$ != null) return " + "extractorOf$extr_type_name$;\n" + " extractorOf$extr_type_name$ = new " + "FlatbuffersUtils.FBExtactor<$extr_type$>() {\n" + " public $extr_type$ extract (ByteBuffer buffer) {\n" + " return " + "$extr_type$.getRootAs$extr_type_name$(buffer);\n" + " }\n" + " };\n" + " return extractorOf$extr_type_name$;\n" + " }\n" + "}\n\n"); +} +static void PrintMethodFields(Printer* p, VARS& vars, + const ServiceDescriptor* service) { + p->Print("// Static method descriptors that strictly reflect the proto.\n"); + vars["service_name"] = service->name(); + + //set of names of rpc input- and output- types that were already encountered. + //this is needed to avoid duplicating type extractor since it's possible that + //the same type is used as an input or output type of more than a single RPC method + std::set<std::string> encounteredTypes; + + for (int i = 0; i < service->method_count(); ++i) { + auto method = service->method(i); + vars["arg_in_id"] = to_string(2L * i); //trying to make msvc 10 happy + vars["arg_out_id"] = to_string(2L * i + 1); + vars["method_name"] = method->name(); + vars["input_type_name"] = method->get_input_type_name(); + vars["output_type_name"] = method->get_output_type_name(); + vars["input_type"] = JavaClassName(vars, method->get_input_type_name()); + vars["output_type"] = JavaClassName(vars, method->get_output_type_name()); + vars["method_field_name"] = MethodPropertiesFieldName(method.get()); + vars["method_new_field_name"] = MethodPropertiesGetterName(method.get()); + vars["method_method_name"] = MethodPropertiesGetterName(method.get()); + bool client_streaming = method->ClientStreaming() || method->BidiStreaming(); + bool server_streaming = method->ServerStreaming() || method->BidiStreaming(); + if (client_streaming) { + if (server_streaming) { + vars["method_type"] = "BIDI_STREAMING"; + } else { + vars["method_type"] = "CLIENT_STREAMING"; + } + } else { + if (server_streaming) { + vars["method_type"] = "SERVER_STREAMING"; + } else { + vars["method_type"] = "UNARY"; + } + } + + p->Print( + vars, + "@$ExperimentalApi$(\"https://github.com/grpc/grpc-java/issues/" + "1901\")\n" + "@$Deprecated$ // Use {@link #$method_method_name$()} instead. \n" + "public static final $MethodDescriptor$<$input_type$,\n" + " $output_type$> $method_field_name$ = $method_method_name$();\n" + "\n" + "private static volatile $MethodDescriptor$<$input_type$,\n" + " $output_type$> $method_new_field_name$;\n" + "\n"); + + if (encounteredTypes.insert(vars["input_type_name"]).second) { + vars["extr_type"] = vars["input_type"]; + vars["extr_type_name"] = vars["input_type_name"]; + PrintTypeExtractor(p, vars); + } + + if (encounteredTypes.insert(vars["output_type_name"]).second) { + vars["extr_type"] = vars["output_type"]; + vars["extr_type_name"] = vars["output_type_name"]; + PrintTypeExtractor(p, vars); + } + + p->Print( + vars, + "@$ExperimentalApi$(\"https://github.com/grpc/grpc-java/issues/" + "1901\")\n" + "public static $MethodDescriptor$<$input_type$,\n" + " $output_type$> $method_method_name$() {\n" + " $MethodDescriptor$<$input_type$, $output_type$> " + "$method_new_field_name$;\n" + " if (($method_new_field_name$ = " + "$service_class_name$.$method_new_field_name$) == null) {\n" + " synchronized ($service_class_name$.class) {\n" + " if (($method_new_field_name$ = " + "$service_class_name$.$method_new_field_name$) == null) {\n" + " $service_class_name$.$method_new_field_name$ = " + "$method_new_field_name$ = \n" + " $MethodDescriptor$.<$input_type$, " + "$output_type$>newBuilder()\n" + " .setType($MethodType$.$method_type$)\n" + " .setFullMethodName(generateFullMethodName(\n" + " \"$Package$$service_name$\", \"$method_name$\"))\n" + " .setSampledToLocalTracing(true)\n" + " .setRequestMarshaller(FlatbuffersUtils.marshaller(\n" + " $input_type$.class, " + "getExtractorOf$input_type_name$()))\n" + " .setResponseMarshaller(FlatbuffersUtils.marshaller(\n" + " $output_type$.class, " + "getExtractorOf$output_type_name$()))\n"); + + // vars["proto_method_descriptor_supplier"] = service->name() + + // "MethodDescriptorSupplier"; + p->Print(vars, " .setSchemaDescriptor(null)\n"); + //" .setSchemaDescriptor(new + //$proto_method_descriptor_supplier$(\"$method_name$\"))\n"); + + p->Print(vars, " .build();\n"); + p->Print(vars, + " }\n" + " }\n" + " }\n" + " return $method_new_field_name$;\n" + "}\n"); + + p->Print("\n"); + } +} +enum StubType { + ASYNC_INTERFACE = 0, + BLOCKING_CLIENT_INTERFACE = 1, + FUTURE_CLIENT_INTERFACE = 2, + BLOCKING_SERVER_INTERFACE = 3, + ASYNC_CLIENT_IMPL = 4, + BLOCKING_CLIENT_IMPL = 5, + FUTURE_CLIENT_IMPL = 6, + ABSTRACT_CLASS = 7, +}; + +enum CallType { ASYNC_CALL = 0, BLOCKING_CALL = 1, FUTURE_CALL = 2 }; + +static void PrintBindServiceMethodBody(Printer* p, VARS& vars, + const ServiceDescriptor* service); + +// Prints a client interface or implementation class, or a server interface. +static void PrintStub(Printer* p, VARS& vars, const ServiceDescriptor* service, + StubType type) { + const string service_name = service->name(); + vars["service_name"] = service_name; + vars["abstract_name"] = service_name + "ImplBase"; + string stub_name = service_name; + string client_name = service_name; + CallType call_type = ASYNC_CALL; + bool impl_base = false; + bool interface = false; + switch (type) { + case ABSTRACT_CLASS: + call_type = ASYNC_CALL; + impl_base = true; + break; + case ASYNC_CLIENT_IMPL: + call_type = ASYNC_CALL; + stub_name += "Stub"; + break; + case BLOCKING_CLIENT_INTERFACE: + interface = true; + FLATBUFFERS_FALLTHROUGH(); // fall thru + case BLOCKING_CLIENT_IMPL: + call_type = BLOCKING_CALL; + stub_name += "BlockingStub"; + client_name += "BlockingClient"; + break; + case FUTURE_CLIENT_INTERFACE: + interface = true; + FLATBUFFERS_FALLTHROUGH(); // fall thru + case FUTURE_CLIENT_IMPL: + call_type = FUTURE_CALL; + stub_name += "FutureStub"; + client_name += "FutureClient"; + break; + case ASYNC_INTERFACE: + call_type = ASYNC_CALL; + interface = true; + break; + default: + GRPC_CODEGEN_FAIL << "Cannot determine class name for StubType: " << type; + } + vars["stub_name"] = stub_name; + vars["client_name"] = client_name; + + // Class head + if (!interface) { + GrpcWriteServiceDocComment(p, vars, service); + } + if (impl_base) { + p->Print(vars, + "public static abstract class $abstract_name$ implements " + "$BindableService$ {\n"); + } else { + p->Print(vars, + "public static final class $stub_name$ extends " + "$AbstractStub$<$stub_name$> {\n"); + } + p->Indent(); + + // Constructor and build() method + if (!impl_base && !interface) { + p->Print(vars, "private $stub_name$($Channel$ channel) {\n"); + p->Indent(); + p->Print("super(channel);\n"); + p->Outdent(); + p->Print("}\n\n"); + p->Print(vars, + "private $stub_name$($Channel$ channel,\n" + " $CallOptions$ callOptions) {\n"); + p->Indent(); + p->Print("super(channel, callOptions);\n"); + p->Outdent(); + p->Print("}\n\n"); + p->Print(vars, + "@$Override$\n" + "protected $stub_name$ build($Channel$ channel,\n" + " $CallOptions$ callOptions) {\n"); + p->Indent(); + p->Print(vars, "return new $stub_name$(channel, callOptions);\n"); + p->Outdent(); + p->Print("}\n"); + } + + // RPC methods + for (int i = 0; i < service->method_count(); ++i) { + auto method = service->method(i); + vars["input_type"] = JavaClassName(vars, method->get_input_type_name()); + vars["output_type"] = JavaClassName(vars, method->get_output_type_name()); + vars["lower_method_name"] = LowerMethodName(&*method); + vars["method_method_name"] = MethodPropertiesGetterName(&*method); + bool client_streaming = method->ClientStreaming() || method->BidiStreaming(); + bool server_streaming = method->ServerStreaming() || method->BidiStreaming(); + + if (call_type == BLOCKING_CALL && client_streaming) { + // Blocking client interface with client streaming is not available + continue; + } + + if (call_type == FUTURE_CALL && (client_streaming || server_streaming)) { + // Future interface doesn't support streaming. + continue; + } + + // Method signature + p->Print("\n"); + // TODO(nmittler): Replace with WriteMethodDocComment once included by the + // protobuf distro. + if (!interface) { + GrpcWriteMethodDocComment(p, vars, &*method); + } + p->Print("public "); + switch (call_type) { + case BLOCKING_CALL: + GRPC_CODEGEN_CHECK(!client_streaming) + << "Blocking client interface with client streaming is unavailable"; + if (server_streaming) { + // Server streaming + p->Print(vars, + "$Iterator$<$output_type$> $lower_method_name$(\n" + " $input_type$ request)"); + } else { + // Simple RPC + p->Print(vars, + "$output_type$ $lower_method_name$($input_type$ request)"); + } + break; + case ASYNC_CALL: + if (client_streaming) { + // Bidirectional streaming or client streaming + p->Print(vars, + "$StreamObserver$<$input_type$> $lower_method_name$(\n" + " $StreamObserver$<$output_type$> responseObserver)"); + } else { + // Server streaming or simple RPC + p->Print(vars, + "void $lower_method_name$($input_type$ request,\n" + " $StreamObserver$<$output_type$> responseObserver)"); + } + break; + case FUTURE_CALL: + GRPC_CODEGEN_CHECK(!client_streaming && !server_streaming) + << "Future interface doesn't support streaming. " + << "client_streaming=" << client_streaming << ", " + << "server_streaming=" << server_streaming; + p->Print(vars, + "$ListenableFuture$<$output_type$> $lower_method_name$(\n" + " $input_type$ request)"); + break; + } + + if (interface) { + p->Print(";\n"); + continue; + } + // Method body. + p->Print(" {\n"); + p->Indent(); + if (impl_base) { + switch (call_type) { + // NB: Skipping validation of service methods. If something is wrong, + // we wouldn't get to this point as compiler would return errors when + // generating service interface. + case ASYNC_CALL: + if (client_streaming) { + p->Print(vars, + "return " + "asyncUnimplementedStreamingCall($method_method_name$(), " + "responseObserver);\n"); + } else { + p->Print(vars, + "asyncUnimplementedUnaryCall($method_method_name$(), " + "responseObserver);\n"); + } + break; + default: + break; + } + } else if (!interface) { + switch (call_type) { + case BLOCKING_CALL: + GRPC_CODEGEN_CHECK(!client_streaming) + << "Blocking client streaming interface is not available"; + if (server_streaming) { + vars["calls_method"] = "blockingServerStreamingCall"; + vars["params"] = "request"; + } else { + vars["calls_method"] = "blockingUnaryCall"; + vars["params"] = "request"; + } + p->Print(vars, + "return $calls_method$(\n" + " getChannel(), $method_method_name$(), " + "getCallOptions(), $params$);\n"); + break; + case ASYNC_CALL: + if (server_streaming) { + if (client_streaming) { + vars["calls_method"] = "asyncBidiStreamingCall"; + vars["params"] = "responseObserver"; + } else { + vars["calls_method"] = "asyncServerStreamingCall"; + vars["params"] = "request, responseObserver"; + } + } else { + if (client_streaming) { + vars["calls_method"] = "asyncClientStreamingCall"; + vars["params"] = "responseObserver"; + } else { + vars["calls_method"] = "asyncUnaryCall"; + vars["params"] = "request, responseObserver"; + } + } + vars["last_line_prefix"] = client_streaming ? "return " : ""; + p->Print(vars, + "$last_line_prefix$$calls_method$(\n" + " getChannel().newCall($method_method_name$(), " + "getCallOptions()), $params$);\n"); + break; + case FUTURE_CALL: + GRPC_CODEGEN_CHECK(!client_streaming && !server_streaming) + << "Future interface doesn't support streaming. " + << "client_streaming=" << client_streaming << ", " + << "server_streaming=" << server_streaming; + vars["calls_method"] = "futureUnaryCall"; + p->Print(vars, + "return $calls_method$(\n" + " getChannel().newCall($method_method_name$(), " + "getCallOptions()), request);\n"); + break; + } + } + p->Outdent(); + p->Print("}\n"); + } + + if (impl_base) { + p->Print("\n"); + p->Print( + vars, + "@$Override$ public final $ServerServiceDefinition$ bindService() {\n"); + vars["instance"] = "this"; + PrintBindServiceMethodBody(p, vars, service); + p->Print("}\n"); + } + + p->Outdent(); + p->Print("}\n\n"); +} + +static bool CompareMethodClientStreaming( + const std::unique_ptr<const grpc_generator::Method>& method1, + const std::unique_ptr<const grpc_generator::Method>& method2) { + return method1->ClientStreaming() < method2->ClientStreaming(); +} + +// Place all method invocations into a single class to reduce memory footprint +// on Android. +static void PrintMethodHandlerClass(Printer* p, VARS& vars, + const ServiceDescriptor* service) { + // Sort method ids based on ClientStreaming() so switch tables are compact. + std::vector<std::unique_ptr<const grpc_generator::Method>> sorted_methods( + service->method_count()); + for (int i = 0; i < service->method_count(); ++i) { + sorted_methods[i] = service->method(i); + } + stable_sort(sorted_methods.begin(), sorted_methods.end(), + CompareMethodClientStreaming); + for (size_t i = 0; i < sorted_methods.size(); i++) { + auto& method = sorted_methods[i]; + vars["method_id"] = to_string(i); + vars["method_id_name"] = MethodIdFieldName(&*method); + p->Print(vars, + "private static final int $method_id_name$ = $method_id$;\n"); + } + p->Print("\n"); + vars["service_name"] = service->name() + "ImplBase"; + p->Print(vars, + "private static final class MethodHandlers<Req, Resp> implements\n" + " io.grpc.stub.ServerCalls.UnaryMethod<Req, Resp>,\n" + " io.grpc.stub.ServerCalls.ServerStreamingMethod<Req, Resp>,\n" + " io.grpc.stub.ServerCalls.ClientStreamingMethod<Req, Resp>,\n" + " io.grpc.stub.ServerCalls.BidiStreamingMethod<Req, Resp> {\n" + " private final $service_name$ serviceImpl;\n" + " private final int methodId;\n" + "\n" + " MethodHandlers($service_name$ serviceImpl, int methodId) {\n" + " this.serviceImpl = serviceImpl;\n" + " this.methodId = methodId;\n" + " }\n\n"); + p->Indent(); + p->Print(vars, + "@$Override$\n" + "@java.lang.SuppressWarnings(\"unchecked\")\n" + "public void invoke(Req request, $StreamObserver$<Resp> " + "responseObserver) {\n" + " switch (methodId) {\n"); + p->Indent(); + p->Indent(); + + for (int i = 0; i < service->method_count(); ++i) { + auto method = service->method(i); + if (method->ClientStreaming() || method->BidiStreaming()) { + continue; + } + vars["method_id_name"] = MethodIdFieldName(&*method); + vars["lower_method_name"] = LowerMethodName(&*method); + vars["input_type"] = JavaClassName(vars, method->get_input_type_name()); + vars["output_type"] = JavaClassName(vars, method->get_output_type_name()); + p->Print(vars, + "case $method_id_name$:\n" + " serviceImpl.$lower_method_name$(($input_type$) request,\n" + " ($StreamObserver$<$output_type$>) responseObserver);\n" + " break;\n"); + } + p->Print( + "default:\n" + " throw new AssertionError();\n"); + + p->Outdent(); + p->Outdent(); + p->Print( + " }\n" + "}\n\n"); + + p->Print(vars, + "@$Override$\n" + "@java.lang.SuppressWarnings(\"unchecked\")\n" + "public $StreamObserver$<Req> invoke(\n" + " $StreamObserver$<Resp> responseObserver) {\n" + " switch (methodId) {\n"); + p->Indent(); + p->Indent(); + + for (int i = 0; i < service->method_count(); ++i) { + auto method = service->method(i); + if (!(method->ClientStreaming() || method->BidiStreaming())) { + continue; + } + vars["method_id_name"] = MethodIdFieldName(&*method); + vars["lower_method_name"] = LowerMethodName(&*method); + vars["input_type"] = JavaClassName(vars, method->get_input_type_name()); + vars["output_type"] = JavaClassName(vars, method->get_output_type_name()); + p->Print( + vars, + "case $method_id_name$:\n" + " return ($StreamObserver$<Req>) serviceImpl.$lower_method_name$(\n" + " ($StreamObserver$<$output_type$>) responseObserver);\n"); + } + p->Print( + "default:\n" + " throw new AssertionError();\n"); + + p->Outdent(); + p->Outdent(); + p->Print( + " }\n" + "}\n"); + + p->Outdent(); + p->Print("}\n\n"); +} + +static void PrintGetServiceDescriptorMethod(Printer* p, VARS& vars, + const ServiceDescriptor* service) { + vars["service_name"] = service->name(); + // vars["proto_base_descriptor_supplier"] = service->name() + + // "BaseDescriptorSupplier"; vars["proto_file_descriptor_supplier"] = + // service->name() + "FileDescriptorSupplier"; + // vars["proto_method_descriptor_supplier"] = service->name() + + // "MethodDescriptorSupplier"; vars["proto_class_name"] = + // google::protobuf::compiler::java::ClassName(service->file()); + // p->Print( + // vars, + // "private static abstract class + // $proto_base_descriptor_supplier$\n" " implements + // $ProtoFileDescriptorSupplier$, + // $ProtoServiceDescriptorSupplier$ {\n" " + // $proto_base_descriptor_supplier$() {}\n" + // "\n" + // " @$Override$\n" + // " public com.google.protobuf.Descriptors.FileDescriptor + // getFileDescriptor() {\n" " return + // $proto_class_name$.getDescriptor();\n" " }\n" + // "\n" + // " @$Override$\n" + // " public com.google.protobuf.Descriptors.ServiceDescriptor + // getServiceDescriptor() {\n" " return + // getFileDescriptor().findServiceByName(\"$service_name$\");\n" + // " }\n" + // "}\n" + // "\n" + // "private static final class + // $proto_file_descriptor_supplier$\n" " extends + // $proto_base_descriptor_supplier$ {\n" " + // $proto_file_descriptor_supplier$() {}\n" + // "}\n" + // "\n" + // "private static final class + // $proto_method_descriptor_supplier$\n" " extends + // $proto_base_descriptor_supplier$\n" " implements + // $ProtoMethodDescriptorSupplier$ {\n" " private final + // String methodName;\n" + // "\n" + // " $proto_method_descriptor_supplier$(String methodName) + // {\n" " this.methodName = methodName;\n" " }\n" + // "\n" + // " @$Override$\n" + // " public com.google.protobuf.Descriptors.MethodDescriptor + // getMethodDescriptor() {\n" " return + // getServiceDescriptor().findMethodByName(methodName);\n" " + // }\n" + // "}\n\n"); + + p->Print( + vars, + "private static volatile $ServiceDescriptor$ serviceDescriptor;\n\n"); + + p->Print(vars, + "public static $ServiceDescriptor$ getServiceDescriptor() {\n"); + p->Indent(); + p->Print(vars, "$ServiceDescriptor$ result = serviceDescriptor;\n"); + p->Print("if (result == null) {\n"); + p->Indent(); + p->Print(vars, "synchronized ($service_class_name$.class) {\n"); + p->Indent(); + p->Print("result = serviceDescriptor;\n"); + p->Print("if (result == null) {\n"); + p->Indent(); + + p->Print(vars, + "serviceDescriptor = result = " + "$ServiceDescriptor$.newBuilder(SERVICE_NAME)"); + p->Indent(); + p->Indent(); + p->Print(vars, "\n.setSchemaDescriptor(null)"); + for (int i = 0; i < service->method_count(); ++i) { + auto method = service->method(i); + vars["method_method_name"] = MethodPropertiesGetterName(&*method); + p->Print(vars, "\n.addMethod($method_method_name$())"); + } + p->Print("\n.build();\n"); + p->Outdent(); + p->Outdent(); + + p->Outdent(); + p->Print("}\n"); + p->Outdent(); + p->Print("}\n"); + p->Outdent(); + p->Print("}\n"); + p->Print("return result;\n"); + p->Outdent(); + p->Print("}\n"); +} + +static void PrintBindServiceMethodBody(Printer* p, VARS& vars, + const ServiceDescriptor* service) { + vars["service_name"] = service->name(); + p->Indent(); + p->Print(vars, + "return " + "$ServerServiceDefinition$.builder(getServiceDescriptor())\n"); + p->Indent(); + p->Indent(); + for (int i = 0; i < service->method_count(); ++i) { + auto method = service->method(i); + vars["lower_method_name"] = LowerMethodName(&*method); + vars["method_method_name"] = MethodPropertiesGetterName(&*method); + vars["input_type"] = JavaClassName(vars, method->get_input_type_name()); + vars["output_type"] = JavaClassName(vars, method->get_output_type_name()); + vars["method_id_name"] = MethodIdFieldName(&*method); + bool client_streaming = method->ClientStreaming() || method->BidiStreaming(); + bool server_streaming = method->ServerStreaming() || method->BidiStreaming(); + if (client_streaming) { + if (server_streaming) { + vars["calls_method"] = "asyncBidiStreamingCall"; + } else { + vars["calls_method"] = "asyncClientStreamingCall"; + } + } else { + if (server_streaming) { + vars["calls_method"] = "asyncServerStreamingCall"; + } else { + vars["calls_method"] = "asyncUnaryCall"; + } + } + p->Print(vars, ".addMethod(\n"); + p->Indent(); + p->Print(vars, + "$method_method_name$(),\n" + "$calls_method$(\n"); + p->Indent(); + p->Print(vars, + "new MethodHandlers<\n" + " $input_type$,\n" + " $output_type$>(\n" + " $instance$, $method_id_name$)))\n"); + p->Outdent(); + p->Outdent(); + } + p->Print(".build();\n"); + p->Outdent(); + p->Outdent(); + p->Outdent(); +} + +static void PrintService(Printer* p, VARS& vars, + const ServiceDescriptor* service, + bool disable_version) { + vars["service_name"] = service->name(); + vars["service_class_name"] = ServiceClassName(service->name()); + vars["grpc_version"] = ""; +#ifdef GRPC_VERSION + if (!disable_version) { + vars["grpc_version"] = " (version " XSTR(GRPC_VERSION) ")"; + } +#else + (void)disable_version; +#endif + // TODO(nmittler): Replace with WriteServiceDocComment once included by + // protobuf distro. + GrpcWriteServiceDocComment(p, vars, service); + p->Print(vars, + "@$Generated$(\n" + " value = \"by gRPC proto compiler$grpc_version$\",\n" + " comments = \"Source: $file_name$.fbs\")\n" + "public final class $service_class_name$ {\n\n"); + p->Indent(); + p->Print(vars, "private $service_class_name$() {}\n\n"); + + p->Print(vars, + "public static final String SERVICE_NAME = " + "\"$Package$$service_name$\";\n\n"); + + PrintMethodFields(p, vars, service); + + // TODO(nmittler): Replace with WriteDocComment once included by protobuf + // distro. + GrpcWriteDocComment( + p, vars, + " Creates a new async stub that supports all call types for the service"); + p->Print(vars, + "public static $service_name$Stub newStub($Channel$ channel) {\n"); + p->Indent(); + p->Print(vars, "return new $service_name$Stub(channel);\n"); + p->Outdent(); + p->Print("}\n\n"); + + // TODO(nmittler): Replace with WriteDocComment once included by protobuf + // distro. + GrpcWriteDocComment( + p, vars, + " Creates a new blocking-style stub that supports unary and streaming " + "output calls on the service"); + p->Print(vars, + "public static $service_name$BlockingStub newBlockingStub(\n" + " $Channel$ channel) {\n"); + p->Indent(); + p->Print(vars, "return new $service_name$BlockingStub(channel);\n"); + p->Outdent(); + p->Print("}\n\n"); + + // TODO(nmittler): Replace with WriteDocComment once included by protobuf + // distro. + GrpcWriteDocComment( + p, vars, + " Creates a new ListenableFuture-style stub that supports unary calls " + "on the service"); + p->Print(vars, + "public static $service_name$FutureStub newFutureStub(\n" + " $Channel$ channel) {\n"); + p->Indent(); + p->Print(vars, "return new $service_name$FutureStub(channel);\n"); + p->Outdent(); + p->Print("}\n\n"); + + PrintStub(p, vars, service, ABSTRACT_CLASS); + PrintStub(p, vars, service, ASYNC_CLIENT_IMPL); + PrintStub(p, vars, service, BLOCKING_CLIENT_IMPL); + PrintStub(p, vars, service, FUTURE_CLIENT_IMPL); + + PrintMethodHandlerClass(p, vars, service); + PrintGetServiceDescriptorMethod(p, vars, service); + p->Outdent(); + p->Print("}\n"); +} + +void PrintStaticImports(Printer* p) { + p->Print( + "import java.nio.ByteBuffer;\n" + "import static " + "io.grpc.MethodDescriptor.generateFullMethodName;\n" + "import static " + "io.grpc.stub.ClientCalls.asyncBidiStreamingCall;\n" + "import static " + "io.grpc.stub.ClientCalls.asyncClientStreamingCall;\n" + "import static " + "io.grpc.stub.ClientCalls.asyncServerStreamingCall;\n" + "import static " + "io.grpc.stub.ClientCalls.asyncUnaryCall;\n" + "import static " + "io.grpc.stub.ClientCalls.blockingServerStreamingCall;\n" + "import static " + "io.grpc.stub.ClientCalls.blockingUnaryCall;\n" + "import static " + "io.grpc.stub.ClientCalls.futureUnaryCall;\n" + "import static " + "io.grpc.stub.ServerCalls.asyncBidiStreamingCall;\n" + "import static " + "io.grpc.stub.ServerCalls.asyncClientStreamingCall;\n" + "import static " + "io.grpc.stub.ServerCalls.asyncServerStreamingCall;\n" + "import static " + "io.grpc.stub.ServerCalls.asyncUnaryCall;\n" + "import static " + "io.grpc.stub.ServerCalls.asyncUnimplementedStreamingCall;\n" + "import static " + "io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall;\n\n"); +} + +void GenerateService(const grpc_generator::Service* service, + grpc_generator::Printer* printer, VARS& vars, + bool disable_version) { + // All non-generated classes must be referred by fully qualified names to + // avoid collision with generated classes. + vars["String"] = "java.lang.String"; + vars["Deprecated"] = "java.lang.Deprecated"; + vars["Override"] = "java.lang.Override"; + vars["Channel"] = "io.grpc.Channel"; + vars["CallOptions"] = "io.grpc.CallOptions"; + vars["MethodType"] = "io.grpc.MethodDescriptor.MethodType"; + vars["ServerMethodDefinition"] = "io.grpc.ServerMethodDefinition"; + vars["BindableService"] = "io.grpc.BindableService"; + vars["ServerServiceDefinition"] = "io.grpc.ServerServiceDefinition"; + vars["ServiceDescriptor"] = "io.grpc.ServiceDescriptor"; + vars["ProtoFileDescriptorSupplier"] = + "io.grpc.protobuf.ProtoFileDescriptorSupplier"; + vars["ProtoServiceDescriptorSupplier"] = + "io.grpc.protobuf.ProtoServiceDescriptorSupplier"; + vars["ProtoMethodDescriptorSupplier"] = + "io.grpc.protobuf.ProtoMethodDescriptorSupplier"; + vars["AbstractStub"] = "io.grpc.stub.AbstractStub"; + vars["MethodDescriptor"] = "io.grpc.MethodDescriptor"; + vars["NanoUtils"] = "io.grpc.protobuf.nano.NanoUtils"; + vars["StreamObserver"] = "io.grpc.stub.StreamObserver"; + vars["Iterator"] = "java.util.Iterator"; + vars["Generated"] = "javax.annotation.Generated"; + vars["ListenableFuture"] = + "com.google.common.util.concurrent.ListenableFuture"; + vars["ExperimentalApi"] = "io.grpc.ExperimentalApi"; + + PrintStaticImports(printer); + + PrintService(printer, vars, service, disable_version); +} + +grpc::string GenerateServiceSource( + grpc_generator::File* file, const grpc_generator::Service* service, + grpc_java_generator::Parameters* parameters) { + grpc::string out; + auto printer = file->CreatePrinter(&out); + VARS vars; + vars["flatc_version"] = grpc::string( + FLATBUFFERS_STRING(FLATBUFFERS_VERSION_MAJOR) "." FLATBUFFERS_STRING( + FLATBUFFERS_VERSION_MINOR) "." FLATBUFFERS_STRING(FLATBUFFERS_VERSION_REVISION)); + + vars["file_name"] = file->filename(); + + if (!parameters->package_name.empty()) { + vars["Package"] = parameters->package_name; // ServiceJavaPackage(service); + } + GenerateImports(file, &*printer, vars); + GenerateService(service, &*printer, vars, false); + return out; +} + +} // namespace grpc_java_generator diff --git a/contrib/libs/flatbuffers/grpc/src/compiler/java_generator.h b/contrib/libs/flatbuffers/grpc/src/compiler/java_generator.h new file mode 100644 index 0000000000..b101fbf565 --- /dev/null +++ b/contrib/libs/flatbuffers/grpc/src/compiler/java_generator.h @@ -0,0 +1,85 @@ +/* + * Copyright 2016 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef NET_GRPC_COMPILER_JAVA_GENERATOR_H_ +#define NET_GRPC_COMPILER_JAVA_GENERATOR_H_ + +#include <stdlib.h> // for abort() +#include <iostream> +#include <map> +#include <string> + +#include "src/compiler/schema_interface.h" + +class LogMessageVoidify { + public: + LogMessageVoidify() {} + // This has to be an operator with a precedence lower than << but + // higher than ?: + void operator&(std::ostream&) {} +}; + +class LogHelper { + std::ostream* os_; + + public: + LogHelper(std::ostream* os) : os_(os) {} +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning( \ + disable : 4722) // the flow of control terminates in a destructor + // (needed to compile ~LogHelper where destructor emits abort intentionally - + // inherited from grpc/java code generator). +#endif + ~LogHelper() { + *os_ << std::endl; + ::abort(); + } +#if defined(_MSC_VER) +#pragma warning(pop) +#endif + std::ostream& get_os() const { return *os_; } +}; + +// Abort the program after logging the mesage if the given condition is not +// true. Otherwise, do nothing. +#define GRPC_CODEGEN_CHECK(x) \ + (x) ? (void)0 \ + : LogMessageVoidify() & LogHelper(&std::cerr).get_os() \ + << "CHECK FAILED: " << __FILE__ << ":" \ + << __LINE__ << ": " + +// Abort the program after logging the mesage. +#define GRPC_CODEGEN_FAIL GRPC_CODEGEN_CHECK(false) + +namespace grpc_java_generator { +struct Parameters { + // //Defines the custom parameter types for methods + // //eg: flatbuffers uses flatbuffers.Builder as input for the client + // and output for the server grpc::string custom_method_io_type; + + // Package name for the service + grpc::string package_name; +}; + +// Return the source of the generated service file. +grpc::string GenerateServiceSource(grpc_generator::File* file, + const grpc_generator::Service* service, + grpc_java_generator::Parameters* parameters); + +} // namespace grpc_java_generator + +#endif // NET_GRPC_COMPILER_JAVA_GENERATOR_H_ diff --git a/contrib/libs/flatbuffers/grpc/src/compiler/python_generator.cc b/contrib/libs/flatbuffers/grpc/src/compiler/python_generator.cc new file mode 100644 index 0000000000..8108db45d5 --- /dev/null +++ b/contrib/libs/flatbuffers/grpc/src/compiler/python_generator.cc @@ -0,0 +1,149 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include <map> +#include <sstream> + +#include "flatbuffers/util.h" +#include "src/compiler/python_generator.h" + +namespace grpc_python_generator { + +grpc::string GenerateMethodType(const grpc_generator::Method *method) { + + if (method->NoStreaming()) + return "unary_unary"; + + if (method->ServerStreaming()) + return "unary_stream"; + + if (method->ClientStreaming()) + return "stream_unary"; + + return "stream_stream"; +} + +grpc::string GenerateMethodInput(const grpc_generator::Method *method) { + + if (method->NoStreaming() || method->ServerStreaming()) + return "self, request, context"; + + return "self, request_iterator, context"; +} + +void GenerateStub(const grpc_generator::Service *service, + grpc_generator::Printer *printer, + std::map<grpc::string, grpc::string> *dictonary) { + auto vars = *dictonary; + printer->Print(vars, "class $ServiceName$Stub(object):\n"); + printer->Indent(); + printer->Print("\"\"\" Interface exported by the server. \"\"\""); + printer->Print("\n\n"); + printer->Print("def __init__(self, channel):\n"); + printer->Indent(); + printer->Print("\"\"\" Constructor. \n\n"); + printer->Print("Args: \n"); + printer->Print("channel: A grpc.Channel. \n"); + printer->Print("\"\"\"\n\n"); + + for (int j = 0; j < service->method_count(); j++) { + auto method = service->method(j); + vars["MethodName"] = method->name(); + vars["MethodType"] = GenerateMethodType(&*method); + printer->Print(vars, "self.$MethodName$ = channel.$MethodType$(\n"); + printer->Indent(); + printer->Print(vars, "\"/$PATH$$ServiceName$/$MethodName$\"\n"); + printer->Print(")\n"); + printer->Outdent(); + printer->Print("\n"); + } + printer->Outdent(); + printer->Outdent(); + printer->Print("\n"); +} + +void GenerateServicer(const grpc_generator::Service *service, + grpc_generator::Printer *printer, + std::map<grpc::string, grpc::string> *dictonary) { + auto vars = *dictonary; + printer->Print(vars, "class $ServiceName$Servicer(object):\n"); + printer->Indent(); + printer->Print("\"\"\" Interface exported by the server. \"\"\""); + printer->Print("\n\n"); + + for (int j = 0; j < service->method_count(); j++) { + auto method = service->method(j); + vars["MethodName"] = method->name(); + vars["MethodInput"] = GenerateMethodInput(&*method); + printer->Print(vars, "def $MethodName$($MethodInput$):\n"); + printer->Indent(); + printer->Print("context.set_code(grpc.StatusCode.UNIMPLEMENTED)\n"); + printer->Print("context.set_details('Method not implemented!')\n"); + printer->Print("raise NotImplementedError('Method not implemented!')\n"); + printer->Outdent(); + printer->Print("\n\n"); + } + printer->Outdent(); + printer->Print("\n"); + +} + +void GenerateRegister(const grpc_generator::Service *service, + grpc_generator::Printer *printer, + std::map<grpc::string, grpc::string> *dictonary) { + auto vars = *dictonary; + printer->Print(vars, "def add_$ServiceName$Servicer_to_server(servicer, server):\n"); + printer->Indent(); + printer->Print("rpc_method_handlers = {\n"); + printer->Indent(); + for (int j = 0; j < service->method_count(); j++) { + auto method = service->method(j); + vars["MethodName"] = method->name(); + vars["MethodType"] = GenerateMethodType(&*method); + printer->Print(vars, "'$MethodName$': grpc.$MethodType$_rpc_method_handler(\n"); + printer->Indent(); + printer->Print(vars, "servicer.$MethodName$\n"); + printer->Outdent(); + printer->Print("),\n"); + } + printer->Outdent(); + printer->Print("}\n"); + printer->Print(vars, "generic_handler = grpc.method_handlers_generic_handler(\n"); + printer->Indent(); + printer->Print(vars, "'$PATH$$ServiceName$', rpc_method_handlers)\n"); + printer->Outdent(); + printer->Print("server.add_generic_rpc_handlers((generic_handler,))"); + printer->Outdent(); + printer->Print("\n"); +} + +grpc::string Generate(grpc_generator::File *file, + const grpc_generator::Service *service) { + grpc::string output; + std::map<grpc::string, grpc::string> vars; + vars["PATH"] = file->package(); + if (!file->package().empty()) { vars["PATH"].append("."); } + vars["ServiceName"] = service->name(); + auto printer = file->CreatePrinter(&output); + GenerateStub(service, &*printer, &vars); + GenerateServicer(service, &*printer, &vars); + GenerateRegister(service, &*printer, &vars); + return output; +} + +} // namespace grpc_python_generator diff --git a/contrib/libs/flatbuffers/grpc/src/compiler/python_generator.h b/contrib/libs/flatbuffers/grpc/src/compiler/python_generator.h new file mode 100644 index 0000000000..4f8f5cc806 --- /dev/null +++ b/contrib/libs/flatbuffers/grpc/src/compiler/python_generator.h @@ -0,0 +1,33 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPC_INTERNAL_COMPILER_PYTHON_GENERATOR_H +#define GRPC_INTERNAL_COMPILER_PYTHON_GENERATOR_H + +#include <utility> + +#include "src/compiler/config.h" +#include "src/compiler/schema_interface.h" + +namespace grpc_python_generator { + +grpc::string Generate(grpc_generator::File *file, + const grpc_generator::Service *service); +} // namespace grpc_python_generator + +#endif // GRPC_INTERNAL_COMPILER_PYTHON_GENERATOR_H diff --git a/contrib/libs/flatbuffers/grpc/src/compiler/schema_interface.h b/contrib/libs/flatbuffers/grpc/src/compiler/schema_interface.h new file mode 100644 index 0000000000..0449498198 --- /dev/null +++ b/contrib/libs/flatbuffers/grpc/src/compiler/schema_interface.h @@ -0,0 +1,120 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPC_INTERNAL_COMPILER_SCHEMA_INTERFACE_H +#define GRPC_INTERNAL_COMPILER_SCHEMA_INTERFACE_H + +#include <memory> +#include <vector> + +#include "src/compiler/config.h" + +#ifndef GRPC_CUSTOM_STRING +# include <string> +# define GRPC_CUSTOM_STRING std::string +#endif + +namespace grpc { + +typedef GRPC_CUSTOM_STRING string; + +} // namespace grpc + +namespace grpc_generator { + +// A common interface for objects having comments in the source. +// Return formatted comments to be inserted in generated code. +struct CommentHolder { + virtual ~CommentHolder() {} + virtual grpc::string GetLeadingComments(const grpc::string prefix) const = 0; + virtual grpc::string GetTrailingComments(const grpc::string prefix) const = 0; + virtual std::vector<grpc::string> GetAllComments() const = 0; +}; + +// An abstract interface representing a method. +struct Method : public CommentHolder { + virtual ~Method() {} + + virtual grpc::string name() const = 0; + + virtual grpc::string input_type_name() const = 0; + virtual grpc::string output_type_name() const = 0; + + virtual bool get_module_and_message_path_input( + grpc::string *str, grpc::string generator_file_name, + bool generate_in_pb2_grpc, grpc::string import_prefix) const = 0; + virtual bool get_module_and_message_path_output( + grpc::string *str, grpc::string generator_file_name, + bool generate_in_pb2_grpc, grpc::string import_prefix) const = 0; + + virtual std::vector<grpc::string> get_input_namespace_parts() const = 0; + virtual grpc::string get_input_type_name() const = 0; + virtual std::vector<grpc::string> get_output_namespace_parts() const = 0; + virtual grpc::string get_output_type_name() const = 0; + + virtual grpc::string get_fb_builder() const = 0; + + virtual bool NoStreaming() const = 0; + virtual bool ClientStreaming() const = 0; + virtual bool ServerStreaming() const = 0; + virtual bool BidiStreaming() const = 0; +}; + +// An abstract interface representing a service. +struct Service : public CommentHolder { + virtual ~Service() {} + + virtual std::vector<grpc::string> namespace_parts() const = 0; + virtual grpc::string name() const = 0; + virtual bool is_internal() const = 0; + + virtual int method_count() const = 0; + virtual std::unique_ptr<const Method> method(int i) const = 0; +}; + +struct Printer { + virtual ~Printer() {} + + virtual void Print(const std::map<grpc::string, grpc::string> &vars, + const char *template_string) = 0; + virtual void Print(const char *string) = 0; + virtual void SetIndentationSize(const int size) = 0; + virtual void Indent() = 0; + virtual void Outdent() = 0; +}; + +// An interface that allows the source generated to be output using various +// libraries/idls/serializers. +struct File : public CommentHolder { + virtual ~File() {} + + virtual grpc::string filename() const = 0; + virtual grpc::string filename_without_ext() const = 0; + virtual grpc::string package() const = 0; + virtual std::vector<grpc::string> package_parts() const = 0; + virtual grpc::string additional_headers() const = 0; + + virtual int service_count() const = 0; + virtual std::unique_ptr<const Service> service(int i) const = 0; + + virtual std::unique_ptr<Printer> CreatePrinter( + grpc::string *str, const char indentation_type = ' ') const = 0; +}; +} // namespace grpc_generator + +#endif // GRPC_INTERNAL_COMPILER_SCHEMA_INTERFACE_H diff --git a/contrib/libs/flatbuffers/grpc/src/compiler/swift_generator.cc b/contrib/libs/flatbuffers/grpc/src/compiler/swift_generator.cc new file mode 100644 index 0000000000..403a803ef1 --- /dev/null +++ b/contrib/libs/flatbuffers/grpc/src/compiler/swift_generator.cc @@ -0,0 +1,438 @@ +/* + * Copyright 2020 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * NOTE: The following implementation is a translation for the Swift-grpc + * generator since flatbuffers doesnt allow plugins for now. if an issue arises + * please open an issue in the flatbuffers repository. This file should always + * be maintained according to the Swift-grpc repository + */ +#include <map> +#include <sstream> + +#include "flatbuffers/util.h" +#include "src/compiler/schema_interface.h" +#include "src/compiler/swift_generator.h" + +namespace grpc_swift_generator { + +std::string WrapInNameSpace(const std::vector<std::string> &components, + const grpc::string &name) { + std::string qualified_name; + for (auto it = components.begin(); it != components.end(); ++it) + qualified_name += *it + "_"; + return qualified_name + name; +} + +grpc::string GenerateMessage(const std::vector<std::string> &components, + const grpc::string &name) { + return "Message<" + WrapInNameSpace(components, name) + ">"; +} + +// MARK: - Client + +void GenerateClientFuncName(const grpc_generator::Method *method, + grpc_generator::Printer *printer, + std::map<grpc::string, grpc::string> *dictonary) { + auto vars = *dictonary; + if (method->NoStreaming()) { + printer->Print(vars, + " $GenAccess$func $MethodName$(\n" + " _ request: $Input$\n" + " , callOptions: CallOptions?$isNil$\n" + " ) -> UnaryCall<$Input$, $Output$>"); + return; + } + + if (method->ServerStreaming()) { + printer->Print(vars, + " $GenAccess$func $MethodName$(\n" + " _ request: $Input$\n" + " , callOptions: CallOptions?$isNil$,\n" + " handler: @escaping ($Output$) -> Void\n" + " ) -> ServerStreamingCall<$Input$, $Output$>"); + return; + } + + if (method->ClientStreaming()) { + printer->Print(vars, + " $GenAccess$func $MethodName$(\n" + " callOptions: CallOptions?$isNil$\n" + " ) -> ClientStreamingCall<$Input$, $Output$>"); + return; + } + + printer->Print(vars, + " $GenAccess$func $MethodName$(\n" + " callOptions: CallOptions?$isNil$,\n" + " handler: @escaping ($Output$ ) -> Void\n" + " ) -> BidirectionalStreamingCall<$Input$, $Output$>"); +} + +void GenerateClientFuncBody(const grpc_generator::Method *method, + grpc_generator::Printer *printer, + std::map<grpc::string, grpc::string> *dictonary) { + auto vars = *dictonary; + vars["Interceptor"] = + "interceptors: self.interceptors?.make$MethodName$Interceptors() ?? []"; + if (method->NoStreaming()) { + printer->Print( + vars, + " return self.makeUnaryCall(\n" + " path: \"/$PATH$$ServiceName$/$MethodName$\",\n" + " request: request,\n" + " callOptions: callOptions ?? self.defaultCallOptions,\n" + " $Interceptor$\n" + " )\n"); + return; + } + + if (method->ServerStreaming()) { + printer->Print( + vars, + " return self.makeServerStreamingCall(\n" + " path: \"/$PATH$$ServiceName$/$MethodName$\",\n" + " request: request,\n" + " callOptions: callOptions ?? self.defaultCallOptions,\n" + " $Interceptor$,\n" + " handler: handler\n" + " )\n"); + return; + } + + if (method->ClientStreaming()) { + printer->Print( + vars, + " return self.makeClientStreamingCall(\n" + " path: \"/$PATH$$ServiceName$/$MethodName$\",\n" + " callOptions: callOptions ?? self.defaultCallOptions,\n" + " $Interceptor$\n" + " )\n"); + return; + } + printer->Print(vars, + " return self.makeBidirectionalStreamingCall(\n" + " path: \"/$PATH$$ServiceName$/$MethodName$\",\n" + " callOptions: callOptions ?? self.defaultCallOptions,\n" + " $Interceptor$,\n" + " handler: handler\n" + " )\n"); +} + +void GenerateClientProtocol(const grpc_generator::Service *service, + grpc_generator::Printer *printer, + std::map<grpc::string, grpc::string> *dictonary) { + auto vars = *dictonary; + printer->Print( + vars, + "$ACCESS$ protocol $ServiceQualifiedName$ClientProtocol: GRPCClient {"); + printer->Print("\n\n"); + printer->Print(" var serviceName: String { get }"); + printer->Print("\n\n"); + printer->Print( + vars, + " var interceptors: " + "$ServiceQualifiedName$ClientInterceptorFactoryProtocol? { get }"); + printer->Print("\n\n"); + + vars["GenAccess"] = ""; + for (auto it = 0; it < service->method_count(); it++) { + auto method = service->method(it); + vars["Input"] = GenerateMessage(method->get_input_namespace_parts(), + method->get_input_type_name()); + vars["Output"] = GenerateMessage(method->get_output_namespace_parts(), + method->get_output_type_name()); + vars["MethodName"] = method->name(); + vars["isNil"] = ""; + GenerateClientFuncName(method.get(), &*printer, &vars); + printer->Print("\n\n"); + } + printer->Print("}\n\n"); + + printer->Print(vars, "extension $ServiceQualifiedName$ClientProtocol {"); + printer->Print("\n\n"); + printer->Print(vars, + " $ACCESS$ var serviceName: String { " + "\"$PATH$$ServiceName$\" }\n"); + + vars["GenAccess"] = service->is_internal() ? "internal " : "public "; + for (auto it = 0; it < service->method_count(); it++) { + auto method = service->method(it); + vars["Input"] = GenerateMessage(method->get_input_namespace_parts(), + method->get_input_type_name()); + vars["Output"] = GenerateMessage(method->get_output_namespace_parts(), + method->get_output_type_name()); + vars["MethodName"] = method->name(); + vars["isNil"] = " = nil"; + printer->Print("\n"); + GenerateClientFuncName(method.get(), &*printer, &vars); + printer->Print(" {\n"); + GenerateClientFuncBody(method.get(), &*printer, &vars); + printer->Print(" }\n"); + } + printer->Print("}\n\n"); + + printer->Print(vars, + "$ACCESS$ protocol " + "$ServiceQualifiedName$ClientInterceptorFactoryProtocol {\n"); + + for (auto it = 0; it < service->method_count(); it++) { + auto method = service->method(it); + vars["Input"] = GenerateMessage(method->get_input_namespace_parts(), + method->get_input_type_name()); + vars["Output"] = GenerateMessage(method->get_output_namespace_parts(), + method->get_output_type_name()); + vars["MethodName"] = method->name(); + printer->Print( + vars, + " /// - Returns: Interceptors to use when invoking '$MethodName$'.\n"); + printer->Print(vars, + " func make$MethodName$Interceptors() -> " + "[ClientInterceptor<$Input$, $Output$>]\n\n"); + } + printer->Print("}\n\n"); +} + +void GenerateClientClass(grpc_generator::Printer *printer, + std::map<grpc::string, grpc::string> *dictonary) { + auto vars = *dictonary; + printer->Print(vars, + "$ACCESS$ final class $ServiceQualifiedName$ServiceClient: " + "$ServiceQualifiedName$ClientProtocol {\n"); + printer->Print(vars, " $ACCESS$ let channel: GRPCChannel\n"); + printer->Print(vars, " $ACCESS$ var defaultCallOptions: CallOptions\n"); + printer->Print(vars, + " $ACCESS$ var interceptors: " + "$ServiceQualifiedName$ClientInterceptorFactoryProtocol?\n"); + printer->Print("\n"); + printer->Print( + vars, + " $ACCESS$ init(\n" + " channel: GRPCChannel,\n" + " defaultCallOptions: CallOptions = CallOptions(),\n" + " interceptors: " + "$ServiceQualifiedName$ClientInterceptorFactoryProtocol? = nil\n" + " ) {\n"); + printer->Print(" self.channel = channel\n"); + printer->Print(" self.defaultCallOptions = defaultCallOptions\n"); + printer->Print(" self.interceptors = interceptors\n"); + printer->Print(" }"); + printer->Print("\n"); + printer->Print("}\n"); +} + +// MARK: - Server + +grpc::string GenerateServerFuncName(const grpc_generator::Method *method) { + if (method->NoStreaming()) { + return "func $MethodName$(request: $Input$" + ", context: StatusOnlyCallContext) -> EventLoopFuture<$Output$>"; + } + + if (method->ClientStreaming()) { + return "func $MethodName$(context: UnaryResponseCallContext<$Output$>) -> " + "EventLoopFuture<(StreamEvent<$Input$" + ">) -> Void>"; + } + + if (method->ServerStreaming()) { + return "func $MethodName$(request: $Input$" + ", context: StreamingResponseCallContext<$Output$>) -> " + "EventLoopFuture<GRPCStatus>"; + } + return "func $MethodName$(context: StreamingResponseCallContext<$Output$>) " + "-> EventLoopFuture<(StreamEvent<$Input$>) -> Void>"; +} + +grpc::string GenerateServerExtensionBody(const grpc_generator::Method *method) { + grpc::string start = " case \"$MethodName$\":\n "; + grpc::string interceptors = + " interceptors: self.interceptors?.make$MethodName$Interceptors() " + "?? [],\n"; + if (method->NoStreaming()) { + return start + + "return UnaryServerHandler(\n" + " context: context,\n" + " requestDeserializer: GRPCPayloadDeserializer<$Input$>(),\n" + " responseSerializer: GRPCPayloadSerializer<$Output$>(),\n" + + interceptors + + " userFunction: self.$MethodName$(request:context:))\n"; + } + if (method->ServerStreaming()) { + return start + + "return ServerStreamingServerHandler(\n" + " context: context,\n" + " requestDeserializer: GRPCPayloadDeserializer<$Input$>(),\n" + " responseSerializer: GRPCPayloadSerializer<$Output$>(),\n" + + interceptors + + " userFunction: self.$MethodName$(request:context:))\n"; + } + if (method->ClientStreaming()) { + return start + + "return ClientStreamingServerHandler(\n" + " context: context,\n" + " requestDeserializer: GRPCPayloadDeserializer<$Input$>(),\n" + " responseSerializer: GRPCPayloadSerializer<$Output$>(),\n" + + interceptors + + " observerFactory: self.$MethodName$(context:))\n"; + } + if (method->BidiStreaming()) { + return start + + "return BidirectionalStreamingServerHandler(\n" + " context: context,\n" + " requestDeserializer: GRPCPayloadDeserializer<$Input$>(),\n" + " responseSerializer: GRPCPayloadSerializer<$Output$>(),\n" + + interceptors + + " observerFactory: self.$MethodName$(context:))\n"; + } + return ""; +} + +void GenerateServerProtocol(const grpc_generator::Service *service, + grpc_generator::Printer *printer, + std::map<grpc::string, grpc::string> *dictonary) { + auto vars = *dictonary; + printer->Print(vars, + "$ACCESS$ protocol $ServiceQualifiedName$Provider: " + "CallHandlerProvider {\n"); + printer->Print( + vars, + " var interceptors: " + "$ServiceQualifiedName$ServerInterceptorFactoryProtocol? { get }\n"); + for (auto it = 0; it < service->method_count(); it++) { + auto method = service->method(it); + vars["Input"] = GenerateMessage(method->get_input_namespace_parts(), + method->get_input_type_name()); + vars["Output"] = GenerateMessage(method->get_output_namespace_parts(), + method->get_output_type_name()); + vars["MethodName"] = method->name(); + printer->Print(" "); + auto func = GenerateServerFuncName(method.get()); + printer->Print(vars, func.c_str()); + printer->Print("\n"); + } + printer->Print("}\n\n"); + + printer->Print(vars, "$ACCESS$ extension $ServiceQualifiedName$Provider {\n"); + printer->Print("\n"); + printer->Print(vars, + " var serviceName: Substring { return " + "\"$PATH$$ServiceName$\" }\n"); + printer->Print("\n"); + printer->Print( + " func handle(method name: Substring, context: " + "CallHandlerContext) -> GRPCServerHandlerProtocol? {\n"); + printer->Print(" switch name {\n"); + for (auto it = 0; it < service->method_count(); it++) { + auto method = service->method(it); + vars["Input"] = GenerateMessage(method->get_input_namespace_parts(), + method->get_input_type_name()); + vars["Output"] = GenerateMessage(method->get_output_namespace_parts(), + method->get_output_type_name()); + vars["MethodName"] = method->name(); + auto body = GenerateServerExtensionBody(method.get()); + printer->Print(vars, body.c_str()); + printer->Print("\n"); + } + printer->Print(" default: return nil;\n"); + printer->Print(" }\n"); + printer->Print(" }\n\n"); + printer->Print("}\n\n"); + + printer->Print(vars, + "$ACCESS$ protocol " + "$ServiceQualifiedName$ServerInterceptorFactoryProtocol {\n"); + for (auto it = 0; it < service->method_count(); it++) { + auto method = service->method(it); + vars["Input"] = GenerateMessage(method->get_input_namespace_parts(), + method->get_input_type_name()); + vars["Output"] = GenerateMessage(method->get_output_namespace_parts(), + method->get_output_type_name()); + vars["MethodName"] = method->name(); + printer->Print( + vars, + " /// - Returns: Interceptors to use when handling '$MethodName$'.\n" + " /// Defaults to calling `self.makeInterceptors()`.\n"); + printer->Print(vars, + " func make$MethodName$Interceptors() -> " + "[ServerInterceptor<$Input$, $Output$>]\n\n"); + } + printer->Print("}"); +} + +grpc::string Generate(grpc_generator::File *file, + const grpc_generator::Service *service) { + grpc::string output; + std::map<grpc::string, grpc::string> vars; + vars["PATH"] = file->package(); + if (!file->package().empty()) { vars["PATH"].append("."); } + vars["ServiceQualifiedName"] = + WrapInNameSpace(service->namespace_parts(), service->name()); + vars["ServiceName"] = service->name(); + vars["ACCESS"] = service->is_internal() ? "internal" : "public"; + auto printer = file->CreatePrinter(&output); + printer->Print( + vars, + "/// Usage: instantiate $ServiceQualifiedName$ServiceClient, then call " + "methods of this protocol to make API calls.\n"); + GenerateClientProtocol(service, &*printer, &vars); + GenerateClientClass(&*printer, &vars); + printer->Print("\n"); + GenerateServerProtocol(service, &*printer, &vars); + return output; +} + +grpc::string GenerateHeader() { + grpc::string code; + code += + "/// The following code is generated by the Flatbuffers library which " + "might not be in sync with grpc-swift\n"; + code += + "/// in case of an issue please open github issue, though it would be " + "maintained\n"; + code += "\n"; + code += "// swiftlint:disable all\n"; + code += "// swiftformat:disable all\n"; + code += "\n"; + code += "import Foundation\n"; + code += "import GRPC\n"; + code += "import NIO\n"; + code += "import NIOHTTP1\n"; + code += "import FlatBuffers\n"; + code += "\n"; + code += + "public protocol GRPCFlatBufPayload: GRPCPayload, FlatBufferGRPCMessage " + "{}\n"; + + code += "public extension GRPCFlatBufPayload {\n"; + code += " init(serializedByteBuffer: inout NIO.ByteBuffer) throws {\n"; + code += + " self.init(byteBuffer: FlatBuffers.ByteBuffer(contiguousBytes: " + "serializedByteBuffer.readableBytesView, count: " + "serializedByteBuffer.readableBytes))\n"; + code += " }\n"; + + code += " func serialize(into buffer: inout NIO.ByteBuffer) throws {\n"; + code += + " let buf = UnsafeRawBufferPointer(start: self.rawPointer, count: " + "Int(self.size))\n"; + code += " buffer.writeBytes(buf)\n"; + code += " }\n"; + code += "}\n"; + code += "extension Message: GRPCFlatBufPayload {}\n"; + return code; +} +} // namespace grpc_swift_generator diff --git a/contrib/libs/flatbuffers/grpc/src/compiler/swift_generator.h b/contrib/libs/flatbuffers/grpc/src/compiler/swift_generator.h new file mode 100644 index 0000000000..1639cb07c8 --- /dev/null +++ b/contrib/libs/flatbuffers/grpc/src/compiler/swift_generator.h @@ -0,0 +1,55 @@ +/* + * + * Copyright 2020, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include <memory> +#include <vector> + +#include "src/compiler/config.h" +#include "src/compiler/schema_interface.h" + +#ifndef GRPC_CUSTOM_STRING +# include <string> +# define GRPC_CUSTOM_STRING std::string +#endif + +namespace grpc { + +typedef GRPC_CUSTOM_STRING string; + +} // namespace grpc + +namespace grpc_swift_generator { +grpc::string Generate(grpc_generator::File *file, + const grpc_generator::Service *service); +grpc::string GenerateHeader(); +} // namespace grpc_swift_generator diff --git a/contrib/libs/flatbuffers/grpc/src/compiler/ts_generator.cc b/contrib/libs/flatbuffers/grpc/src/compiler/ts_generator.cc new file mode 100644 index 0000000000..e49fd8d925 --- /dev/null +++ b/contrib/libs/flatbuffers/grpc/src/compiler/ts_generator.cc @@ -0,0 +1,523 @@ +/* + * Copyright 2020 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * NOTE: The following implementation is a translation for the Swift-grpc + * generator since flatbuffers doesnt allow plugins for now. if an issue arises + * please open an issue in the flatbuffers repository. This file should always + * be maintained according to the Swift-grpc repository + */ + +#include <map> +#include <sstream> + +#include "flatbuffers/util.h" +#include "src/compiler/schema_interface.h" +#include "src/compiler/ts_generator.h" + +namespace grpc_ts_generator { + +grpc::string ToDasherizedCase(const grpc::string pascal_case) { + std::string dasherized_case; + char p = 0; + for (size_t i = 0; i < pascal_case.length(); i++) { + char const &c = pascal_case[i]; + if (flatbuffers::is_alpha_upper(c)) { + if (i > 0 && p != flatbuffers::kPathSeparator) dasherized_case += "-"; + dasherized_case += flatbuffers::CharToLower(c); + } else { + dasherized_case += c; + } + p = c; + } + return dasherized_case; +} + +grpc::string GenerateNamespace(const std::vector<std::string> namepsace, + const std::string filename, + const bool include_separator) { + grpc::string path = ""; + if (include_separator) path += "."; + + for (auto it = namepsace.begin(); it < namepsace.end(); it++) { + if (include_separator) path += "/"; + path += include_separator ? ToDasherizedCase(*it) : *it + "_"; + } + + if (include_separator) path += "/"; + path += include_separator ? ToDasherizedCase(filename) : filename; + return path; +} + +// MARK: - Shared code + +void GenerateImports(const grpc_generator::Service *service, + grpc_generator::Printer *printer, + std::map<grpc::string, grpc::string> *dictonary, + const bool grpc_var_import) { + auto vars = *dictonary; + printer->Print( + "// Generated GRPC code for FlatBuffers TS *** DO NOT EDIT ***\n"); + printer->Print("import * as flatbuffers from 'flatbuffers';\n"); + + std::set<grpc::string> generated_imports; + + for (auto it = 0; it < service->method_count(); it++) { + auto method = service->method(it); + auto output = method->get_output_type_name(); + auto input = method->get_input_type_name(); + auto input_namespace = method->get_input_namespace_parts(); + + vars["OUTPUT"] = output; + vars["INPUT"] = input; + + if (generated_imports.find(output) == generated_imports.end()) { + generated_imports.insert(output); + vars["OUTPUT_DIR"] = + GenerateNamespace(method->get_output_namespace_parts(), output, true); + vars["Output_alias"] = GenerateNamespace( + method->get_output_namespace_parts(), output, false); + printer->Print( + vars, "import { $OUTPUT$ as $Output_alias$ } from '$OUTPUT_DIR$';\n"); + } + if (generated_imports.find(input) == generated_imports.end()) { + generated_imports.insert(input); + vars["INPUT_DIR"] = + GenerateNamespace(method->get_output_namespace_parts(), input, true); + vars["Input_alias"] = + GenerateNamespace(method->get_output_namespace_parts(), input, false); + printer->Print( + vars, "import { $INPUT$ as $Input_alias$ } from '$INPUT_DIR$';\n"); + } + } + printer->Print("\n"); + if (grpc_var_import) + printer->Print("var grpc = require('grpc');\n"); + else + printer->Print("import * as grpc from 'grpc';\n"); + printer->Print("\n"); +} + +// MARK: - Generate Main GRPC Code + +void GetStreamType(grpc_generator::Printer *printer, + const grpc_generator::Method *method, + std::map<grpc::string, grpc::string> *dictonary) { + auto vars = *dictonary; + auto client_streaming = method->ClientStreaming() || method->BidiStreaming(); + auto server_streaming = method->ServerStreaming() || method->BidiStreaming(); + vars["ClientStreaming"] = client_streaming ? "true" : "false"; + vars["ServerStreaming"] = server_streaming ? "true" : "false"; + printer->Print(vars, "requestStream: $ClientStreaming$,\n"); + printer->Print(vars, "responseStream: $ServerStreaming$,\n"); +} + +void GenerateSerializeMethod(grpc_generator::Printer *printer, + std::map<grpc::string, grpc::string> *dictonary) { + auto vars = *dictonary; + printer->Print(vars, "function serialize_$Type$(buffer_args) {\n"); + printer->Indent(); + printer->Print(vars, "if (!(buffer_args instanceof $Type$)) {\n"); + printer->Indent(); + printer->Print(vars, + "throw new Error('Expected argument of type $VALUE$');\n"); + printer->Outdent(); + printer->Print("}\n"); + printer->Print(vars, "return buffer_args.serialize();\n"); + printer->Outdent(); + printer->Print("}\n\n"); +} + +void GenerateDeserializeMethod( + grpc_generator::Printer *printer, + std::map<grpc::string, grpc::string> *dictonary) { + auto vars = *dictonary; + printer->Print(vars, "function deserialize_$Type$(buffer) {\n"); + printer->Indent(); + printer->Print(vars, + "return $Type$.getRootAs$VALUE$(new " + "flatbuffers.ByteBuffer(buffer))\n"); + printer->Outdent(); + printer->Print("}\n\n"); +} + +void GenerateMethods(const grpc_generator::Service *service, + grpc_generator::Printer *printer, + std::map<grpc::string, grpc::string> *dictonary) { + auto vars = *dictonary; + + std::set<grpc::string> generated_functions; + + for (auto it = 0; it < service->method_count(); it++) { + auto method = service->method(it); + auto output = method->get_output_type_name(); + auto input = method->get_input_type_name(); + + if (generated_functions.find(output) == generated_functions.end()) { + generated_functions.insert(output); + vars["VALUE"] = output; + vars["Type"] = GenerateNamespace(method->get_output_namespace_parts(), + output, false); + GenerateSerializeMethod(printer, &vars); + GenerateDeserializeMethod(printer, &vars); + } + printer->Print("\n"); + if (generated_functions.find(input) == generated_functions.end()) { + generated_functions.insert(input); + vars["VALUE"] = input; + vars["Type"] = + GenerateNamespace(method->get_input_namespace_parts(), input, false); + GenerateSerializeMethod(printer, &vars); + GenerateDeserializeMethod(printer, &vars); + } + } +} + +void GenerateService(const grpc_generator::Service *service, + grpc_generator::Printer *printer, + std::map<grpc::string, grpc::string> *dictonary) { + auto vars = *dictonary; + vars["NAME"] = service->name() + "Service"; + + printer->Print(vars, "var $NAME$ = exports.$NAME$ = {\n"); + printer->Indent(); + for (auto it = 0; it < service->method_count(); it++) { + auto method = service->method(it); + vars["MethodName"] = method->name(); + vars["OUTPUT"] = GenerateNamespace(method->get_output_namespace_parts(), + method->get_output_type_name(), false); + vars["INPUT"] = GenerateNamespace(method->get_input_namespace_parts(), + method->get_input_type_name(), false); + printer->Print(vars, "$MethodName$: {\n"); + printer->Indent(); + printer->Print(vars, "path: '/$PATH$$ServiceName$/$MethodName$',\n"); + GetStreamType(printer, &*method, &vars); + printer->Print(vars, "requestType: flatbuffers.ByteBuffer,\n"); + printer->Print(vars, "responseType: $OUTPUT$,\n"); + printer->Print(vars, "requestSerialize: serialize_$INPUT$,\n"); + printer->Print(vars, "requestDeserialize: deserialize_$INPUT$,\n"); + printer->Print(vars, "responseSerialize: serialize_$OUTPUT$,\n"); + printer->Print(vars, "responseDeserialize: deserialize_$OUTPUT$,\n"); + printer->Outdent(); + printer->Print("},\n"); + } + printer->Outdent(); + printer->Print("};\n"); + printer->Print(vars, + "exports.$ServiceName$Client = " + "grpc.makeGenericClientConstructor($NAME$);"); +} + +grpc::string Generate(grpc_generator::File *file, + const grpc_generator::Service *service, + const grpc::string &filename) { + grpc::string output; + std::map<grpc::string, grpc::string> vars; + + vars["PATH"] = file->package(); + + if (!file->package().empty()) { vars["PATH"].append("."); } + + vars["ServiceName"] = service->name(); + vars["FBSFile"] = service->name() + "_fbs"; + vars["Filename"] = filename; + auto printer = file->CreatePrinter(&output); + + GenerateImports(service, &*printer, &vars, true); + GenerateMethods(service, &*printer, &vars); + GenerateService(service, &*printer, &vars); + return output; +} + +// MARK: - Generate Interface + +void FillInterface(grpc_generator::Printer *printer, + std::map<grpc::string, grpc::string> *dictonary) { + auto vars = *dictonary; + printer->Print(vars, + "interface I$ServiceName$Service_I$MethodName$ extends " + "grpc.MethodDefinition<$INPUT$, $OUTPUT$> {\n"); + printer->Indent(); + printer->Print(vars, "path: string; // /$PATH$$ServiceName$/$MethodName$\n"); + printer->Print(vars, "requestStream: boolean; // $ClientStreaming$\n"); + printer->Print(vars, "responseStream: boolean; // $ServerStreaming$\n"); + printer->Print(vars, "requestSerialize: grpc.serialize<$INPUT$>;\n"); + printer->Print(vars, "requestDeserialize: grpc.deserialize<$INPUT$>;\n"); + printer->Print(vars, "responseSerialize: grpc.serialize<$OUTPUT$>;\n"); + printer->Print(vars, "responseDeserialize: grpc.deserialize<$OUTPUT$>;\n"); + printer->Outdent(); + printer->Print("}\n"); +} + +void GenerateInterfaces(const grpc_generator::Service *service, + grpc_generator::Printer *printer, + std::map<grpc::string, grpc::string> *dictonary) { + auto vars = *dictonary; + for (auto it = 0; it < service->method_count(); it++) { + auto method = service->method(it); + auto client_streaming = + method->ClientStreaming() || method->BidiStreaming(); + auto server_streaming = + method->ServerStreaming() || method->BidiStreaming(); + vars["ClientStreaming"] = client_streaming ? "true" : "false"; + vars["ServerStreaming"] = server_streaming ? "true" : "false"; + vars["MethodName"] = method->name(); + vars["OUTPUT"] = GenerateNamespace(method->get_output_namespace_parts(), + method->get_output_type_name(), false); + vars["INPUT"] = GenerateNamespace(method->get_input_namespace_parts(), + method->get_input_type_name(), false); + FillInterface(printer, &vars); + printer->Print("\n"); + } +} + +void GenerateExportedInterface( + const grpc_generator::Service *service, grpc_generator::Printer *printer, + std::map<grpc::string, grpc::string> *dictonary) { + auto vars = *dictonary; + printer->Print(vars, "export interface I$ServiceName$Server {\n"); + printer->Indent(); + for (auto it = 0; it < service->method_count(); it++) { + auto method = service->method(it); + vars["Name"] = method->name(); + vars["OUTPUT"] = GenerateNamespace(method->get_output_namespace_parts(), + method->get_output_type_name(), false); + vars["INPUT"] = GenerateNamespace(method->get_input_namespace_parts(), + method->get_input_type_name(), false); + if (method->BidiStreaming()) { + printer->Print(vars, + "$Name$: grpc.handleBidiStreamingCall<$INPUT$, " + "$OUTPUT$>;\n"); + continue; + } + if (method->NoStreaming()) { + printer->Print(vars, + "$Name$: grpc.handleUnaryCall<$INPUT$, " + "$OUTPUT$>;\n"); + continue; + } + if (method->ClientStreaming()) { + printer->Print(vars, + "$Name$: grpc.handleClientStreamingCall<$INPUT$, " + "$OUTPUT$>;\n"); + continue; + } + if (method->ServerStreaming()) { + printer->Print(vars, + "$Name$: grpc.handleServerStreamingCall<$INPUT$, " + "$OUTPUT$>;\n"); + continue; + } + } + printer->Outdent(); + printer->Print("}\n"); +} + +void GenerateMainInterface(const grpc_generator::Service *service, + grpc_generator::Printer *printer, + std::map<grpc::string, grpc::string> *dictonary) { + auto vars = *dictonary; + printer->Print( + vars, + "interface I$ServiceName$Service extends " + "grpc.ServiceDefinition<grpc.UntypedServiceImplementation> {\n"); + printer->Indent(); + for (auto it = 0; it < service->method_count(); it++) { + auto method = service->method(it); + vars["MethodName"] = method->name(); + printer->Print(vars, + "$MethodName$: I$ServiceName$Service_I$MethodName$;\n"); + } + printer->Outdent(); + printer->Print("}\n"); + GenerateInterfaces(service, printer, &vars); + printer->Print("\n"); + printer->Print(vars, + "export const $ServiceName$Service: I$ServiceName$Service;\n"); + printer->Print("\n"); + GenerateExportedInterface(service, printer, &vars); +} + +grpc::string GenerateMetaData() { return "metadata: grpc.Metadata"; } + +grpc::string GenerateOptions() { return "options: Partial<grpc.CallOptions>"; } + +void GenerateUnaryClientInterface( + grpc_generator::Printer *printer, + std::map<grpc::string, grpc::string> *dictonary) { + auto vars = *dictonary; + grpc::string main = "$ISPUBLIC$$MethodName$(request: $INPUT$, "; + grpc::string callback = + "callback: (error: grpc.ServiceError | null, response: " + "$OUTPUT$) => void): grpc.ClientUnaryCall;\n"; + auto meta_data = GenerateMetaData() + ", "; + auto options = GenerateOptions() + ", "; + printer->Print(vars, (main + callback).c_str()); + printer->Print(vars, (main + meta_data + callback).c_str()); + printer->Print(vars, (main + meta_data + options + callback).c_str()); +} + +void GenerateClientWriteStreamInterface( + grpc_generator::Printer *printer, + std::map<grpc::string, grpc::string> *dictonary) { + auto vars = *dictonary; + grpc::string main = "$ISPUBLIC$$MethodName$("; + grpc::string callback = + "callback: (error: grpc.ServiceError | null, response: " + "$INPUT$) => void): " + "grpc.ClientWritableStream<$OUTPUT$>;\n"; + auto meta_data = GenerateMetaData() + ", "; + auto options = GenerateOptions() + ", "; + printer->Print(vars, (main + callback).c_str()); + printer->Print(vars, (main + meta_data + callback).c_str()); + printer->Print(vars, (main + options + callback).c_str()); + printer->Print(vars, (main + meta_data + options + callback).c_str()); +} + +void GenerateClientReadableStreamInterface( + grpc_generator::Printer *printer, + std::map<grpc::string, grpc::string> *dictonary) { + auto vars = *dictonary; + grpc::string main = "$ISPUBLIC$$MethodName$(request: $INPUT$, "; + grpc::string end_function = "): grpc.ClientReadableStream<$OUTPUT$>;\n"; + auto meta_data = GenerateMetaData(); + auto options = GenerateOptions(); + printer->Print(vars, (main + meta_data + end_function).c_str()); + printer->Print(vars, (main + options + end_function).c_str()); +} + +void GenerateDepluxStreamInterface( + grpc_generator::Printer *printer, + std::map<grpc::string, grpc::string> *dictonary) { + auto vars = *dictonary; + grpc::string main = "$ISPUBLIC$$MethodName$("; + grpc::string end_function = + "): grpc.ClientDuplexStream<$INPUT$, $OUTPUT$>;\n"; + auto meta_data = GenerateMetaData(); + auto options = GenerateOptions(); + printer->Print(vars, (main + end_function).c_str()); + printer->Print(vars, (main + options + end_function).c_str()); + printer->Print(vars, (main + meta_data + + ", options?: Partial<grpc.CallOptions>" + end_function) + .c_str()); +} + +void GenerateClientInterface(const grpc_generator::Service *service, + grpc_generator::Printer *printer, + std::map<grpc::string, grpc::string> *dictonary) { + auto vars = *dictonary; + printer->Print(vars, "export interface I$ServiceName$Client {\n"); + printer->Indent(); + for (auto it = 0; it < service->method_count(); it++) { + auto method = service->method(it); + vars["MethodName"] = method->name(); + vars["OUTPUT"] = GenerateNamespace(method->get_output_namespace_parts(), + method->get_output_type_name(), false); + vars["INPUT"] = GenerateNamespace(method->get_input_namespace_parts(), + method->get_input_type_name(), false); + vars["ISPUBLIC"] = ""; + + if (method->NoStreaming()) { + GenerateUnaryClientInterface(printer, &vars); + continue; + } + if (method->BidiStreaming()) { + GenerateDepluxStreamInterface(printer, &vars); + continue; + } + + if (method->ClientStreaming()) { + GenerateClientWriteStreamInterface(printer, &vars); + continue; + } + + if (method->ServerStreaming()) { + GenerateClientReadableStreamInterface(printer, &vars); + continue; + } + } + printer->Outdent(); + printer->Print("}\n"); +} + +void GenerateClientClassInterface( + const grpc_generator::Service *service, grpc_generator::Printer *printer, + std::map<grpc::string, grpc::string> *dictonary) { + auto vars = *dictonary; + printer->Print(vars, + "export class $ServiceName$Client extends grpc.Client " + "implements I$ServiceName$Client {\n"); + printer->Indent(); + printer->Print( + "constructor(address: string, credentials: grpc.ChannelCredentials, " + "options?: object);"); + for (auto it = 0; it < service->method_count(); it++) { + auto method = service->method(it); + vars["MethodName"] = method->name(); + vars["OUTPUT"] = GenerateNamespace(method->get_output_namespace_parts(), + method->get_output_type_name(), false); + vars["INPUT"] = GenerateNamespace(method->get_input_namespace_parts(), + method->get_input_type_name(), false); + vars["ISPUBLIC"] = "public "; + if (method->NoStreaming()) { + GenerateUnaryClientInterface(printer, &vars); + continue; + } + if (method->BidiStreaming()) { + GenerateDepluxStreamInterface(printer, &vars); + continue; + } + + if (method->ClientStreaming()) { + GenerateClientWriteStreamInterface(printer, &vars); + continue; + } + + if (method->ServerStreaming()) { + GenerateClientReadableStreamInterface(printer, &vars); + continue; + } + } + printer->Outdent(); + printer->Print("}\n"); +} + +grpc::string GenerateInterface(grpc_generator::File *file, + const grpc_generator::Service *service, + const grpc::string &filename) { + grpc::string output; + + std::set<grpc::string> generated_functions; + std::map<grpc::string, grpc::string> vars; + + vars["PATH"] = file->package(); + + if (!file->package().empty()) { vars["PATH"].append("."); } + + vars["ServiceName"] = service->name(); + vars["FBSFile"] = service->name() + "_fbs"; + vars["Filename"] = filename; + auto printer = file->CreatePrinter(&output); + + GenerateImports(service, &*printer, &vars, false); + GenerateMainInterface(service, &*printer, &vars); + printer->Print("\n"); + GenerateClientInterface(service, &*printer, &vars); + printer->Print("\n"); + GenerateClientClassInterface(service, &*printer, &vars); + return output; +} +} // namespace grpc_ts_generator diff --git a/contrib/libs/flatbuffers/grpc/src/compiler/ts_generator.h b/contrib/libs/flatbuffers/grpc/src/compiler/ts_generator.h new file mode 100644 index 0000000000..a33bb3c5d2 --- /dev/null +++ b/contrib/libs/flatbuffers/grpc/src/compiler/ts_generator.h @@ -0,0 +1,61 @@ +/* + * + * Copyright 2020, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include <memory> +#include <vector> +#include <set> + +#include "src/compiler/config.h" +#include "src/compiler/schema_interface.h" + +#ifndef GRPC_CUSTOM_STRING +# include <string> +# define GRPC_CUSTOM_STRING std::string +#endif + +namespace grpc { + +typedef GRPC_CUSTOM_STRING string; + +} // namespace grpc + +namespace grpc_ts_generator { +grpc::string Generate(grpc_generator::File *file, + const grpc_generator::Service *service, + const grpc::string &filename); + +grpc::string GenerateInterface(grpc_generator::File *file, + const grpc_generator::Service *service, + const grpc::string &filename); +} // namespace grpc_ts_generator + |