diff options
Diffstat (limited to 'ruby')
-rw-r--r-- | ruby/ext/google/protobuf_c/encode_decode.c | 27 | ||||
-rw-r--r-- | ruby/tests/generated_code.rb | 70 |
2 files changed, 24 insertions, 73 deletions
diff --git a/ruby/ext/google/protobuf_c/encode_decode.c b/ruby/ext/google/protobuf_c/encode_decode.c index 0630f567..5730504d 100644 --- a/ruby/ext/google/protobuf_c/encode_decode.c +++ b/ruby/ext/google/protobuf_c/encode_decode.c @@ -208,7 +208,11 @@ typedef struct { size_t ofs; upb_fieldtype_t key_field_type; upb_fieldtype_t value_field_type; - VALUE value_field_typeclass; + + // We know that we can hold this reference because the handlerdata has the + // same lifetime as the upb_handlers struct, and the upb_handlers struct holds + // a reference to the upb_msgdef, which in turn has references to its subdefs. + 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 +252,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 +291,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 |