Forráskód Böngészése

Merge pull request #2037 from abscondment/fix-2036-ruby-hash

Fix #2036 (Ruby `hash` broken for Messages with repeated fields.)
Joshua Haberman 9 éve
szülő
commit
b5bbdb0967
2 módosított fájl, 9 hozzáadás és 8 törlés
  1. 5 7
      ruby/ext/google/protobuf_c/repeated_field.c
  2. 4 1
      ruby/tests/basic.rb

+ 5 - 7
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);
 }
 
 /*

+ 4 - 1
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