diff --git a/Makefile b/Makefile index 903e497b776..8e01bb88dc6 100644 --- a/Makefile +++ b/Makefile @@ -455,7 +455,7 @@ endif .SECONDARY = %.pb.h %.pb.cc -PROTOC_PLUGINS = $(BINDIR)/$(CONFIG)/grpc_cpp_plugin $(BINDIR)/$(CONFIG)/grpc_python_plugin $(BINDIR)/$(CONFIG)/grpc_ruby_plugin +PROTOC_PLUGINS = $(BINDIR)/$(CONFIG)/grpc_cpp_plugin $(BINDIR)/$(CONFIG)/grpc_objective_c_plugin $(BINDIR)/$(CONFIG)/grpc_python_plugin $(BINDIR)/$(CONFIG)/grpc_ruby_plugin ifeq ($(DEP_MISSING),) all: static shared plugins dep_error: @@ -631,6 +631,7 @@ end2end_test: $(BINDIR)/$(CONFIG)/end2end_test generic_end2end_test: $(BINDIR)/$(CONFIG)/generic_end2end_test grpc_cli: $(BINDIR)/$(CONFIG)/grpc_cli grpc_cpp_plugin: $(BINDIR)/$(CONFIG)/grpc_cpp_plugin +grpc_objective_c_plugin: $(BINDIR)/$(CONFIG)/grpc_objective_c_plugin grpc_python_plugin: $(BINDIR)/$(CONFIG)/grpc_python_plugin grpc_ruby_plugin: $(BINDIR)/$(CONFIG)/grpc_ruby_plugin interop_client: $(BINDIR)/$(CONFIG)/interop_client @@ -2265,6 +2266,8 @@ else $(Q) $(INSTALL) -d $(prefix)/bin $(Q) $(INSTALL) $(BINDIR)/$(CONFIG)/grpc_cpp_plugin $(prefix)/bin/grpc_cpp_plugin $(Q) $(INSTALL) -d $(prefix)/bin + $(Q) $(INSTALL) $(BINDIR)/$(CONFIG)/grpc_objective_c_plugin $(prefix)/bin/grpc_objective_c_plugin + $(Q) $(INSTALL) -d $(prefix)/bin $(Q) $(INSTALL) $(BINDIR)/$(CONFIG)/grpc_python_plugin $(prefix)/bin/grpc_python_plugin $(Q) $(INSTALL) -d $(prefix)/bin $(Q) $(INSTALL) $(BINDIR)/$(CONFIG)/grpc_ruby_plugin $(prefix)/bin/grpc_ruby_plugin @@ -3614,6 +3617,7 @@ $(OBJDIR)/$(CONFIG)/src/cpp/util/time.o: LIBGRPC_PLUGIN_SUPPORT_SRC = \ src/compiler/cpp_generator.cc \ + src/compiler/objective_c_generator.cc \ src/compiler/python_generator.cc \ src/compiler/ruby_generator.cc \ @@ -3648,6 +3652,7 @@ ifneq ($(NO_DEPS),true) endif $(OBJDIR)/$(CONFIG)/src/compiler/cpp_generator.o: +$(OBJDIR)/$(CONFIG)/src/compiler/objective_c_generator.o: $(OBJDIR)/$(CONFIG)/src/compiler/python_generator.o: $(OBJDIR)/$(CONFIG)/src/compiler/ruby_generator.o: @@ -8330,6 +8335,36 @@ ifneq ($(NO_DEPS),true) endif +GRPC_OBJECTIVE_C_PLUGIN_SRC = \ + src/compiler/objective_c_plugin.cc \ + +GRPC_OBJECTIVE_C_PLUGIN_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_OBJECTIVE_C_PLUGIN_SRC)))) + + +ifeq ($(NO_PROTOBUF),true) + +# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+. + +$(BINDIR)/$(CONFIG)/grpc_objective_c_plugin: protobuf_dep_error + +else + +$(BINDIR)/$(CONFIG)/grpc_objective_c_plugin: $(PROTOBUF_DEP) $(GRPC_OBJECTIVE_C_PLUGIN_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_plugin_support.a + $(E) "[HOSTLD] Linking $@" + $(Q) mkdir -p `dirname $@` + $(Q) $(HOST_LDXX) $(HOST_LDFLAGS) $(GRPC_OBJECTIVE_C_PLUGIN_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_plugin_support.a $(HOST_LDLIBSXX) $(HOST_LDLIBS_PROTOC) $(HOST_LDLIBS) $(HOST_LDLIBS_PROTOC) -o $(BINDIR)/$(CONFIG)/grpc_objective_c_plugin + +endif + +$(OBJDIR)/$(CONFIG)/src/compiler/objective_c_plugin.o: $(LIBDIR)/$(CONFIG)/libgrpc_plugin_support.a + +deps_grpc_objective_c_plugin: $(GRPC_OBJECTIVE_C_PLUGIN_OBJS:.o=.dep) + +ifneq ($(NO_DEPS),true) +-include $(GRPC_OBJECTIVE_C_PLUGIN_OBJS:.o=.dep) +endif + + GRPC_PYTHON_PLUGIN_SRC = \ src/compiler/python_plugin.cc \ diff --git a/build.json b/build.json index d814e4c6bd8..f8f23e0d335 100644 --- a/build.json +++ b/build.json @@ -514,6 +514,8 @@ "src/compiler/cpp_generator.h", "src/compiler/cpp_generator_helpers.h", "src/compiler/generator_helpers.h", + "src/compiler/objective_c_generator.h", + "src/compiler/objective_c_generator_helpers.h", "src/compiler/python_generator.h", "src/compiler/ruby_generator.h", "src/compiler/ruby_generator_helpers-inl.h", @@ -522,6 +524,7 @@ ], "src": [ "src/compiler/cpp_generator.cc", + "src/compiler/objective_c_generator.cc", "src/compiler/python_generator.cc", "src/compiler/ruby_generator.cc" ], @@ -1817,6 +1820,18 @@ ], "secure": "no" }, + { + "name": "grpc_objective_c_plugin", + "build": "protoc", + "language": "c++", + "src": [ + "src/compiler/objective_c_plugin.cc" + ], + "deps": [ + "grpc_plugin_support" + ], + "secure": "no" + }, { "name": "grpc_python_plugin", "build": "protoc", diff --git a/src/compiler/generator_helpers.h b/src/compiler/generator_helpers.h index 30857891c77..374e1374cf4 100644 --- a/src/compiler/generator_helpers.h +++ b/src/compiler/generator_helpers.h @@ -95,6 +95,27 @@ inline std::vector tokenize(const grpc::string &input, } } +inline grpc::string CapitalizeFirstLetter(grpc::string s) { + if (s.empty()) { + return s; + } + s[0] = ::toupper(s[0]); + return s; +} + +inline grpc::string LowerUnderscoreToUpperCamel(grpc::string str) { + std::vector tokens = tokenize(str, "_"); + grpc::string result = ""; + for (unsigned int i = 0; i < tokens.size(); i++) { + result += CapitalizeFirstLetter(tokens[i]); + } + return result; +} + +inline grpc::string FileNameInUpperCamel(const grpc::protobuf::FileDescriptor *file) { + return LowerUnderscoreToUpperCamel(StripProto(file->name())); +} + } // namespace grpc_generator #endif // GRPC_INTERNAL_COMPILER_GENERATOR_HELPERS_H diff --git a/src/compiler/objective_c_generator.cc b/src/compiler/objective_c_generator.cc new file mode 100644 index 00000000000..c68c9c37c21 --- /dev/null +++ b/src/compiler/objective_c_generator.cc @@ -0,0 +1,236 @@ +/* + * + * 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 + +#include "src/compiler/objective_c_generator.h" +#include "src/compiler/objective_c_generator_helpers.h" + +#include "src/compiler/config.h" + +#include + +namespace grpc_objective_c_generator { +namespace { + +void PrintSimpleBlockSignature(grpc::protobuf::io::Printer *printer, + const grpc::protobuf::MethodDescriptor *method, + std::map *vars) { + (*vars)["method_name"] = method->name(); + (*vars)["request_type"] = PrefixedName(method->input_type()->name()); + (*vars)["response_type"] = PrefixedName(method->output_type()->name()); + + if (method->server_streaming()) { + printer->Print("// When the response stream finishes, the handler is " + "called with nil for both arguments.\n\n"); + } else { + printer->Print("// The handler is only called once.\n\n"); + } + printer->Print(*vars, "- (id)$method_name$WithRequest:" + "($request_type$)request completionHandler:(void(^)" + "($response_type$ *, NSError *))handler"); +} + +void PrintSimpleDelegateSignature(grpc::protobuf::io::Printer *printer, + const grpc::protobuf::MethodDescriptor *method, + std::map *vars) { + (*vars)["method_name"] = method->name(); + (*vars)["request_type"] = PrefixedName(method->input_type()->name()); + + printer->Print(*vars, "- (id)$method_name$WithRequest:" + "($request_type$)request delegate:(id)delegate"); +} + +void PrintAdvancedSignature(grpc::protobuf::io::Printer *printer, + const grpc::protobuf::MethodDescriptor *method, + std::map *vars) { + (*vars)["method_name"] = method->name(); + printer->Print(*vars, "- (GRXSource *)$method_name$WithRequest:" + "(id)request"); +} + +void PrintSourceMethodSimpleBlock(grpc::protobuf::io::Printer *printer, + const grpc::protobuf::MethodDescriptor *method, + std::map *vars) { + PrintSimpleBlockSignature(printer, method, vars); + + (*vars)["method_name"] = method->name(); + printer->Print(" {\n"); + printer->Indent(); + printer->Print(*vars, "return [[self $method_name$WithRequest:request] " + "connectHandler:^(id value, NSError *error) {\n"); + printer->Indent(); + printer->Print("handler(value, error);\n"); + printer->Outdent(); + printer->Print("}];\n"); + printer->Outdent(); + printer->Print("}\n"); +} + +void PrintSourceMethodSimpleDelegate(grpc::protobuf::io::Printer *printer, + const grpc::protobuf::MethodDescriptor *method, + std::map *vars) { + PrintSimpleDelegateSignature(printer, method, vars); + + (*vars)["method_name"] = method->name(); + printer->Print(" {\n"); + printer->Indent(); + printer->Print(*vars, "return [[self $method_name$WithRequest:request]" + "connectToSink:delegate];\n"); + printer->Outdent(); + printer->Print("}\n"); +} + +void PrintSourceMethodAdvanced(grpc::protobuf::io::Printer *printer, + const grpc::protobuf::MethodDescriptor *method, + std::map *vars) { + PrintAdvancedSignature(printer, method, vars); + + (*vars)["method_name"] = method->name(); + printer->Print(" {\n"); + printer->Indent(); + printer->Print(*vars, "return [self $method_name$WithRequest:request " + "client:[self newClient]];\n"); + printer->Outdent(); + printer->Print("}\n"); +} + +void PrintSourceMethodHandler(grpc::protobuf::io::Printer *printer, + const grpc::protobuf::MethodDescriptor *method, + std::map *vars) { + (*vars)["method_name"] = method->name(); + (*vars)["response_type"] = PrefixedName(method->output_type()->name()); + (*vars)["caps_name"] = grpc_generator::CapitalizeFirstLetter(method->name()); + + printer->Print(*vars, "- (GRXSource *)$method_name$WithRequest:" + "(id)request client:(PBgRPCClient *)client {\n"); + printer->Indent(); + printer->Print(*vars, + "return [self responseWithMethod:$@\"$caps_name\"\n"); + printer->Print(*vars, + " class:[$response_type$ class]\n"); + printer->Print(" request:request\n"); + printer->Print(" client:client];\n"); + printer->Outdent(); + printer->Print("}\n"); +} + +} + +grpc::string GetHeader(const grpc::protobuf::ServiceDescriptor *service, + const grpc::string message_header) { + grpc::string output; + grpc::protobuf::io::StringOutputStream output_stream(&output); + grpc::protobuf::io::Printer printer(&output_stream, '$'); + std::map vars; + printer.Print("#import \"PBgRPCClient.h\"\n"); + printer.Print("#import \"PBStub.h\"\n"); + vars["message_header"] = message_header; + printer.Print(vars, "#import \"$message_header$\"\n\n"); + printer.Print("@protocol GRXSource\n"); + printer.Print("@class GRXSource\n\n"); + vars["service_name"] = service->name(); + printer.Print("@protocol $service_name$Stub \n\n"); + printer.Print("#pragma mark Simple block handlers\n\n"); + for (int i = 0; i < service->method_count(); i++) { + PrintSimpleBlockSignature(&printer, service->method(i), &vars); + printer.Print(";\n"); + } + printer.Print("\n"); + printer.Print("#pragma mark Simple delegate handlers.\n\n"); + printer.Print("# TODO(jcanizales): Use high-level snippets to remove this duplication."); + for (int i = 0; i < service->method_count(); i++) { + PrintSimpleDelegateSignature(&printer, service->method(i), &vars); + printer.Print(";\n"); + } + printer.Print("\n"); + printer.Print("#pragma mark Advanced handlers.\n\n"); + for (int i = 0; i < service->method_count(); i++) { + PrintAdvancedSignature(&printer, service->method(i), &vars); + printer.Print(";\n"); + } + printer.Print("\n"); + printer.Print("@end\n\n"); + printer.Print("// Basic stub that only does marshalling and parsing\n"); + printer.Print(vars, "@interface $service_name$Stub :" + " PBStub<$service_name$Stub>\n"); + printer.Print("- (instancetype)initWithHost:(NSString *)host;\n"); + printer.Print("@end\n"); + return output; +} + +grpc::string GetSource(const grpc::protobuf::ServiceDescriptor *service) { + grpc::string output; + grpc::protobuf::io::StringOutputStream output_stream(&output); + grpc::protobuf::io::Printer printer(&output_stream, '$'); + std::map vars; + vars["service_name"] = service->name(); + printer.Print(vars, "#import \"$service_name$Stub.pb.h\"\n"); + printer.Print("#import \"PBGeneratedMessage+GRXSource.h\"\n\n"); + vars["full_name"] = service->full_name(); + printer.Print(vars, + "static NSString *const kInterface = @\"$full_name$\";\n"); + printer.Print("@implementation $service_name$Stub\n\n"); + printer.Print("- (instancetype)initWithHost:(NSString *)host {\n"); + printer.Indent(); + printer.Print("if ((self = [super initWithHost:host " + "interface:kInterface])) {\n"); + printer.Print("}\n"); + printer.Print("return self;\n"); + printer.Outdent(); + printer.Print("}\n\n"); + printer.Print("#pragma mark Simple block handlers.\n"); + for (int i = 0; i < service->method_count(); i++) { + PrintSourceMethodSimpleBlock(&printer, service->method(i), &vars); + } + printer.Print("\n"); + printer.Print("#pragma mark Simple delegate handlers.\n"); + for (int i = 0; i < service->method_count(); i++) { + PrintSourceMethodSimpleDelegate(&printer, service->method(i), &vars); + } + printer.Print("\n"); + printer.Print("#pragma mark Advanced handlers.\n"); + for (int i = 0; i < service->method_count(); i++) { + PrintSourceMethodAdvanced(&printer, service->method(i), &vars); + } + printer.Print("\n"); + printer.Print("#pragma mark Handlers for subclasses " + "(stub wrappers) to override.\n"); + for (int i = 0; i < service->method_count(); i++) { + PrintSourceMethodHandler(&printer, service->method(i), &vars); + } + printer.Print("@end\n"); + return output; +} + +} // namespace grpc_objective_c_generator diff --git a/src/compiler/objective_c_generator.h b/src/compiler/objective_c_generator.h new file mode 100644 index 00000000000..93c730b34e4 --- /dev/null +++ b/src/compiler/objective_c_generator.h @@ -0,0 +1,48 @@ +/* + * + * 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_OBJECTIVE_C_GENERATOR_H +#define GRPC_INTERNAL_COMPILER_OBJECTIVE_C_GENERATOR_H + +#include "src/compiler/config.h" + +namespace grpc_objective_c_generator { + +grpc::string GetHeader(const grpc::protobuf::ServiceDescriptor *service, + const grpc::string message_header); + +grpc::string GetSource(const grpc::protobuf::ServiceDescriptor *service); + +} // namespace grpc_objective_c_generator + +#endif // GRPC_INTERNAL_COMPILER_OBJECTIVE_C_GENERATOR_H diff --git a/src/compiler/objective_c_generator_helpers.h b/src/compiler/objective_c_generator_helpers.h new file mode 100644 index 00000000000..6a7c13991fd --- /dev/null +++ b/src/compiler/objective_c_generator_helpers.h @@ -0,0 +1,58 @@ +/* + * + * 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_OBJECTIVE_C_GENERATOR_HELPERS_H +#define GRPC_INTERNAL_COMPILER_OBJECTIVE_C_GENERATOR_HELPERS_H + +#include +#include "src/compiler/config.h" +#include "src/compiler/generator_helpers.h" + +namespace grpc_objective_c_generator { + +const grpc::string prefix = "PBG"; + +inline grpc::string MessageHeaderName(const grpc::protobuf::FileDescriptor *file) { + return grpc_generator::FileNameInUpperCamel(file) + ".pb.h"; +} + +inline grpc::string StubFileName(grpc::string service_name) { + return prefix + service_name + "Stub"; +} + +inline grpc::string PrefixedName(grpc::string name) { + return prefix + name; +} + +} +#endif // GRPC_INTERNAL_COMPILER_OBJECTIVE_C_GENERATOR_HELPERS_H diff --git a/src/compiler/objective_c_plugin.cc b/src/compiler/objective_c_plugin.cc new file mode 100644 index 00000000000..eebce0cd20d --- /dev/null +++ b/src/compiler/objective_c_plugin.cc @@ -0,0 +1,98 @@ +/* + * + * 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. + * + */ + +// Generates Objective C gRPC service interface out of Protobuf IDL. + +#include + +#include "src/compiler/config.h" +#include "src/compiler/objective_c_generator.h" +#include "src/compiler/objective_c_generator_helpers.h" + +class ObjectiveCGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator { + public: + ObjectiveCGrpcGenerator() {} + virtual ~ObjectiveCGrpcGenerator() {} + + virtual bool Generate(const grpc::protobuf::FileDescriptor *file, + const grpc::string ¶meter, + grpc::protobuf::compiler::GeneratorContext *context, + grpc::string *error) const { + + if (file->service_count() == 0) { + // No services. Do nothing. + return true; + } + + for (int i = 0; i < file->service_count(); i++) { + const grpc::protobuf::ServiceDescriptor *service = file->service(i); + grpc::string file_name = grpc_objective_c_generator::StubFileName( + service->name()); + + // Generate .pb.h + grpc::string header_code = grpc_objective_c_generator::GetHeader( + service, grpc_objective_c_generator::MessageHeaderName(file)); + std::unique_ptr header_output( + context->Open(file_name + ".pb.h")); + grpc::protobuf::io::CodedOutputStream header_coded_out( + header_output.get()); + header_coded_out.WriteRaw(header_code.data(), header_code.size()); + + // Generate .pb.m + grpc::string source_code = grpc_objective_c_generator::GetSource(service); + std::unique_ptr source_output( + context->Open(file_name + ".pb.m")); + grpc::protobuf::io::CodedOutputStream source_coded_out( + source_output.get()); + source_coded_out.WriteRaw(source_code.data(), source_code.size()); + } + + return true; + } + + private: + // Insert the given code into the given file at the given insertion point. + void Insert(grpc::protobuf::compiler::GeneratorContext *context, + const grpc::string &filename, const grpc::string &insertion_point, + const grpc::string &code) const { + std::unique_ptr output( + context->OpenForInsert(filename, insertion_point)); + grpc::protobuf::io::CodedOutputStream coded_out(output.get()); + coded_out.WriteRaw(code.data(), code.size()); + } +}; + +int main(int argc, char *argv[]) { + ObjectiveCGrpcGenerator generator; + return grpc::protobuf::compiler::PluginMain(argc, argv, &generator); +}