From 91473dcebfbd90a8e256568e287e168b70c77ff0 Mon Sep 17 00:00:00 2001 From: Chris Fallin Date: Fri, 12 Dec 2014 15:58:26 -0800 Subject: Rename protobuf Ruby module to google/protobuf and rework its build system. The Ruby module build now uses an amalgamated distribution of upb, and successfully builds a Ruby gem called 'google-protobuf' with module 'google/protobuf'. --- src/google/protobuf/compiler/ruby/ruby_generator.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/google/protobuf/compiler/ruby/ruby_generator.cc') diff --git a/src/google/protobuf/compiler/ruby/ruby_generator.cc b/src/google/protobuf/compiler/ruby/ruby_generator.cc index 82ccd72b..e70425ff 100644 --- a/src/google/protobuf/compiler/ruby/ruby_generator.cc +++ b/src/google/protobuf/compiler/ruby/ruby_generator.cc @@ -261,7 +261,7 @@ void GenerateFile(const google::protobuf::FileDescriptor* file, "filename", file->name()); printer->Print( - "require 'protobuf'\n\n"); + "require 'google/protobuf'\n\n"); for (int i = 0; i < file->dependency_count(); i++) { const std::string& name = file->dependency(i)->name(); -- cgit v1.2.3 From 5ce69e991a00a5a0c5016bffd150ce0abbf84e1b Mon Sep 17 00:00:00 2001 From: Chris Fallin Date: Fri, 12 Dec 2014 17:31:25 -0800 Subject: Support Ruby code generation only for proto3. --- src/google/protobuf/compiler/ruby/ruby_generator.cc | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'src/google/protobuf/compiler/ruby/ruby_generator.cc') diff --git a/src/google/protobuf/compiler/ruby/ruby_generator.cc b/src/google/protobuf/compiler/ruby/ruby_generator.cc index e70425ff..c5687903 100644 --- a/src/google/protobuf/compiler/ruby/ruby_generator.cc +++ b/src/google/protobuf/compiler/ruby/ruby_generator.cc @@ -297,6 +297,14 @@ bool Generator::Generate( const string& parameter, GeneratorContext* generator_context, string* error) const { + + if (file->syntax() != FileDescriptor::SYNTAX_PROTO3) { + *error = + "Can only generate Ruby code for proto3 .proto files.\n" + "Please add 'syntax = \"proto3\";' to the top of your .proto file.\n"; + return false; + } + std::string filename = StripDotProto(file->name()) + ".rb"; scoped_ptr output(generator_context->Open(filename)); -- cgit v1.2.3 From 7c4bbf07a5eee1fd4f5c2d60be32b95c35b0ed1d Mon Sep 17 00:00:00 2001 From: Chris Fallin Date: Wed, 14 Jan 2015 14:56:17 -0800 Subject: Support oneofs in the Ruby code generator. --- .../protobuf/compiler/ruby/ruby_generator.cc | 64 ++++++++++++++++------ 1 file changed, 46 insertions(+), 18 deletions(-) (limited to 'src/google/protobuf/compiler/ruby/ruby_generator.cc') diff --git a/src/google/protobuf/compiler/ruby/ruby_generator.cc b/src/google/protobuf/compiler/ruby/ruby_generator.cc index c5687903..3101c524 100644 --- a/src/google/protobuf/compiler/ruby/ruby_generator.cc +++ b/src/google/protobuf/compiler/ruby/ruby_generator.cc @@ -100,6 +100,45 @@ std::string TypeName(const google::protobuf::FieldDescriptor* field) { } } +void GenerateField(const google::protobuf::FieldDescriptor* field, + google::protobuf::io::Printer* printer) { + printer->Print( + "$label$ :$name$, ", + "label", LabelForField(field), + "name", field->name()); + printer->Print( + ":$type$, $number$", + "type", TypeName(field), + "number", IntToString(field->number())); + if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + printer->Print( + ", \"$subtype$\"\n", + "subtype", field->message_type()->full_name()); + } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) { + printer->Print( + ", \"$subtype$\"\n", + "subtype", field->enum_type()->full_name()); + } else { + printer->Print("\n"); + } +} + +void GenerateOneof(const google::protobuf::OneofDescriptor* oneof, + google::protobuf::io::Printer* printer) { + printer->Print( + "oneof :$name$ do\n", + "name", oneof->name()); + printer->Indent(); + + for (int i = 0; i < oneof->field_count(); i++) { + const FieldDescriptor* field = oneof->field(i); + GenerateField(field, printer); + } + + printer->Outdent(); + printer->Print("end\n"); +} + void GenerateMessage(const google::protobuf::Descriptor* message, google::protobuf::io::Printer* printer) { printer->Print( @@ -109,27 +148,16 @@ void GenerateMessage(const google::protobuf::Descriptor* message, for (int i = 0; i < message->field_count(); i++) { const FieldDescriptor* field = message->field(i); - printer->Print( - "$label$ :$name$, ", - "label", LabelForField(field), - "name", field->name()); - printer->Print( - ":$type$, $number$", - "type", TypeName(field), - "number", IntToString(field->number())); - if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { - printer->Print( - ", \"$subtype$\"\n", - "subtype", field->message_type()->full_name()); - } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) { - printer->Print( - ", \"$subtype$\"\n", - "subtype", field->enum_type()->full_name()); - } else { - printer->Print("\n"); + if (!field->containing_oneof()) { + GenerateField(field, printer); } } + for (int i = 0; i < message->oneof_decl_count(); i++) { + const OneofDescriptor* oneof = message->oneof_decl(i); + GenerateOneof(oneof, printer); + } + printer->Outdent(); printer->Print("end\n"); -- cgit v1.2.3 From df4730ca9c093a8551b2a9ee7ba0f3098796aeb8 Mon Sep 17 00:00:00 2001 From: Florian Enner Date: Sat, 31 Jan 2015 19:01:34 -0500 Subject: fixed MSVC compile error is not part of the standard, so I've added a workaround. --- src/google/protobuf/compiler/ruby/ruby_generator.cc | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src/google/protobuf/compiler/ruby/ruby_generator.cc') diff --git a/src/google/protobuf/compiler/ruby/ruby_generator.cc b/src/google/protobuf/compiler/ruby/ruby_generator.cc index c5687903..bb88fc16 100644 --- a/src/google/protobuf/compiler/ruby/ruby_generator.cc +++ b/src/google/protobuf/compiler/ruby/ruby_generator.cc @@ -46,6 +46,12 @@ namespace protobuf { namespace compiler { namespace ruby { +#if _MSC_VER >= 1400 // VS 2005 and above + // is not part of the standard, so we need to map + // to MSVC's custom sized integer types instead. + typedef unsigned __int32 uint32_t; +#endif + // Forward decls. std::string IntToString(uint32_t value); std::string StripDotProto(const std::string& proto_file); -- cgit v1.2.3 From e1e86b02a8569f522a867d55c42e5ac5664fc86e Mon Sep 17 00:00:00 2001 From: Florian Enner Date: Sat, 31 Jan 2015 19:22:52 -0500 Subject: replaced type fix with the recommended way --- src/google/protobuf/compiler/ruby/ruby_generator.cc | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) (limited to 'src/google/protobuf/compiler/ruby/ruby_generator.cc') diff --git a/src/google/protobuf/compiler/ruby/ruby_generator.cc b/src/google/protobuf/compiler/ruby/ruby_generator.cc index bb88fc16..da2e7e89 100644 --- a/src/google/protobuf/compiler/ruby/ruby_generator.cc +++ b/src/google/protobuf/compiler/ruby/ruby_generator.cc @@ -45,15 +45,9 @@ namespace google { namespace protobuf { namespace compiler { namespace ruby { - -#if _MSC_VER >= 1400 // VS 2005 and above - // is not part of the standard, so we need to map - // to MSVC's custom sized integer types instead. - typedef unsigned __int32 uint32_t; -#endif // Forward decls. -std::string IntToString(uint32_t value); +std::string IntToString(uint32 value); std::string StripDotProto(const std::string& proto_file); std::string LabelForField(google::protobuf::FieldDescriptor* field); std::string TypeName(google::protobuf::FieldDescriptor* field); @@ -70,7 +64,7 @@ void GenerateEnumAssignment( const google::protobuf::EnumDescriptor* en, google::protobuf::io::Printer* printer); -std::string IntToString(uint32_t value) { +std::string IntToString(uint32 value) { std::ostringstream os; os << value; return os.str(); -- cgit v1.2.3 From e544b38815134ea800c1c4d86d207c1b56535afe Mon Sep 17 00:00:00 2001 From: Florian Enner Date: Mon, 2 Feb 2015 15:19:01 -0500 Subject: removed accidental whitespace --- src/google/protobuf/compiler/ruby/ruby_generator.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/google/protobuf/compiler/ruby/ruby_generator.cc') diff --git a/src/google/protobuf/compiler/ruby/ruby_generator.cc b/src/google/protobuf/compiler/ruby/ruby_generator.cc index da2e7e89..22a64de9 100644 --- a/src/google/protobuf/compiler/ruby/ruby_generator.cc +++ b/src/google/protobuf/compiler/ruby/ruby_generator.cc @@ -45,7 +45,7 @@ namespace google { namespace protobuf { namespace compiler { namespace ruby { - + // Forward decls. std::string IntToString(uint32 value); std::string StripDotProto(const std::string& proto_file); -- cgit v1.2.3 From a2bea0a0012b4adbc50c47246d968a85cb88cec2 Mon Sep 17 00:00:00 2001 From: Chris Fallin Date: Thu, 12 Feb 2015 16:08:01 -0800 Subject: Properly support maps in Ruby protoc and another bugfix. Previously, we supported map fields in the Ruby DSL. However, we never connected the final link in the chain and generated `map` DSL commands for map fields in `.proto` files. My apologies -- I had been testing with the DSL directly so I missed this. Also fixed a handlerdata-setup-infinite-loop when a map value field's type is its containing message. --- ruby/ext/google/protobuf_c/encode_decode.c | 23 +++---- ruby/tests/generated_code.rb | 70 +++----------------- .../protobuf/compiler/ruby/ruby_generator.cc | 75 +++++++++++++++++----- 3 files changed, 79 insertions(+), 89 deletions(-) (limited to 'src/google/protobuf/compiler/ruby/ruby_generator.cc') diff --git a/ruby/ext/google/protobuf_c/encode_decode.c b/ruby/ext/google/protobuf_c/encode_decode.c index 0630f567..256fc829 100644 --- a/ruby/ext/google/protobuf_c/encode_decode.c +++ b/ruby/ext/google/protobuf_c/encode_decode.c @@ -208,7 +208,7 @@ typedef struct { size_t ofs; upb_fieldtype_t key_field_type; upb_fieldtype_t value_field_type; - VALUE value_field_typeclass; + const upb_def* value_field_subdef; } map_handlerdata_t; // Temporary frame for map parsing: at the beginning of a map entry message, a @@ -248,8 +248,15 @@ static bool endmap_handler(void *closure, const void *hd, upb_status* s) { VALUE key = native_slot_get( mapdata->key_field_type, Qnil, &frame->key_storage); + + VALUE value_field_typeclass = Qnil; + if (mapdata->value_field_type == UPB_TYPE_MESSAGE || + mapdata->value_field_type == UPB_TYPE_ENUM) { + value_field_typeclass = get_def_obj(mapdata->value_field_subdef); + } + VALUE value = native_slot_get( - mapdata->value_field_type, mapdata->value_field_typeclass, + mapdata->value_field_type, value_field_typeclass, &frame->value_storage); Map_index_set(frame->map, key, value); @@ -280,17 +287,7 @@ static map_handlerdata_t* new_map_handlerdata( MAP_VALUE_FIELD); assert(value_field != NULL); hd->value_field_type = upb_fielddef_type(value_field); - hd->value_field_typeclass = field_type_class(value_field); - - // Ensure that value_field_typeclass is properly GC-rooted. We must do this - // because we hold a reference to the Ruby class in the handlerdata, which is - // owned by the handlers. The handlers are owned by *this* message's Ruby - // object, but each Ruby object is rooted independently at the def -> Ruby - // object map. So we have to ensure that the Ruby objects we depend on will - // stick around as long as we're around. - if (hd->value_field_typeclass != Qnil) { - rb_ary_push(desc->typeclass_references, hd->value_field_typeclass); - } + hd->value_field_subdef = upb_fielddef_subdef(value_field); return hd; } diff --git a/ruby/tests/generated_code.rb b/ruby/tests/generated_code.rb index db762ad9..5a685433 100644 --- a/ruby/tests/generated_code.rb +++ b/ruby/tests/generated_code.rb @@ -27,16 +27,16 @@ Google::Protobuf::DescriptorPool.generated_pool.build do repeated :repeated_bytes, :string, 29 repeated :repeated_enum, :enum, 30, "A.B.C.TestEnum" repeated :repeated_msg, :message, 31, "A.B.C.TestMessage" - repeated :map_int32_string, :message, 61, "A.B.C.TestMessage.MapInt32StringEntry" - repeated :map_int64_string, :message, 62, "A.B.C.TestMessage.MapInt64StringEntry" - repeated :map_uint32_string, :message, 63, "A.B.C.TestMessage.MapUint32StringEntry" - repeated :map_uint64_string, :message, 64, "A.B.C.TestMessage.MapUint64StringEntry" - repeated :map_bool_string, :message, 65, "A.B.C.TestMessage.MapBoolStringEntry" - repeated :map_string_string, :message, 66, "A.B.C.TestMessage.MapStringStringEntry" - repeated :map_string_msg, :message, 67, "A.B.C.TestMessage.MapStringMsgEntry" - repeated :map_string_enum, :message, 68, "A.B.C.TestMessage.MapStringEnumEntry" - repeated :map_string_int32, :message, 69, "A.B.C.TestMessage.MapStringInt32Entry" - repeated :map_string_bool, :message, 70, "A.B.C.TestMessage.MapStringBoolEntry" + map :map_int32_string, :int32, :string, 61 + map :map_int64_string, :int64, :string, 62 + map :map_uint32_string, :uint32, :string, 63 + map :map_uint64_string, :uint64, :string, 64 + map :map_bool_string, :bool, :string, 65 + map :map_string_string, :string, :string, 66 + map :map_string_msg, :string, :message, 67, "A.B.C.TestMessage" + map :map_string_enum, :string, :enum, 68, "A.B.C.TestEnum" + map :map_string_int32, :string, :int32, 69 + map :map_string_bool, :string, :bool, 70 optional :nested_message, :message, 80, "A.B.C.TestMessage.NestedMessage" oneof :my_oneof do optional :oneof_int32, :int32, 41 @@ -52,46 +52,6 @@ Google::Protobuf::DescriptorPool.generated_pool.build do optional :oneof_msg, :message, 51, "A.B.C.TestMessage" end end - add_message "A.B.C.TestMessage.MapInt32StringEntry" do - optional :key, :int32, 1 - optional :value, :string, 2 - end - add_message "A.B.C.TestMessage.MapInt64StringEntry" do - optional :key, :int64, 1 - optional :value, :string, 2 - end - add_message "A.B.C.TestMessage.MapUint32StringEntry" do - optional :key, :uint32, 1 - optional :value, :string, 2 - end - add_message "A.B.C.TestMessage.MapUint64StringEntry" do - optional :key, :uint64, 1 - optional :value, :string, 2 - end - add_message "A.B.C.TestMessage.MapBoolStringEntry" do - optional :key, :bool, 1 - optional :value, :string, 2 - end - add_message "A.B.C.TestMessage.MapStringStringEntry" do - optional :key, :string, 1 - optional :value, :string, 2 - end - add_message "A.B.C.TestMessage.MapStringMsgEntry" do - optional :key, :string, 1 - optional :value, :message, 2, "A.B.C.TestMessage" - end - add_message "A.B.C.TestMessage.MapStringEnumEntry" do - optional :key, :string, 1 - optional :value, :enum, 2, "A.B.C.TestEnum" - end - add_message "A.B.C.TestMessage.MapStringInt32Entry" do - optional :key, :string, 1 - optional :value, :int32, 2 - end - add_message "A.B.C.TestMessage.MapStringBoolEntry" do - optional :key, :string, 1 - optional :value, :bool, 2 - end add_message "A.B.C.TestMessage.NestedMessage" do optional :foo, :int32, 1 end @@ -107,16 +67,6 @@ module A module B module C TestMessage = Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestMessage").msgclass - TestMessage::MapInt32StringEntry = Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestMessage.MapInt32StringEntry").msgclass - TestMessage::MapInt64StringEntry = Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestMessage.MapInt64StringEntry").msgclass - TestMessage::MapUint32StringEntry = Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestMessage.MapUint32StringEntry").msgclass - TestMessage::MapUint64StringEntry = Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestMessage.MapUint64StringEntry").msgclass - TestMessage::MapBoolStringEntry = Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestMessage.MapBoolStringEntry").msgclass - TestMessage::MapStringStringEntry = Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestMessage.MapStringStringEntry").msgclass - TestMessage::MapStringMsgEntry = Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestMessage.MapStringMsgEntry").msgclass - TestMessage::MapStringEnumEntry = Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestMessage.MapStringEnumEntry").msgclass - TestMessage::MapStringInt32Entry = Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestMessage.MapStringInt32Entry").msgclass - TestMessage::MapStringBoolEntry = Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestMessage.MapStringBoolEntry").msgclass TestMessage::NestedMessage = Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestMessage.NestedMessage").msgclass TestEnum = Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestEnum").enummodule end diff --git a/src/google/protobuf/compiler/ruby/ruby_generator.cc b/src/google/protobuf/compiler/ruby/ruby_generator.cc index be59fafd..88292891 100644 --- a/src/google/protobuf/compiler/ruby/ruby_generator.cc +++ b/src/google/protobuf/compiler/ruby/ruby_generator.cc @@ -102,24 +102,53 @@ std::string TypeName(const google::protobuf::FieldDescriptor* field) { void GenerateField(const google::protobuf::FieldDescriptor* field, google::protobuf::io::Printer* printer) { - printer->Print( - "$label$ :$name$, ", - "label", LabelForField(field), - "name", field->name()); - printer->Print( - ":$type$, $number$", - "type", TypeName(field), - "number", IntToString(field->number())); - if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { - printer->Print( - ", \"$subtype$\"\n", - "subtype", field->message_type()->full_name()); - } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) { + + if (field->is_map()) { + const FieldDescriptor* key_field = + field->message_type()->FindFieldByNumber(1); + const FieldDescriptor* value_field = + field->message_type()->FindFieldByNumber(2); + printer->Print( - ", \"$subtype$\"\n", - "subtype", field->enum_type()->full_name()); + "map :$name$, :$key_type$, :$value_type$, $number$", + "name", field->name(), + "key_type", TypeName(key_field), + "value_type", TypeName(value_field), + "number", IntToString(field->number())); + + if (value_field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + printer->Print( + ", \"$subtype$\"\n", + "subtype", value_field->message_type()->full_name()); + } else if (value_field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) { + printer->Print( + ", \"$subtype$\"\n", + "subtype", value_field->enum_type()->full_name()); + } else { + printer->Print("\n"); + } } else { - printer->Print("\n"); + + printer->Print( + "$label$ :$name$, ", + "label", LabelForField(field), + "name", field->name()); + printer->Print( + ":$type$, $number$", + "type", TypeName(field), + "number", IntToString(field->number())); + + if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + printer->Print( + ", \"$subtype$\"\n", + "subtype", field->message_type()->full_name()); + } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) { + printer->Print( + ", \"$subtype$\"\n", + "subtype", field->enum_type()->full_name()); + } else { + printer->Print("\n"); + } } } @@ -141,6 +170,13 @@ void GenerateOneof(const google::protobuf::OneofDescriptor* oneof, void GenerateMessage(const google::protobuf::Descriptor* message, google::protobuf::io::Printer* printer) { + + // Don't generate MapEntry messages -- we use the Ruby extension's native + // support for map fields instead. + if (message->options().map_entry()) { + return; + } + printer->Print( "add_message \"$name$\" do\n", "name", message->full_name()); @@ -213,6 +249,13 @@ void GenerateMessageAssignment( const std::string& prefix, const google::protobuf::Descriptor* message, google::protobuf::io::Printer* printer) { + + // Don't generate MapEntry messages -- we use the Ruby extension's native + // support for map fields instead. + if (message->options().map_entry()) { + return; + } + printer->Print( "$prefix$$name$ = ", "prefix", prefix, -- cgit v1.2.3