diff options
author | Chris Fallin <cfallin@google.com> | 2015-02-12 16:08:01 -0800 |
---|---|---|
committer | Chris Fallin <cfallin@google.com> | 2015-02-12 16:08:01 -0800 |
commit | a2bea0a0012b4adbc50c47246d968a85cb88cec2 (patch) | |
tree | 6ed5b7445bc098091fadf094b2ccbeb124d3569e /ruby/ext | |
parent | 43beb6268bd3989154991bccb831e2bc951402d8 (diff) | |
download | protobuf-a2bea0a0012b4adbc50c47246d968a85cb88cec2.tar.gz protobuf-a2bea0a0012b4adbc50c47246d968a85cb88cec2.tar.bz2 protobuf-a2bea0a0012b4adbc50c47246d968a85cb88cec2.zip |
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.
Diffstat (limited to 'ruby/ext')
-rw-r--r-- | ruby/ext/google/protobuf_c/encode_decode.c | 23 |
1 files changed, 10 insertions, 13 deletions
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; } |