Merge pull request #190 from isaiah/to_ary

add #to_ary to RepeatedField
diff --git a/ruby/ext/google/protobuf_c/repeated_field.c b/ruby/ext/google/protobuf_c/repeated_field.c
index 6e3f0bc..8cf2e29 100644
--- a/ruby/ext/google/protobuf_c/repeated_field.c
+++ b/ruby/ext/google/protobuf_c/repeated_field.c
@@ -318,6 +318,29 @@
 
 /*
  * call-seq:
+ *     RepeatedField.to_ary => array
+ *
+ * Used when converted implicitly into array, e.g. compared to an Array.
+ * Also called as a fallback of Object#to_a
+ */
+VALUE RepeatedField_to_ary(VALUE _self) {
+  RepeatedField* self = ruby_to_RepeatedField(_self);
+  upb_fieldtype_t field_type = self->field_type;
+
+  size_t elem_size = native_slot_size(field_type);
+  size_t off = 0;
+  VALUE ary = rb_ary_new2(self->size);
+  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, self->field_type_class, mem);
+
+    rb_ary_push(ary, elem);
+  }
+  return ary;
+}
+
+/*
+ * call-seq:
  *     RepeatedField.==(other) => boolean
  *
  * Compares this repeated field to another. Repeated fields are equal if their
@@ -335,15 +358,9 @@
   }
   RepeatedField* self = ruby_to_RepeatedField(_self);
 
-  // Inefficient but workable: to support comparison to a generic array, we
-  // build a temporary RepeatedField of our type.
   if (TYPE(_other) == T_ARRAY) {
-    VALUE new_rptfield = RepeatedField_new_this_type(_self);
-    for (int i = 0; i < RARRAY_LEN(_other); i++) {
-      VALUE elem = rb_ary_entry(_other, i);
-      RepeatedField_push(new_rptfield, elem);
-    }
-    _other = new_rptfield;
+    VALUE self_ary = RepeatedField_to_ary(_self);
+    return rb_equal(self_ary, _other);
   }
 
   RepeatedField* other = ruby_to_RepeatedField(_other);
@@ -401,29 +418,8 @@
  * representation computed by its own #inspect method.
  */
 VALUE RepeatedField_inspect(VALUE _self) {
-  RepeatedField* self = ruby_to_RepeatedField(_self);
-
-  VALUE str = rb_str_new2("[");
-
-  bool first = true;
-
-  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);
-  size_t off = 0;
-  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);
-    if (!first) {
-      str = rb_str_cat2(str, ", ");
-    } else {
-      first = false;
-    }
-    str = rb_str_append(str, rb_funcall(elem, rb_intern("inspect"), 0));
-  }
-
-  str = rb_str_cat2(str, "]");
-  return str;
+  VALUE self_ary = RepeatedField_to_ary(_self);
+  return rb_funcall(self_ary, rb_intern("inspect"), 0);
 }
 
 /*
@@ -594,6 +590,7 @@
   // Also define #clone so that we don't inherit Object#clone.
   rb_define_method(klass, "clone", RepeatedField_dup, 0);
   rb_define_method(klass, "==", RepeatedField_eq, 1);
+  rb_define_method(klass, "to_ary", RepeatedField_to_ary, 0);
   rb_define_method(klass, "hash", RepeatedField_hash, 0);
   rb_define_method(klass, "inspect", RepeatedField_inspect, 0);
   rb_define_method(klass, "+", RepeatedField_plus, 1);
diff --git a/ruby/tests/basic.rb b/ruby/tests/basic.rb
index 1b7508b..321b1d3 100644
--- a/ruby/tests/basic.rb
+++ b/ruby/tests/basic.rb
@@ -236,7 +236,8 @@
       assert l.count == 0
       l = Google::Protobuf::RepeatedField.new(:int32, [1, 2, 3])
       assert l.count == 3
-      assert l == [1, 2, 3]
+      assert_equal [1, 2, 3], l
+      assert_equal l, [1, 2, 3]
       l.push 4
       assert l == [1, 2, 3, 4]
       dst_list = []