aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--js/binary/proto_test.js6
-rw-r--r--js/message.js4
-rw-r--r--js/message_test.js3
-rw-r--r--ruby/ext/google/protobuf_c/map.c31
-rw-r--r--ruby/ext/google/protobuf_c/message.c14
-rw-r--r--ruby/ext/google/protobuf_c/protobuf.h2
-rw-r--r--ruby/tests/basic.rb10
7 files changed, 61 insertions, 9 deletions
diff --git a/js/binary/proto_test.js b/js/binary/proto_test.js
index f86dc645..f5e1b6bb 100644
--- a/js/binary/proto_test.js
+++ b/js/binary/proto_test.js
@@ -283,8 +283,7 @@ function checkAllFields(original, copy) {
* @param {!proto.jspb.test.TestExtendable} msg
*/
function checkExtensions(msg) {
- assertEquals(-42,
- msg.getExtension(proto.jspb.test.extendOptionalInt32));
+ assertEquals(0, msg.getExtension(proto.jspb.test.extendOptionalInt32));
assertEquals(-0x7fffffff00000000,
msg.getExtension(proto.jspb.test.extendOptionalInt64));
assertEquals(0x80000000,
@@ -512,8 +511,7 @@ describe('protoBinaryTest', function() {
* @param {proto.jspb.test.TestExtendable} msg
*/
function fillExtensions(msg) {
- msg.setExtension(
- proto.jspb.test.extendOptionalInt32, -42);
+ msg.setExtension(proto.jspb.test.extendOptionalInt32, 0);
msg.setExtension(
proto.jspb.test.extendOptionalInt64, -0x7fffffff00000000);
msg.setExtension(
diff --git a/js/message.js b/js/message.js
index 05d34e9d..4e2517d3 100644
--- a/js/message.js
+++ b/js/message.js
@@ -497,7 +497,7 @@ jspb.Message.toObjectExtension = function(proto, obj, extensions,
for (var fieldNumber in extensions) {
var fieldInfo = extensions[fieldNumber];
var value = getExtensionFn.call(proto, fieldInfo);
- if (value) {
+ if (goog.isDefAndNotNull(value)) {
for (var name in fieldInfo.fieldName) {
if (fieldInfo.fieldName.hasOwnProperty(name)) {
break; // the compiled field name
@@ -541,7 +541,7 @@ jspb.Message.serializeBinaryExtensions = function(proto, writer, extensions,
'without binary serialization support');
}
var value = getExtensionFn.call(proto, fieldInfo);
- if (value) {
+ if (goog.isDefAndNotNull(value)) {
if (fieldInfo.isMessageType()) {
// If the message type of the extension was generated without binary
// support, there may not be a binary message serializer function, and
diff --git a/js/message_test.js b/js/message_test.js
index a2c5763d..2298742d 100644
--- a/js/message_test.js
+++ b/js/message_test.js
@@ -693,10 +693,11 @@ describe('Message test suite', function() {
});
it('testToObject_hasExtensionField', function() {
- var data = new proto.jspb.test.HasExtensions(['str1', {100: ['ext1']}]);
+ var data = new proto.jspb.test.HasExtensions(['str1', {100: ['ext1'], 102: ''}]);
var obj = data.toObject();
assertEquals('str1', obj.str1);
assertEquals('ext1', obj.extField.ext1);
+ assertEquals('', obj.str);
});
it('testGetExtension', function() {
diff --git a/ruby/ext/google/protobuf_c/map.c b/ruby/ext/google/protobuf_c/map.c
index 12f1f9dd..4be54c39 100644
--- a/ruby/ext/google/protobuf_c/map.c
+++ b/ruby/ext/google/protobuf_c/map.c
@@ -654,6 +654,35 @@ VALUE Map_hash(VALUE _self) {
/*
* call-seq:
+ * Map.to_h => {}
+ *
+ * Returns a Ruby Hash object containing all the values within the map
+ */
+VALUE Map_to_h(VALUE _self) {
+ Map* self = ruby_to_Map(_self);
+ VALUE hash = rb_hash_new();
+ upb_strtable_iter it;
+ for (upb_strtable_begin(&it, &self->table);
+ !upb_strtable_done(&it);
+ upb_strtable_next(&it)) {
+ VALUE key = table_key_to_ruby(
+ self, upb_strtable_iter_key(&it), upb_strtable_iter_keylength(&it));
+ upb_value v = upb_strtable_iter_value(&it);
+ void* mem = value_memory(&v);
+ VALUE value = native_slot_get(self->value_type,
+ self->value_type_class,
+ mem);
+
+ if (self->value_type == UPB_TYPE_MESSAGE) {
+ value = Message_to_h(value);
+ }
+ rb_hash_aset(hash, key, value);
+ }
+ return hash;
+}
+
+/*
+ * call-seq:
* Map.inspect => string
*
* Returns a string representing this map's elements. It will be formatted as
@@ -804,6 +833,8 @@ void Map_register(VALUE module) {
rb_define_method(klass, "dup", Map_dup, 0);
rb_define_method(klass, "==", Map_eq, 1);
rb_define_method(klass, "hash", Map_hash, 0);
+ rb_define_method(klass, "to_hash", Map_to_h, 0);
+ rb_define_method(klass, "to_h", Map_to_h, 0);
rb_define_method(klass, "inspect", Map_inspect, 0);
rb_define_method(klass, "merge", Map_merge, 1);
rb_include_module(klass, rb_mEnumerable);
diff --git a/ruby/ext/google/protobuf_c/message.c b/ruby/ext/google/protobuf_c/message.c
index 837a974b..29911140 100644
--- a/ruby/ext/google/protobuf_c/message.c
+++ b/ruby/ext/google/protobuf_c/message.c
@@ -394,7 +394,12 @@ VALUE Message_inspect(VALUE _self) {
return str;
}
-
+/*
+ * call-seq:
+ * Message.to_h => {}
+ *
+ * Returns the message as a Ruby Hash object, with keys as symbols.
+ */
VALUE Message_to_h(VALUE _self) {
MessageHeader* self;
VALUE hash;
@@ -410,8 +415,13 @@ VALUE Message_to_h(VALUE _self) {
VALUE msg_value = layout_get(self->descriptor->layout, Message_data(self),
field);
VALUE msg_key = ID2SYM(rb_intern(upb_fielddef_name(field)));
- if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
+ if (upb_fielddef_ismap(field)) {
+ msg_value = Map_to_h(msg_value);
+ } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
msg_value = RepeatedField_to_ary(msg_value);
+ } else if (msg_value != Qnil &&
+ upb_fielddef_type(field) == UPB_TYPE_MESSAGE) {
+ msg_value = Message_to_h(msg_value);
}
rb_hash_aset(hash, msg_key, msg_value);
}
diff --git a/ruby/ext/google/protobuf_c/protobuf.h b/ruby/ext/google/protobuf_c/protobuf.h
index d5ced567..520e9d9b 100644
--- a/ruby/ext/google/protobuf_c/protobuf.h
+++ b/ruby/ext/google/protobuf_c/protobuf.h
@@ -424,6 +424,7 @@ VALUE Map_dup(VALUE _self);
VALUE Map_deep_copy(VALUE _self);
VALUE Map_eq(VALUE _self, VALUE _other);
VALUE Map_hash(VALUE _self);
+VALUE Map_to_h(VALUE _self);
VALUE Map_inspect(VALUE _self);
VALUE Map_merge(VALUE _self, VALUE hashmap);
VALUE Map_merge_into_self(VALUE _self, VALUE hashmap);
@@ -496,6 +497,7 @@ VALUE Message_deep_copy(VALUE _self);
VALUE Message_eq(VALUE _self, VALUE _other);
VALUE Message_hash(VALUE _self);
VALUE Message_inspect(VALUE _self);
+VALUE Message_to_h(VALUE _self);
VALUE Message_index(VALUE _self, VALUE field_name);
VALUE Message_index_set(VALUE _self, VALUE field_name, VALUE value);
VALUE Message_descriptor(VALUE klass);
diff --git a/ruby/tests/basic.rb b/ruby/tests/basic.rb
index ca81e3a5..34251234 100644
--- a/ruby/tests/basic.rb
+++ b/ruby/tests/basic.rb
@@ -927,6 +927,16 @@ module BasicTest
:repeated_uint64=>[]
}
assert_equal expected_result, m.to_h
+
+ m = MapMessage.new(
+ :map_string_int32 => {"a" => 1, "b" => 2},
+ :map_string_msg => {"a" => TestMessage2.new(:foo => 1),
+ "b" => TestMessage2.new(:foo => 2)})
+ expected_result = {
+ :map_string_int32 => {"a" => 1, "b" => 2},
+ :map_string_msg => {"a" => {:foo => 1}, "b" => {:foo => 2}}
+ }
+ assert_equal expected_result, m.to_h
end