aboutsummaryrefslogtreecommitdiffhomepage
path: root/ruby
diff options
context:
space:
mode:
authorGravatar Joshua Haberman <jhaberman@gmail.com>2016-09-18 21:38:51 -0700
committerGravatar GitHub <noreply@github.com>2016-09-18 21:38:51 -0700
commitb5bbdb0967109fbae7bfc423ef3cd6dc776359b6 (patch)
tree79920944d315149f92c3e37f0e27b7c0156c6ec5 /ruby
parentc44ca26fe89ed8a81d3ee475a2ccc1797141dbce (diff)
parentde028631fce33b77811f2a29c83c36ab875c751c (diff)
Merge pull request #2037 from abscondment/fix-2036-ruby-hash
Fix #2036 (Ruby `hash` broken for Messages with repeated fields.)
Diffstat (limited to 'ruby')
-rw-r--r--ruby/ext/google/protobuf_c/repeated_field.c12
-rw-r--r--ruby/tests/basic.rb5
2 files changed, 9 insertions, 8 deletions
diff --git a/ruby/ext/google/protobuf_c/repeated_field.c b/ruby/ext/google/protobuf_c/repeated_field.c
index 47c207a5..1c651c19 100644
--- a/ruby/ext/google/protobuf_c/repeated_field.c
+++ b/ruby/ext/google/protobuf_c/repeated_field.c
@@ -447,9 +447,8 @@ VALUE RepeatedField_eq(VALUE _self, VALUE _other) {
*/
VALUE RepeatedField_hash(VALUE _self) {
RepeatedField* self = ruby_to_RepeatedField(_self);
-
- VALUE hash = LL2NUM(0);
-
+ st_index_t h = rb_hash_start(0);
+ VALUE hash_sym = rb_intern("hash");
upb_fieldtype_t field_type = self->field_type;
VALUE field_type_class = self->field_type_class;
size_t elem_size = native_slot_size(field_type);
@@ -457,12 +456,11 @@ VALUE RepeatedField_hash(VALUE _self) {
for (int i = 0; i < self->size; i++, off += elem_size) {
void* mem = ((uint8_t *)self->elements) + off;
VALUE elem = native_slot_get(field_type, field_type_class, mem);
- hash = rb_funcall(hash, rb_intern("<<"), 1, INT2NUM(2));
- hash = rb_funcall(hash, rb_intern("^"), 1,
- rb_funcall(elem, rb_intern("hash"), 0));
+ h = rb_hash_uint(h, NUM2LONG(rb_funcall(elem, hash_sym, 0)));
}
+ h = rb_hash_end(h);
- return hash;
+ return INT2FIX(h);
}
/*
diff --git a/ruby/tests/basic.rb b/ruby/tests/basic.rb
index 8b6d329e..989a047e 100644
--- a/ruby/tests/basic.rb
+++ b/ruby/tests/basic.rb
@@ -183,12 +183,15 @@ module BasicTest
def test_hash
m1 = TestMessage.new(:optional_int32 => 42)
- m2 = TestMessage.new(:optional_int32 => 102)
+ m2 = TestMessage.new(:optional_int32 => 102, repeated_string: ['please', 'work', 'ok?'])
+ m3 = TestMessage.new(:optional_int32 => 102, repeated_string: ['please', 'work', 'ok?'])
assert m1.hash != 0
assert m2.hash != 0
+ assert m3.hash != 0
# relying on the randomness here -- if hash function changes and we are
# unlucky enough to get a collision, then change the values above.
assert m1.hash != m2.hash
+ assert_equal m2.hash, m3.hash
end
def test_unknown_field_errors