THRIFT-1331. rb: Ruby library deserializes an empty map to nil
This patch properly detects when the metadata is omitted in Compact Protocol messages.
Patch: Armaan Sarkar
git-svn-id: https://svn.apache.org/repos/asf/thrift/trunk@1173300 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/lib/rb/ext/struct.c b/lib/rb/ext/struct.c
index dae338e..590983f 100644
--- a/lib/rb/ext/struct.c
+++ b/lib/rb/ext/struct.c
@@ -484,7 +484,7 @@
if (!NIL_P(key_info) && !NIL_P(value_info)) {
int specified_key_type = FIX2INT(rb_hash_aref(key_info, type_sym));
int specified_value_type = FIX2INT(rb_hash_aref(value_info, type_sym));
- if (specified_key_type == key_ttype && specified_value_type == value_ttype) {
+ if (num_entries == 0 || (specified_key_type == key_ttype && specified_value_type == value_ttype)) {
result = rb_hash_new();
for (i = 0; i < num_entries; ++i) {
diff --git a/lib/rb/lib/thrift/struct_union.rb b/lib/rb/lib/thrift/struct_union.rb
index 0ff175f..4e0afcf 100644
--- a/lib/rb/lib/thrift/struct_union.rb
+++ b/lib/rb/lib/thrift/struct_union.rb
@@ -56,7 +56,7 @@
when Types::MAP
key_type, val_type, size = iprot.read_map_begin
# Skip the map contents if the declared key or value types don't match the expected ones.
- if (key_type != field[:key][:type] || val_type != field[:value][:type])
+ if (size != 0 && (key_type != field[:key][:type] || val_type != field[:value][:type]))
size.times do
iprot.skip(key_type)
iprot.skip(val_type)
diff --git a/lib/rb/spec/compact_protocol_spec.rb b/lib/rb/spec/compact_protocol_spec.rb
index 1fa2182..a88a2ae 100644
--- a/lib/rb/spec/compact_protocol_spec.rb
+++ b/lib/rb/spec/compact_protocol_spec.rb
@@ -115,6 +115,17 @@
brcp2.should == brcp
end
+ it "should deserialize an empty map to an empty hash" do
+ struct = SingleMapTestStruct.new(:i32_map => {})
+ ser = Thrift::Serializer.new(Thrift::CompactProtocolFactory.new)
+ bytes = ser.serialize(struct)
+
+ deser = Thrift::Deserializer.new(Thrift::CompactProtocolFactory.new)
+ struct2 = SingleMapTestStruct.new
+ deser.deserialize(struct2, bytes)
+ struct.should == struct2
+ end
+
class JankyHandler
def Janky(i32arg)
i32arg * 2
diff --git a/test/DebugProtoTest.thrift b/test/DebugProtoTest.thrift
index 23d5d97..b8b89b7 100644
--- a/test/DebugProtoTest.thrift
+++ b/test/DebugProtoTest.thrift
@@ -161,6 +161,10 @@
49: map<byte, list<byte>> byte_list_map;
}
+// To be used to test the serialization of an empty map
+struct SingleMapTestStruct {
+ 1: required map<i32, i32> i32_map;
+}
const CompactProtoTestStruct COMPACT_TEST = {
'a_byte' : 127,