diff options
author | Chris Fallin <cfallin@c1f.net> | 2015-02-03 09:57:13 -0800 |
---|---|---|
committer | Chris Fallin <cfallin@c1f.net> | 2015-02-03 09:57:13 -0800 |
commit | e7e79a43ed13b25232384eeeabf4089026876e9d (patch) | |
tree | 712558fcb9edf1e93d445839ee242a6f07607c5b | |
parent | a22bc812a4042a3a1bd6aab48a87aee036650745 (diff) | |
parent | ee5f6e9a35bec5c4e57a8da5d0c8357633200eb8 (diff) |
Merge pull request #190 from isaiah/to_ary
add #to_ary to RepeatedField
-rw-r--r-- | ruby/ext/google/protobuf_c/repeated_field.c | 59 | ||||
-rw-r--r-- | ruby/tests/basic.rb | 3 |
2 files changed, 30 insertions, 32 deletions
diff --git a/ruby/ext/google/protobuf_c/repeated_field.c b/ruby/ext/google/protobuf_c/repeated_field.c index 6e3f0bc7..8cf2e29b 100644 --- a/ruby/ext/google/protobuf_c/repeated_field.c +++ b/ruby/ext/google/protobuf_c/repeated_field.c @@ -318,6 +318,29 @@ VALUE RepeatedField_deep_copy(VALUE _self) { /* * 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 @@ VALUE RepeatedField_eq(VALUE _self, VALUE _other) { } 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 @@ VALUE RepeatedField_hash(VALUE _self) { * 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 @@ void RepeatedField_register(VALUE module) { // 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 1b7508bb..321b1d34 100644 --- a/ruby/tests/basic.rb +++ b/ruby/tests/basic.rb @@ -236,7 +236,8 @@ module BasicTest 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 = [] |