mirror of https://github.com/grpc/grpc.git
Change on 2014/12/10 by nnoble <nnoble@google.com> ------------- Created by MOE: http://code.google.com/p/moe-java MOE_MIGRATED_REVID=81829127pull/1/merge
parent
0005b778ee
commit
ebebb7e21c
13 changed files with 1356 additions and 3 deletions
@ -0,0 +1,451 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2014, 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 "src/compiler/cpp_generator.h" |
||||
|
||||
#include "src/compiler/cpp_generator_helpers.h" |
||||
#include <google/protobuf/descriptor.h> |
||||
#include <google/protobuf/descriptor.pb.h> |
||||
#include <google/protobuf/io/printer.h> |
||||
#include <google/protobuf/io/zero_copy_stream_impl_lite.h> |
||||
|
||||
namespace grpc_cpp_generator { |
||||
namespace { |
||||
|
||||
bool NoStreaming(const google::protobuf::MethodDescriptor* method) { |
||||
return !method->options().has_client_streaming() && |
||||
!method->options().has_server_streaming(); |
||||
} |
||||
|
||||
bool ClientOnlyStreaming(const google::protobuf::MethodDescriptor* method) { |
||||
return method->options().has_client_streaming() && |
||||
!method->options().has_server_streaming(); |
||||
} |
||||
|
||||
bool ServerOnlyStreaming(const google::protobuf::MethodDescriptor* method) { |
||||
return !method->options().has_client_streaming() && |
||||
method->options().has_server_streaming(); |
||||
} |
||||
|
||||
bool BidiStreaming(const google::protobuf::MethodDescriptor* method) { |
||||
return method->options().has_client_streaming() && |
||||
method->options().has_server_streaming(); |
||||
} |
||||
|
||||
bool HasClientOnlyStreaming(const google::protobuf::FileDescriptor* file) { |
||||
for (int i = 0; i < file->service_count(); i++) { |
||||
for (int j = 0; j < file->service(i)->method_count(); j++) { |
||||
if (ClientOnlyStreaming(file->service(i)->method(j))) { |
||||
return true; |
||||
} |
||||
} |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
bool HasServerOnlyStreaming(const google::protobuf::FileDescriptor* file) { |
||||
for (int i = 0; i < file->service_count(); i++) { |
||||
for (int j = 0; j < file->service(i)->method_count(); j++) { |
||||
if (ServerOnlyStreaming(file->service(i)->method(j))) { |
||||
return true; |
||||
} |
||||
} |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
bool HasBidiStreaming(const google::protobuf::FileDescriptor* file) { |
||||
for (int i = 0; i < file->service_count(); i++) { |
||||
for (int j = 0; j < file->service(i)->method_count(); j++) { |
||||
if (BidiStreaming(file->service(i)->method(j))) { |
||||
return true; |
||||
} |
||||
} |
||||
} |
||||
return false; |
||||
} |
||||
} // namespace
|
||||
|
||||
string GetHeaderIncludes(const google::protobuf::FileDescriptor* file) { |
||||
string temp = |
||||
"#include \"net/grpc/cpp/internal/client/internal_stub.h\"\n" |
||||
"#include \"net/grpc/cpp/public/status.h\"\n" |
||||
"\n" |
||||
"namespace grpc {\n" |
||||
"class ChannelInterface;\n" |
||||
"class RpcService;\n"; |
||||
if (HasClientOnlyStreaming(file)) { |
||||
temp.append("template <class OutMessage> class ClientWriter;\n"); |
||||
temp.append("template <class InMessage> class ServerReader;\n"); |
||||
} |
||||
if (HasServerOnlyStreaming(file)) { |
||||
temp.append("template <class InMessage> class ClientReader;\n"); |
||||
temp.append("template <class OutMessage> class ServerWriter;\n"); |
||||
} |
||||
if (HasBidiStreaming(file)) { |
||||
temp.append( |
||||
"template <class OutMessage, class InMessage>\n" |
||||
"class ClientReaderWriter;\n"); |
||||
temp.append( |
||||
"template <class OutMessage, class InMessage>\n" |
||||
"class ServerReaderWriter;\n"); |
||||
} |
||||
temp.append("} // namespace grpc\n"); |
||||
return temp; |
||||
} |
||||
|
||||
string GetSourceIncludes() { |
||||
return "#include \"net/grpc/cpp/internal/rpc_method.h\"\n" |
||||
"#include \"net/grpc/cpp/internal/server/rpc_service_method.h\"\n" |
||||
"#include \"net/grpc/cpp/public/channel_interface.h\"\n" |
||||
"#include \"net/grpc/cpp/public/stream.h\"\n"; |
||||
} |
||||
|
||||
void PrintHeaderClientMethod(google::protobuf::io::Printer* printer, |
||||
const google::protobuf::MethodDescriptor* method, |
||||
map<string, string>* vars) { |
||||
(*vars)["Method"] = method->name(); |
||||
(*vars)["Request"] = |
||||
grpc_cpp_generator::ClassName(method->input_type(), true); |
||||
(*vars)["Response"] = |
||||
grpc_cpp_generator::ClassName(method->output_type(), true); |
||||
if (NoStreaming(method)) { |
||||
printer->Print(*vars, |
||||
"::grpc::Status $Method$(::grpc::ClientContext* context, " |
||||
"const $Request$& request, $Response$* response);\n\n"); |
||||
} else if (ClientOnlyStreaming(method)) { |
||||
printer->Print( |
||||
*vars, |
||||
"::grpc::ClientWriter<$Request$>* $Method$(" |
||||
"::grpc::ClientContext* context, $Response$* response);\n\n"); |
||||
} else if (ServerOnlyStreaming(method)) { |
||||
printer->Print( |
||||
*vars, |
||||
"::grpc::ClientReader<$Response$>* $Method$(" |
||||
"::grpc::ClientContext* context, const $Request$* request);\n\n"); |
||||
} else if (BidiStreaming(method)) { |
||||
printer->Print(*vars, |
||||
"::grpc::ClientReaderWriter<$Request$, $Response$>* " |
||||
"$Method$(::grpc::ClientContext* context);\n\n"); |
||||
} |
||||
} |
||||
|
||||
void PrintHeaderServerMethod(google::protobuf::io::Printer* printer, |
||||
const google::protobuf::MethodDescriptor* method, |
||||
map<string, string>* vars) { |
||||
(*vars)["Method"] = method->name(); |
||||
(*vars)["Request"] = |
||||
grpc_cpp_generator::ClassName(method->input_type(), true); |
||||
(*vars)["Response"] = |
||||
grpc_cpp_generator::ClassName(method->output_type(), true); |
||||
if (NoStreaming(method)) { |
||||
printer->Print(*vars, |
||||
"virtual ::grpc::Status $Method$(const $Request$* request, " |
||||
"$Response$* response);\n"); |
||||
} else if (ClientOnlyStreaming(method)) { |
||||
printer->Print(*vars, |
||||
"virtual ::grpc::Status $Method$(" |
||||
"::grpc::ServerReader<$Request$>* reader, " |
||||
"$Response$* response);\n"); |
||||
} else if (ServerOnlyStreaming(method)) { |
||||
printer->Print(*vars, |
||||
"virtual ::grpc::Status $Method$(const $Request$* request, " |
||||
"::grpc::ServerWriter<$Response$>* writer);\n"); |
||||
} else if (BidiStreaming(method)) { |
||||
printer->Print(*vars, |
||||
"virtual ::grpc::Status $Method$(" |
||||
"::grpc::ServerReaderWriter<$Response$, $Request$>* stream);" |
||||
"\n"); |
||||
} |
||||
} |
||||
|
||||
void PrintHeaderService(google::protobuf::io::Printer* printer, |
||||
const google::protobuf::ServiceDescriptor* service, |
||||
map<string, string>* vars) { |
||||
(*vars)["Service"] = service->name(); |
||||
|
||||
printer->Print(*vars, |
||||
"class $Service$ {\n" |
||||
" public:\n"); |
||||
printer->Indent(); |
||||
|
||||
// Client side
|
||||
printer->Print("class Stub : public ::grpc::InternalStub {\n" |
||||
" public:\n"); |
||||
printer->Indent(); |
||||
for (int i = 0; i < service->method_count(); ++i) { |
||||
PrintHeaderClientMethod(printer, service->method(i), vars); |
||||
} |
||||
printer->Outdent(); |
||||
printer->Print("};\n"); |
||||
printer->Print( |
||||
"static Stub* NewStub(const std::shared_ptr<::grpc::ChannelInterface>& " |
||||
"channel);\n"); |
||||
|
||||
printer->Print("\n"); |
||||
|
||||
// Server side
|
||||
printer->Print("class Service {\n" |
||||
" public:\n"); |
||||
printer->Indent(); |
||||
printer->Print("Service() : service_(nullptr) {}\n"); |
||||
printer->Print("virtual ~Service();\n"); |
||||
for (int i = 0; i < service->method_count(); ++i) { |
||||
PrintHeaderServerMethod(printer, service->method(i), vars); |
||||
} |
||||
printer->Print("::grpc::RpcService* service();\n"); |
||||
printer->Outdent(); |
||||
printer->Print(" private:\n" |
||||
" ::grpc::RpcService* service_;\n"); |
||||
printer->Print("};\n"); |
||||
|
||||
printer->Outdent(); |
||||
printer->Print("};\n"); |
||||
} |
||||
|
||||
string GetHeaderServices(const google::protobuf::FileDescriptor* file) { |
||||
string output; |
||||
google::protobuf::io::StringOutputStream output_stream(&output); |
||||
google::protobuf::io::Printer printer(&output_stream, '$'); |
||||
map<string, string> vars; |
||||
|
||||
for (int i = 0; i < file->service_count(); ++i) { |
||||
PrintHeaderService(&printer, file->service(0), &vars); |
||||
printer.Print("\n"); |
||||
} |
||||
return output; |
||||
} |
||||
|
||||
void PrintSourceClientMethod(google::protobuf::io::Printer* printer, |
||||
const google::protobuf::MethodDescriptor* method, |
||||
map<string, string>* vars) { |
||||
(*vars)["Method"] = method->name(); |
||||
(*vars)["Request"] = |
||||
grpc_cpp_generator::ClassName(method->input_type(), true); |
||||
(*vars)["Response"] = |
||||
grpc_cpp_generator::ClassName(method->output_type(), true); |
||||
if (NoStreaming(method)) { |
||||
printer->Print(*vars, |
||||
"::grpc::Status $Service$::Stub::$Method$(" |
||||
"::grpc::ClientContext* context, " |
||||
"const $Request$& request, $Response$* response) {\n"); |
||||
printer->Print(*vars, |
||||
" return channel()->StartBlockingRpc(" |
||||
"::grpc::RpcMethod(\"/$Service$/$Method$\"), " |
||||
"context, request, response);\n" |
||||
"}\n\n"); |
||||
} else if (ClientOnlyStreaming(method)) { |
||||
printer->Print(*vars, |
||||
"::grpc::ClientWriter<$Request$>* $Service$::Stub::$Method$(" |
||||
"::grpc::ClientContext* context, $Response$* response) {\n"); |
||||
printer->Print( |
||||
*vars, |
||||
" return new ::grpc::ClientWriter<$Request$>(" |
||||
"channel()->CreateStream(::grpc::RpcMethod(\"/$Service$/$Method$\", " |
||||
"::grpc::RpcMethod::RpcType::CLIENT_STREAMING), " |
||||
"context, nullptr, response));\n" |
||||
"}\n\n"); |
||||
} else if (ServerOnlyStreaming(method)) { |
||||
printer->Print( |
||||
*vars, |
||||
"::grpc::ClientReader<$Response$>* $Service$::Stub::$Method$(" |
||||
"::grpc::ClientContext* context, const $Request$* request) {\n"); |
||||
printer->Print( |
||||
*vars, |
||||
" return new ::grpc::ClientReader<$Response$>(" |
||||
"channel()->CreateStream(::grpc::RpcMethod(\"/$Service$/$Method$\", " |
||||
"::grpc::RpcMethod::RpcType::SERVER_STREAMING), " |
||||
"context, request, nullptr));\n" |
||||
"}\n\n"); |
||||
} else if (BidiStreaming(method)) { |
||||
printer->Print( |
||||
*vars, |
||||
"::grpc::ClientReaderWriter<$Request$, $Response$>* " |
||||
"$Service$::Stub::$Method$(::grpc::ClientContext* context) {\n"); |
||||
printer->Print( |
||||
*vars, |
||||
" return new ::grpc::ClientReaderWriter<$Request$, $Response$>(" |
||||
"channel()->CreateStream(::grpc::RpcMethod(\"/$Service$/$Method$\", " |
||||
"::grpc::RpcMethod::RpcType::BIDI_STREAMING), " |
||||
"context, nullptr, nullptr));\n" |
||||
"}\n\n"); |
||||
} |
||||
} |
||||
|
||||
void PrintSourceServerMethod(google::protobuf::io::Printer* printer, |
||||
const google::protobuf::MethodDescriptor* method, |
||||
map<string, string>* vars) { |
||||
(*vars)["Method"] = method->name(); |
||||
(*vars)["Request"] = |
||||
grpc_cpp_generator::ClassName(method->input_type(), true); |
||||
(*vars)["Response"] = |
||||
grpc_cpp_generator::ClassName(method->output_type(), true); |
||||
if (NoStreaming(method)) { |
||||
printer->Print(*vars, |
||||
"::grpc::Status $Service$::Service::$Method$(" |
||||
"const $Request$* request, $Response$* response) {\n"); |
||||
printer->Print( |
||||
" return ::grpc::Status(" |
||||
"::grpc::StatusCode::UNIMPLEMENTED);\n"); |
||||
printer->Print("}\n\n"); |
||||
} else if (ClientOnlyStreaming(method)) { |
||||
printer->Print(*vars, |
||||
"::grpc::Status $Service$::Service::$Method$(" |
||||
"::grpc::ServerReader<$Request$>* reader, " |
||||
"$Response$* response) {\n"); |
||||
printer->Print( |
||||
" return ::grpc::Status(" |
||||
"::grpc::StatusCode::UNIMPLEMENTED);\n"); |
||||
printer->Print("}\n\n"); |
||||
} else if (ServerOnlyStreaming(method)) { |
||||
printer->Print(*vars, |
||||
"::grpc::Status $Service$::Service::$Method$(" |
||||
"const $Request$* request, " |
||||
"::grpc::ServerWriter<$Response$>* writer) {\n"); |
||||
printer->Print( |
||||
" return ::grpc::Status(" |
||||
"::grpc::StatusCode::UNIMPLEMENTED);\n"); |
||||
printer->Print("}\n\n"); |
||||
} else if (BidiStreaming(method)) { |
||||
printer->Print(*vars, |
||||
"::grpc::Status $Service$::Service::$Method$(" |
||||
"::grpc::ServerReaderWriter<$Response$, $Request$>* " |
||||
"stream) {\n"); |
||||
printer->Print( |
||||
" return ::grpc::Status(" |
||||
"::grpc::StatusCode::UNIMPLEMENTED);\n"); |
||||
printer->Print("}\n\n"); |
||||
} |
||||
} |
||||
|
||||
void PrintSourceService(google::protobuf::io::Printer* printer, |
||||
const google::protobuf::ServiceDescriptor* service, |
||||
map<string, string>* vars) { |
||||
(*vars)["Service"] = service->name(); |
||||
printer->Print(*vars, |
||||
"$Service$::Stub* $Service$::NewStub(" |
||||
"const std::shared_ptr<::grpc::ChannelInterface>& channel) {\n" |
||||
" $Service$::Stub* stub = new $Service$::Stub();\n" |
||||
" stub->set_channel(channel);\n" |
||||
" return stub;\n" |
||||
"};\n\n"); |
||||
for (int i = 0; i < service->method_count(); ++i) { |
||||
PrintSourceClientMethod(printer, service->method(i), vars); |
||||
} |
||||
|
||||
printer->Print(*vars, |
||||
"$Service$::Service::~Service() {\n" |
||||
" delete service_;\n" |
||||
"}\n\n"); |
||||
for (int i = 0; i < service->method_count(); ++i) { |
||||
PrintSourceServerMethod(printer, service->method(i), vars); |
||||
} |
||||
printer->Print(*vars, |
||||
"::grpc::RpcService* $Service$::Service::service() {\n"); |
||||
printer->Indent(); |
||||
printer->Print("if (service_ != nullptr) {\n" |
||||
" return service_;\n" |
||||
"}\n"); |
||||
printer->Print("service_ = new ::grpc::RpcService();\n"); |
||||
for (int i = 0; i < service->method_count(); ++i) { |
||||
const google::protobuf::MethodDescriptor* method = service->method(i); |
||||
(*vars)["Method"] = method->name(); |
||||
(*vars)["Request"] = |
||||
grpc_cpp_generator::ClassName(method->input_type(), true); |
||||
(*vars)["Response"] = |
||||
grpc_cpp_generator::ClassName(method->output_type(), true); |
||||
if (NoStreaming(method)) { |
||||
printer->Print( |
||||
*vars, |
||||
"service_->AddMethod(new ::grpc::RpcServiceMethod(\n" |
||||
" \"/$Service$/$Method$\", ::grpc::RpcMethod::NORMAL_RPC,\n" |
||||
" new ::grpc::RpcMethodHandler<$Service$::Service, $Request$, " |
||||
"$Response$>(\n" |
||||
" std::function<::grpc::Status($Service$::Service*, " |
||||
"const $Request$*, $Response$*)>(" |
||||
"&$Service$::Service::$Method$), this),\n" |
||||
" new $Request$, new $Response$));\n"); |
||||
} else if (ClientOnlyStreaming(method)) { |
||||
printer->Print( |
||||
*vars, |
||||
"service_->AddMethod(new ::grpc::RpcServiceMethod(\n" |
||||
" \"/$Service$/$Method$\", ::grpc::RpcMethod::CLIENT_STREAMING,\n" |
||||
" new ::grpc::ClientStreamingHandler<" |
||||
"$Service$::Service, $Request$, $Response$>(\n" |
||||
" std::function<::grpc::Status($Service$::Service*, " |
||||
"::grpc::ServerReader<$Request$>*, $Response$*)>(" |
||||
"&$Service$::Service::$Method$), this),\n" |
||||
" new $Request$, new $Response$));\n"); |
||||
} else if (ServerOnlyStreaming(method)) { |
||||
printer->Print( |
||||
*vars, |
||||
"service_->AddMethod(new ::grpc::RpcServiceMethod(\n" |
||||
" \"/$Service$/$Method$\", ::grpc::RpcMethod::SERVER_STREAMING,\n" |
||||
" new ::grpc::ServerStreamingHandler<" |
||||
"$Service$::Service, $Request$, $Response$>(\n" |
||||
" std::function<::grpc::Status($Service$::Service*, " |
||||
"const $Request$*, ::grpc::ServerWriter<$Response$>*)>(" |
||||
"&$Service$::Service::$Method$), this),\n" |
||||
" new $Request$, new $Response$));\n"); |
||||
} else if (BidiStreaming(method)) { |
||||
printer->Print( |
||||
*vars, |
||||
"service_->AddMethod(new ::grpc::RpcServiceMethod(\n" |
||||
" \"/$Service$/$Method$\", ::grpc::RpcMethod::BIDI_STREAMING,\n" |
||||
" new ::grpc::BidiStreamingHandler<" |
||||
"$Service$::Service, $Request$, $Response$>(\n" |
||||
" std::function<::grpc::Status($Service$::Service*, " |
||||
"::grpc::ServerReaderWriter<$Response$, $Request$>*)>(" |
||||
"&$Service$::Service::$Method$), this),\n" |
||||
" new $Request$, new $Response$));\n"); |
||||
} |
||||
} |
||||
printer->Print("return service_;\n"); |
||||
printer->Outdent(); |
||||
printer->Print("}\n\n"); |
||||
} |
||||
|
||||
string GetSourceServices(const google::protobuf::FileDescriptor* file) { |
||||
string output; |
||||
google::protobuf::io::StringOutputStream output_stream(&output); |
||||
google::protobuf::io::Printer printer(&output_stream, '$'); |
||||
map<string, string> vars; |
||||
|
||||
for (int i = 0; i < file->service_count(); ++i) { |
||||
PrintSourceService(&printer, file->service(0), &vars); |
||||
printer.Print("\n"); |
||||
} |
||||
return output; |
||||
} |
||||
|
||||
} // namespace grpc_cpp_generator
|
@ -0,0 +1,63 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2014, 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 NET_GRPC_COMPILER_CPP_GENERATOR_H_ |
||||
#define NET_GRPC_COMPILER_CPP_GENERATOR_H_ |
||||
|
||||
#include <string> |
||||
|
||||
namespace google { |
||||
namespace protobuf { |
||||
class FileDescriptor; |
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
using namespace std; |
||||
|
||||
namespace grpc_cpp_generator { |
||||
|
||||
// Return the includes needed for generated header file.
|
||||
string GetHeaderIncludes(const google::protobuf::FileDescriptor* file); |
||||
|
||||
// Return the includes needed for generated source file.
|
||||
string GetSourceIncludes(); |
||||
|
||||
// Return the services for generated header file.
|
||||
string GetHeaderServices(const google::protobuf::FileDescriptor* file); |
||||
|
||||
// Return the services for generated source file.
|
||||
string GetSourceServices(const google::protobuf::FileDescriptor* file); |
||||
|
||||
} // namespace grpc_cpp_generator
|
||||
|
||||
#endif // NET_GRPC_COMPILER_CPP_GENERATOR_H_
|
@ -0,0 +1,106 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2014, 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 NET_GRPC_COMPILER_CPP_GENERATOR_HELPERS_H__ |
||||
#define NET_GRPC_COMPILER_CPP_GENERATOR_HELPERS_H__ |
||||
|
||||
#include <map> |
||||
#include <string> |
||||
#include <google/protobuf/descriptor.h> |
||||
#include <google/protobuf/descriptor.pb.h> |
||||
|
||||
using namespace std; |
||||
|
||||
namespace grpc_cpp_generator { |
||||
|
||||
inline bool StripSuffix(string* filename, const string& suffix) { |
||||
if (filename->length() >= suffix.length()) { |
||||
size_t suffix_pos = filename->length() - suffix.length(); |
||||
if (filename->compare(suffix_pos, string::npos, suffix) == 0) { |
||||
filename->resize(filename->size() - suffix.size()); |
||||
return true; |
||||
} |
||||
} |
||||
|
||||
return false; |
||||
} |
||||
|
||||
inline string StripProto(string filename) { |
||||
if (!StripSuffix(&filename, ".protodevel")) { |
||||
StripSuffix(&filename, ".proto"); |
||||
} |
||||
return filename; |
||||
} |
||||
|
||||
inline string StringReplace(string str, const string& from, const string& to) { |
||||
size_t pos = 0; |
||||
|
||||
for (;;) { |
||||
pos = str.find(from, pos); |
||||
if (pos == string::npos) { |
||||
break; |
||||
} |
||||
str.replace(pos, from.length(), to); |
||||
pos += to.length(); |
||||
} |
||||
|
||||
return str; |
||||
} |
||||
|
||||
inline string DotsToColons(const string& name) { |
||||
return StringReplace(name, ".", "::"); |
||||
} |
||||
|
||||
inline string DotsToUnderscores(const string& name) { |
||||
return StringReplace(name, ".", "_"); |
||||
} |
||||
|
||||
inline string ClassName(const google::protobuf::Descriptor* descriptor, bool qualified) { |
||||
// Find "outer", the descriptor of the top-level message in which
|
||||
// "descriptor" is embedded.
|
||||
const google::protobuf::Descriptor* outer = descriptor; |
||||
while (outer->containing_type() != NULL) outer = outer->containing_type(); |
||||
|
||||
const string& outer_name = outer->full_name(); |
||||
string inner_name = descriptor->full_name().substr(outer_name.size()); |
||||
|
||||
if (qualified) { |
||||
return "::" + DotsToColons(outer_name) + DotsToUnderscores(inner_name); |
||||
} else { |
||||
return outer->name() + DotsToUnderscores(inner_name); |
||||
} |
||||
} |
||||
|
||||
} // namespace grpc_cpp_generator
|
||||
|
||||
#endif // NET_GRPC_COMPILER_CPP_GENERATOR_HELPERS_H__
|
@ -0,0 +1,94 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2014, 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. |
||||
* |
||||
*/ |
||||
|
||||
// Generates cpp gRPC service interface out of Protobuf IDL.
|
||||
//
|
||||
|
||||
#include <memory> |
||||
#include "src/compiler/cpp_generator.h" |
||||
#include "src/compiler/cpp_generator_helpers.h" |
||||
#include <google/protobuf/descriptor.h> |
||||
#include <google/protobuf/descriptor.pb.h> |
||||
#include <google/protobuf/compiler/code_generator.h> |
||||
#include <google/protobuf/compiler/plugin.h> |
||||
#include <google/protobuf/io/coded_stream.h> |
||||
#include <google/protobuf/io/zero_copy_stream.h> |
||||
|
||||
class CppGrpcGenerator : public google::protobuf::compiler::CodeGenerator { |
||||
public: |
||||
CppGrpcGenerator() {} |
||||
virtual ~CppGrpcGenerator() {} |
||||
|
||||
virtual bool Generate(const google::protobuf::FileDescriptor* file, |
||||
const string& parameter, |
||||
google::protobuf::compiler::GeneratorContext* context, |
||||
string* error) const { |
||||
if (file->options().cc_generic_services()) { |
||||
*error = "cpp grpc proto compiler plugin does not work with generic " |
||||
"services. To generate cpp grpc APIs, please set \"" |
||||
"cc_generic_service = false\"."; |
||||
return false; |
||||
} |
||||
|
||||
string file_name = grpc_cpp_generator::StripProto(file->name()); |
||||
|
||||
// Generate .pb.h
|
||||
Insert(context, file_name + ".pb.h", "includes", |
||||
grpc_cpp_generator::GetHeaderIncludes(file)); |
||||
Insert(context, file_name + ".pb.h", "namespace_scope", |
||||
grpc_cpp_generator::GetHeaderServices(file)); |
||||
// Generate .pb.cc
|
||||
Insert(context, file_name + ".pb.cc", "includes", |
||||
grpc_cpp_generator::GetSourceIncludes()); |
||||
Insert(context, file_name + ".pb.cc", "namespace_scope", |
||||
grpc_cpp_generator::GetSourceServices(file)); |
||||
|
||||
return true; |
||||
} |
||||
|
||||
private: |
||||
// Insert the given code into the given file at the given insertion point.
|
||||
void Insert(google::protobuf::compiler::GeneratorContext* context, |
||||
const string& filename, const string& insertion_point, |
||||
const string& code) const { |
||||
std::unique_ptr<google::protobuf::io::ZeroCopyOutputStream> output( |
||||
context->OpenForInsert(filename, insertion_point)); |
||||
google::protobuf::io::CodedOutputStream coded_out(output.get()); |
||||
coded_out.WriteRaw(code.data(), code.size()); |
||||
} |
||||
}; |
||||
|
||||
int main(int argc, char* argv[]) { |
||||
CppGrpcGenerator generator; |
||||
return google::protobuf::compiler::PluginMain(argc, argv, &generator); |
||||
} |
@ -0,0 +1,172 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2014, 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 <cctype> |
||||
#include <map> |
||||
#include <vector> |
||||
|
||||
#include "src/compiler/ruby_generator.h" |
||||
#include "src/compiler/ruby_generator_helpers-inl.h" |
||||
#include "src/compiler/ruby_generator_map-inl.h" |
||||
#include "src/compiler/ruby_generator_string-inl.h" |
||||
#include <google/protobuf/io/printer.h> |
||||
#include <google/protobuf/io/zero_copy_stream_impl_lite.h> |
||||
#include <google/protobuf/descriptor.pb.h> |
||||
#include <google/protobuf/descriptor.h> |
||||
|
||||
using google::protobuf::FileDescriptor; |
||||
using google::protobuf::ServiceDescriptor; |
||||
using google::protobuf::MethodDescriptor; |
||||
using google::protobuf::io::Printer; |
||||
using google::protobuf::io::StringOutputStream; |
||||
using std::map; |
||||
using std::vector; |
||||
|
||||
namespace grpc_ruby_generator { |
||||
namespace { |
||||
|
||||
// Prints out the method using the ruby gRPC DSL.
|
||||
void PrintMethod(const MethodDescriptor* method, const string& package, |
||||
Printer* out) { |
||||
string input_type = RubyTypeOf(method->input_type()->name(), package); |
||||
if (method->options().has_client_streaming()) { |
||||
input_type = "stream(" + input_type + ")"; |
||||
} |
||||
string output_type = RubyTypeOf(method->output_type()->name(), package); |
||||
if (method->options().has_server_streaming()) { |
||||
output_type = "stream(" + output_type + ")"; |
||||
} |
||||
map<string, string> method_vars = ListToDict({ |
||||
"mth.name", method->name(), |
||||
"input.type", input_type, |
||||
"output.type", output_type, |
||||
}); |
||||
out->Print(method_vars, "rpc :$mth.name$, $input.type$, $output.type$\n"); |
||||
} |
||||
|
||||
// Prints out the service using the ruby gRPC DSL.
|
||||
void PrintService(const ServiceDescriptor* service, const string& package, |
||||
Printer* out) { |
||||
if (service->method_count() == 0) { |
||||
return; |
||||
} |
||||
|
||||
// Begin the service module
|
||||
map<string, string> module_vars = ListToDict({ |
||||
"module.name", CapitalizeString(service->name()), |
||||
}); |
||||
out->Print(module_vars, "module $module.name$\n"); |
||||
out->Indent(); |
||||
|
||||
// TODO(temiola): add documentation
|
||||
string doc = "TODO: add proto service documentation here"; |
||||
map<string, string> template_vars = ListToDict({ |
||||
"Documentation", doc, |
||||
}); |
||||
out->Print("\n"); |
||||
out->Print(template_vars, "# $Documentation$\n"); |
||||
out->Print("class Service\n"); |
||||
|
||||
// Write the indented class body.
|
||||
out->Indent(); |
||||
out->Print("\n"); |
||||
out->Print("include GRPC::Generic::Service\n"); |
||||
out->Print("\n"); |
||||
out->Print("self.marshal_class_method = :encode\n"); |
||||
out->Print("self.unmarshal_class_method = :decode\n"); |
||||
out->Print("\n"); |
||||
for (int i = 0; i < service->method_count(); ++i) { |
||||
PrintMethod(service->method(i), package, out); |
||||
} |
||||
out->Outdent(); |
||||
|
||||
out->Print("end\n"); |
||||
out->Print("\n"); |
||||
out->Print("Stub = Service.rpc_stub_class\n"); |
||||
|
||||
// End the service module
|
||||
out->Outdent(); |
||||
out->Print("end\n"); |
||||
} |
||||
|
||||
} // namespace
|
||||
|
||||
string GetServices(const FileDescriptor* file) { |
||||
string output; |
||||
StringOutputStream output_stream(&output); |
||||
Printer out(&output_stream, '$'); |
||||
|
||||
// Always write out a file header.
|
||||
map<string, string> header_comment_vars = ListToDict({ |
||||
"file.name", file->name(), |
||||
"file.package", file->package(), |
||||
}); |
||||
out.Print(header_comment_vars, |
||||
"### Generated from $file.name$ for $file.package$\n"); |
||||
if (file->service_count() == 0) { |
||||
return output; |
||||
} |
||||
|
||||
out.Print("\n"); |
||||
out.Print("require 'grpc'\n"); |
||||
// Write out require statemment to import the separately generated file
|
||||
// that defines the messages used by the service. This is generated by the
|
||||
// main ruby plugin.
|
||||
map<string, string> dep_vars = ListToDict({ |
||||
"dep.name", MessagesRequireName(file), |
||||
}); |
||||
out.Print(dep_vars, "require '$dep.name$'\n"); |
||||
|
||||
// Write out services within the modules
|
||||
out.Print("\n"); |
||||
vector<string> modules = Split(file->package(), '.'); |
||||
for (size_t i = 0; i < modules.size(); ++i) { |
||||
map<string, string> module_vars = ListToDict({ |
||||
"module.name", CapitalizeString(modules[i]), |
||||
}); |
||||
out.Print(module_vars, "module $module.name$\n"); |
||||
out.Indent(); |
||||
} |
||||
for (int i = 0; i < file->service_count(); ++i) { |
||||
auto service = file->service(i); |
||||
PrintService(service, file->package(), &out); |
||||
} |
||||
for (size_t i = 0; i < modules.size(); ++i) { |
||||
out.Outdent(); |
||||
out.Print("end\n"); |
||||
} |
||||
|
||||
return output; |
||||
} |
||||
|
||||
} // namespace grpc_ruby_generator
|
@ -0,0 +1,49 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2014, 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 NET_GRPC_COMPILER_RUBY_GENERATOR_H_ |
||||
#define NET_GRPC_COMPILER_RUBY_GENERATOR_H_ |
||||
|
||||
#include <string> |
||||
|
||||
namespace proto2 { |
||||
class FileDescriptor; |
||||
} // namespace proto2
|
||||
|
||||
namespace grpc_ruby_generator { |
||||
|
||||
string GetServices(const google::protobuf::FileDescriptor* file); |
||||
|
||||
} // namespace grpc_ruby_generator
|
||||
|
||||
#endif // NET_GRPC_COMPILER_RUBY_GENERATOR_H_
|
@ -0,0 +1,65 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2014, 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 NET_GRPC_COMPILER_RUBY_GENERATOR_HELPERS_INL_H_ |
||||
#define NET_GRPC_COMPILER_RUBY_GENERATOR_HELPERS_INL_H_ |
||||
|
||||
#include <string> |
||||
|
||||
#include <google/protobuf/descriptor.h> |
||||
#include "src/compiler/ruby_generator_string-inl.h" |
||||
|
||||
namespace grpc_ruby_generator { |
||||
|
||||
inline bool ServicesFilename(const google::protobuf::FileDescriptor* file, |
||||
string* file_name_or_error) { |
||||
// Get output file name.
|
||||
static const int proto_suffix_length = 6; // length of ".proto"
|
||||
if (file->name().size() > proto_suffix_length && |
||||
file->name().find_last_of(".proto") == file->name().size() - 1) { |
||||
*file_name_or_error = file->name().substr( |
||||
0, file->name().size() - proto_suffix_length) + "_services.rb"; |
||||
return true; |
||||
} else { |
||||
*file_name_or_error = "Invalid proto file name: must end with .proto"; |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
inline string MessagesRequireName(const google::protobuf::FileDescriptor* file) { |
||||
return Replace(file->name(), ".proto", ""); |
||||
} |
||||
|
||||
} // namespace grpc_ruby_generator
|
||||
|
||||
#endif // NET_GRPC_COMPILER_RUBY_GENERATOR_HELPERS_INL_H_
|
@ -0,0 +1,71 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2014, 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 NET_GRPC_COMPILER_RUBY_GENERATOR_MAP_INL_H_ |
||||
#define NET_GRPC_COMPILER_RUBY_GENERATOR_MAP_INL_H_ |
||||
|
||||
#include <initializer_list> |
||||
#include <map> |
||||
#include <ostream> // NOLINT |
||||
#include <string> |
||||
#include <vector> |
||||
|
||||
#include "base/logging.h" |
||||
|
||||
using std::initializer_list; |
||||
using std::map; |
||||
using std::vector; |
||||
|
||||
namespace grpc_ruby_generator { |
||||
|
||||
// Converts an initializer list of the form { key0, value0, key1, value1, ... }
|
||||
// into a map of key* to value*. Is merely a readability helper for later code.
|
||||
inline map<string, string> ListToDict(const initializer_list<string>& values) { |
||||
if (values.size() % 2 != 0) { |
||||
LOG(FATAL) << "Not every 'key' has a value in `values`."; |
||||
} |
||||
map<string, string> value_map; |
||||
auto value_iter = values.begin(); |
||||
for (int i = 0; i < values.size()/2; ++i) { |
||||
string key = *value_iter; |
||||
++value_iter; |
||||
string value = *value_iter; |
||||
value_map[key] = value; |
||||
++value_iter; |
||||
} |
||||
return value_map; |
||||
} |
||||
|
||||
} // namespace grpc_ruby_generator
|
||||
|
||||
#endif // NET_GRPC_COMPILER_RUBY_GENERATOR_MAP_INL_H_
|
@ -0,0 +1,116 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2014, 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 NET_GRPC_COMPILER_RUBY_GENERATOR_STRING_INL_H_ |
||||
#define NET_GRPC_COMPILER_RUBY_GENERATOR_STRING_INL_H_ |
||||
|
||||
#include <algorithm> |
||||
#include <string> |
||||
#include <sstream> |
||||
#include <vector> |
||||
|
||||
using std::getline; |
||||
using std::transform; |
||||
|
||||
namespace grpc_ruby_generator { |
||||
|
||||
// Split splits a string using char into elems.
|
||||
inline vector<string> &Split(const string &s, char delim, |
||||
vector<string>* elems) { |
||||
stringstream ss(s); |
||||
string item; |
||||
while (getline(ss, item, delim)) { |
||||
elems->push_back(item); |
||||
} |
||||
return *elems; |
||||
} |
||||
|
||||
// Split splits a string using char, returning the result in a vector.
|
||||
inline vector<string> Split(const string &s, char delim) { |
||||
vector<string> elems; |
||||
Split(s, delim, &elems); |
||||
return elems; |
||||
} |
||||
|
||||
// Replace replaces from with to in s.
|
||||
inline string Replace(string s, const string& from, const string& to) { |
||||
size_t start_pos = s.find(from); |
||||
if (start_pos == string::npos) { |
||||
return s; |
||||
} |
||||
s.replace(start_pos, from.length(), to); |
||||
return s; |
||||
} |
||||
|
||||
// ReplaceAll replaces all instances of search with replace in s.
|
||||
inline string ReplaceAll(string s, const string& search, |
||||
const string& replace) { |
||||
size_t pos = 0; |
||||
while ((pos = s.find(search, pos)) != string::npos) { |
||||
s.replace(pos, search.length(), replace); |
||||
pos += replace.length(); |
||||
} |
||||
return s; |
||||
} |
||||
|
||||
// ReplacePrefix replaces from with to in s if search is a prefix of s.
|
||||
inline bool ReplacePrefix(string* s, const string& from, const string& to) { |
||||
size_t start_pos = s->find(from); |
||||
if (start_pos == string::npos || start_pos != 0) { |
||||
return false; |
||||
} |
||||
s->replace(start_pos, from.length(), to); |
||||
return true; |
||||
} |
||||
|
||||
// RubyTypeOf updates a proto type to the required ruby equivalent.
|
||||
inline string RubyTypeOf(const string& a_type, const string& package) { |
||||
string res(a_type); |
||||
ReplacePrefix(&res, package, ""); // remove the leading package if present
|
||||
ReplacePrefix(&res, ".", ""); // remove the leading . (no package)
|
||||
return ReplaceAll(res, ".", "::"); // switch '.' to the ruby module delimiter
|
||||
} |
||||
|
||||
// CapitalizeString capitalizes a string.
|
||||
inline string CapitalizeString(string s) { |
||||
if (!s.empty()) { |
||||
return s; |
||||
} |
||||
transform(s.begin(), s.end(), s.begin(), ::tolower); |
||||
s[0] = ::toupper(s[0]); |
||||
return s; |
||||
} |
||||
|
||||
} // namespace grpc_ruby_generator
|
||||
|
||||
#endif // NET_GRPC_COMPILER_RUBY_GENERATOR_STRING_INL_H_
|
@ -0,0 +1,76 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2014, 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. |
||||
* |
||||
*/ |
||||
|
||||
// Generates Ruby gRPC service interface out of Protobuf IDL.
|
||||
//
|
||||
// This is a Proto2 compiler plugin. See net/proto2/compiler/proto/plugin.proto
|
||||
// and net/proto2/compiler/public/plugin.h for more information on plugins.
|
||||
|
||||
#include <memory> |
||||
|
||||
#include "src/compiler/ruby_generator.h" |
||||
#include "src/compiler/ruby_generator_helpers-inl.h" |
||||
#include <google/protobuf/compiler/code_generator.h> |
||||
#include <google/protobuf/compiler/plugin.h> |
||||
#include <google/protobuf/io/coded_stream.h> |
||||
#include <google/protobuf/io/zero_copy_stream.h> |
||||
#include <google/protobuf/descriptor.h> |
||||
|
||||
class RubyGrpcGenerator : public google::protobuf::compiler::CodeGenerator { |
||||
public: |
||||
RubyGrpcGenerator() {} |
||||
~RubyGrpcGenerator() override {} |
||||
|
||||
bool Generate(const google::protobuf::FileDescriptor* file, |
||||
const string& parameter, |
||||
google::protobuf::compiler::GeneratorContext* context, |
||||
string* error) const override { |
||||
// Get output file name.
|
||||
string file_name; |
||||
if (!grpc_ruby_generator::ServicesFilename(file, &file_name)) { |
||||
return false; |
||||
} |
||||
|
||||
std::unique_ptr<google::protobuf::io::ZeroCopyOutputStream> output( |
||||
context->OpenForInsert(file_name, "module_scope")); |
||||
google::protobuf::io::CodedOutputStream coded_out(output.get()); |
||||
string code = grpc_ruby_generator::GetServices(file); |
||||
coded_out.WriteRaw(code.data(), code.size()); |
||||
return true; |
||||
} |
||||
}; |
||||
|
||||
int main(int argc, char* argv[]) { |
||||
RubyGrpcGenerator generator; |
||||
return google::protobuf::compiler::PluginMain(argc, argv, &generator); |
||||
} |
Loading…
Reference in new issue