1 // Protocol Buffers - Google's data interchange format 2 // Copyright 2014 Google Inc. All rights reserved. 3 // https://developers.google.com/protocol-buffers/ 4 // 5 // Redistribution and use in source and binary forms, with or without 6 // modification, are permitted provided that the following conditions are 7 // met: 8 // 9 // * Redistributions of source code must retain the above copyright 10 // notice, this list of conditions and the following disclaimer. 11 // * Redistributions in binary form must reproduce the above 12 // copyright notice, this list of conditions and the following disclaimer 13 // in the documentation and/or other materials provided with the 14 // distribution. 15 // * Neither the name of Google Inc. nor the names of its 16 // contributors may be used to endorse or promote products derived from 17 // this software without specific prior written permission. 18 // 19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 31 #include "protobuf.h" 32 33 // ----------------------------------------------------------------------------- 34 // Repeated field container type. 35 // ----------------------------------------------------------------------------- 36 37 const rb_data_type_t RepeatedField_type = { 38 "Google::Protobuf::RepeatedField", 39 { RepeatedField_mark, RepeatedField_free, NULL }, 40 }; 41 42 VALUE cRepeatedField; 43 44 RepeatedField* ruby_to_RepeatedField(VALUE _self) { 45 RepeatedField* self; 46 TypedData_Get_Struct(_self, RepeatedField, &RepeatedField_type, self); 47 return self; 48 } 49 50 void* RepeatedField_memoryat(RepeatedField* self, int index, int element_size) { 51 return ((uint8_t *)self->elements) + index * element_size; 52 } 53 54 static int index_position(VALUE _index, RepeatedField* repeated_field) { 55 int index = NUM2INT(_index); 56 if (index < 0 && repeated_field->size > 0) { 57 index = repeated_field->size + index; 58 } 59 return index; 60 } 61 62 VALUE RepeatedField_subarray(VALUE _self, long beg, long len) { 63 RepeatedField* self = ruby_to_RepeatedField(_self); 64 int element_size = native_slot_size(self->field_type); 65 upb_fieldtype_t field_type = self->field_type; 66 VALUE field_type_class = self->field_type_class; 67 68 size_t off = beg * element_size; 69 VALUE ary = rb_ary_new2(len); 70 for (int i = beg; i < beg + len; i++, off += element_size) { 71 void* mem = ((uint8_t *)self->elements) + off; 72 VALUE elem = native_slot_get(field_type, field_type_class, mem); 73 rb_ary_push(ary, elem); 74 } 75 return ary; 76 } 77 78 /* 79 * call-seq: 80 * RepeatedField.each(&block) 81 * 82 * Invokes the block once for each element of the repeated field. RepeatedField 83 * also includes Enumerable; combined with this method, the repeated field thus 84 * acts like an ordinary Ruby sequence. 85 */ 86 VALUE RepeatedField_each(VALUE _self) { 87 RepeatedField* self = ruby_to_RepeatedField(_self); 88 upb_fieldtype_t field_type = self->field_type; 89 VALUE field_type_class = self->field_type_class; 90 int element_size = native_slot_size(field_type); 91 92 size_t off = 0; 93 for (int i = 0; i < self->size; i++, off += element_size) { 94 void* memory = (void *) (((uint8_t *)self->elements) + off); 95 VALUE val = native_slot_get(field_type, field_type_class, memory); 96 rb_yield(val); 97 } 98 return _self; 99 } 100 101 102 /* 103 * call-seq: 104 * RepeatedField.[](index) => value 105 * 106 * Accesses the element at the given index. Returns nil on out-of-bounds 107 */ 108 VALUE RepeatedField_index(int argc, VALUE* argv, VALUE _self) { 109 RepeatedField* self = ruby_to_RepeatedField(_self); 110 int element_size = native_slot_size(self->field_type); 111 upb_fieldtype_t field_type = self->field_type; 112 VALUE field_type_class = self->field_type_class; 113 114 VALUE arg = argv[0]; 115 long beg, len; 116 117 if (argc == 1){ 118 if (FIXNUM_P(arg)) { 119 /* standard case */ 120 void* memory; 121 int index = index_position(argv[0], self); 122 if (index < 0 || index >= self->size) { 123 return Qnil; 124 } 125 memory = RepeatedField_memoryat(self, index, element_size); 126 return native_slot_get(field_type, field_type_class, memory); 127 }else{ 128 /* check if idx is Range */ 129 switch (rb_range_beg_len(arg, &beg, &len, self->size, 0)) { 130 case Qfalse: 131 break; 132 case Qnil: 133 return Qnil; 134 default: 135 return RepeatedField_subarray(_self, beg, len); 136 } 137 } 138 } 139 /* assume 2 arguments */ 140 beg = NUM2LONG(argv[0]); 141 len = NUM2LONG(argv[1]); 142 if (beg < 0) { 143 beg += self->size; 144 } 145 if (beg >= self->size) { 146 return Qnil; 147 } 148 return RepeatedField_subarray(_self, beg, len); 149 } 150 151 /* 152 * call-seq: 153 * RepeatedField.[]=(index, value) 154 * 155 * Sets the element at the given index. On out-of-bounds assignments, extends 156 * the array and fills the hole (if any) with default values. 157 */ 158 VALUE RepeatedField_index_set(VALUE _self, VALUE _index, VALUE val) { 159 RepeatedField* self = ruby_to_RepeatedField(_self); 160 upb_fieldtype_t field_type = self->field_type; 161 VALUE field_type_class = self->field_type_class; 162 int element_size = native_slot_size(field_type); 163 void* memory; 164 165 int index = index_position(_index, self); 166 if (index < 0 || index >= (INT_MAX - 1)) { 167 return Qnil; 168 } 169 if (index >= self->size) { 170 upb_fieldtype_t field_type = self->field_type; 171 int element_size = native_slot_size(field_type); 172 RepeatedField_reserve(self, index + 1); 173 for (int i = self->size; i <= index; i++) { 174 void* elem = RepeatedField_memoryat(self, i, element_size); 175 native_slot_init(field_type, elem); 176 } 177 self->size = index + 1; 178 } 179 180 memory = RepeatedField_memoryat(self, index, element_size); 181 native_slot_set(field_type, field_type_class, memory, val); 182 return Qnil; 183 } 184 185 static int kInitialSize = 8; 186 187 void RepeatedField_reserve(RepeatedField* self, int new_size) { 188 void* old_elems = self->elements; 189 int elem_size = native_slot_size(self->field_type); 190 if (new_size <= self->capacity) { 191 return; 192 } 193 if (self->capacity == 0) { 194 self->capacity = kInitialSize; 195 } 196 while (self->capacity < new_size) { 197 self->capacity *= 2; 198 } 199 self->elements = ALLOC_N(uint8_t, elem_size * self->capacity); 200 if (old_elems != NULL) { 201 memcpy(self->elements, old_elems, self->size * elem_size); 202 xfree(old_elems); 203 } 204 } 205 206 /* 207 * call-seq: 208 * RepeatedField.push(value) 209 * 210 * Adds a new element to the repeated field. 211 */ 212 VALUE RepeatedField_push(VALUE _self, VALUE val) { 213 RepeatedField* self = ruby_to_RepeatedField(_self); 214 upb_fieldtype_t field_type = self->field_type; 215 int element_size = native_slot_size(field_type); 216 void* memory; 217 218 RepeatedField_reserve(self, self->size + 1); 219 memory = (void *) (((uint8_t *)self->elements) + self->size * element_size); 220 native_slot_set(field_type, self->field_type_class, memory, val); 221 // native_slot_set may raise an error; bump size only after set. 222 self->size++; 223 return _self; 224 } 225 226 227 // Used by parsing handlers. 228 void RepeatedField_push_native(VALUE _self, void* data) { 229 RepeatedField* self = ruby_to_RepeatedField(_self); 230 upb_fieldtype_t field_type = self->field_type; 231 int element_size = native_slot_size(field_type); 232 void* memory; 233 234 RepeatedField_reserve(self, self->size + 1); 235 memory = (void *) (((uint8_t *)self->elements) + self->size * element_size); 236 memcpy(memory, data, element_size); 237 self->size++; 238 } 239 240 void* RepeatedField_index_native(VALUE _self, int index) { 241 RepeatedField* self = ruby_to_RepeatedField(_self); 242 upb_fieldtype_t field_type = self->field_type; 243 int element_size = native_slot_size(field_type); 244 return RepeatedField_memoryat(self, index, element_size); 245 } 246 247 /* 248 * Private ruby method, used by RepeatedField.pop 249 */ 250 VALUE RepeatedField_pop_one(VALUE _self) { 251 RepeatedField* self = ruby_to_RepeatedField(_self); 252 upb_fieldtype_t field_type = self->field_type; 253 VALUE field_type_class = self->field_type_class; 254 int element_size = native_slot_size(field_type); 255 int index; 256 void* memory; 257 VALUE ret; 258 259 if (self->size == 0) { 260 return Qnil; 261 } 262 index = self->size - 1; 263 memory = RepeatedField_memoryat(self, index, element_size); 264 ret = native_slot_get(field_type, field_type_class, memory); 265 self->size--; 266 return ret; 267 } 268 269 /* 270 * call-seq: 271 * RepeatedField.replace(list) 272 * 273 * Replaces the contents of the repeated field with the given list of elements. 274 */ 275 VALUE RepeatedField_replace(VALUE _self, VALUE list) { 276 RepeatedField* self = ruby_to_RepeatedField(_self); 277 Check_Type(list, T_ARRAY); 278 self->size = 0; 279 for (int i = 0; i < RARRAY_LEN(list); i++) { 280 RepeatedField_push(_self, rb_ary_entry(list, i)); 281 } 282 return list; 283 } 284 285 /* 286 * call-seq: 287 * RepeatedField.clear 288 * 289 * Clears (removes all elements from) this repeated field. 290 */ 291 VALUE RepeatedField_clear(VALUE _self) { 292 RepeatedField* self = ruby_to_RepeatedField(_self); 293 self->size = 0; 294 return _self; 295 } 296 297 /* 298 * call-seq: 299 * RepeatedField.length 300 * 301 * Returns the length of this repeated field. 302 */ 303 VALUE RepeatedField_length(VALUE _self) { 304 RepeatedField* self = ruby_to_RepeatedField(_self); 305 return INT2NUM(self->size); 306 } 307 308 static VALUE RepeatedField_new_this_type(VALUE _self) { 309 RepeatedField* self = ruby_to_RepeatedField(_self); 310 VALUE new_rptfield = Qnil; 311 VALUE element_type = fieldtype_to_ruby(self->field_type); 312 if (self->field_type_class != Qnil) { 313 new_rptfield = rb_funcall(CLASS_OF(_self), rb_intern("new"), 2, 314 element_type, self->field_type_class); 315 } else { 316 new_rptfield = rb_funcall(CLASS_OF(_self), rb_intern("new"), 1, 317 element_type); 318 } 319 return new_rptfield; 320 } 321 322 /* 323 * call-seq: 324 * RepeatedField.dup => repeated_field 325 * 326 * Duplicates this repeated field with a shallow copy. References to all 327 * non-primitive element objects (e.g., submessages) are shared. 328 */ 329 VALUE RepeatedField_dup(VALUE _self) { 330 RepeatedField* self = ruby_to_RepeatedField(_self); 331 VALUE new_rptfield = RepeatedField_new_this_type(_self); 332 RepeatedField* new_rptfield_self = ruby_to_RepeatedField(new_rptfield); 333 upb_fieldtype_t field_type = self->field_type; 334 size_t elem_size = native_slot_size(field_type); 335 size_t off = 0; 336 RepeatedField_reserve(new_rptfield_self, self->size); 337 for (int i = 0; i < self->size; i++, off += elem_size) { 338 void* to_mem = (uint8_t *)new_rptfield_self->elements + off; 339 void* from_mem = (uint8_t *)self->elements + off; 340 native_slot_dup(field_type, to_mem, from_mem); 341 new_rptfield_self->size++; 342 } 343 344 return new_rptfield; 345 } 346 347 // Internal only: used by Google::Protobuf.deep_copy. 348 VALUE RepeatedField_deep_copy(VALUE _self) { 349 RepeatedField* self = ruby_to_RepeatedField(_self); 350 VALUE new_rptfield = RepeatedField_new_this_type(_self); 351 RepeatedField* new_rptfield_self = ruby_to_RepeatedField(new_rptfield); 352 upb_fieldtype_t field_type = self->field_type; 353 size_t elem_size = native_slot_size(field_type); 354 size_t off = 0; 355 RepeatedField_reserve(new_rptfield_self, self->size); 356 for (int i = 0; i < self->size; i++, off += elem_size) { 357 void* to_mem = (uint8_t *)new_rptfield_self->elements + off; 358 void* from_mem = (uint8_t *)self->elements + off; 359 native_slot_deep_copy(field_type, to_mem, from_mem); 360 new_rptfield_self->size++; 361 } 362 363 return new_rptfield; 364 } 365 366 /* 367 * call-seq: 368 * RepeatedField.to_ary => array 369 * 370 * Used when converted implicitly into array, e.g. compared to an Array. 371 * Also called as a fallback of Object#to_a 372 */ 373 VALUE RepeatedField_to_ary(VALUE _self) { 374 RepeatedField* self = ruby_to_RepeatedField(_self); 375 upb_fieldtype_t field_type = self->field_type; 376 377 size_t elem_size = native_slot_size(field_type); 378 size_t off = 0; 379 VALUE ary = rb_ary_new2(self->size); 380 for (int i = 0; i < self->size; i++, off += elem_size) { 381 void* mem = ((uint8_t *)self->elements) + off; 382 VALUE elem = native_slot_get(field_type, self->field_type_class, mem); 383 rb_ary_push(ary, elem); 384 } 385 return ary; 386 } 387 388 /* 389 * call-seq: 390 * RepeatedField.==(other) => boolean 391 * 392 * Compares this repeated field to another. Repeated fields are equal if their 393 * element types are equal, their lengths are equal, and each element is equal. 394 * Elements are compared as per normal Ruby semantics, by calling their :== 395 * methods (or performing a more efficient comparison for primitive types). 396 * 397 * Repeated fields with dissimilar element types are never equal, even if value 398 * comparison (for example, between integers and floats) would have otherwise 399 * indicated that every element has equal value. 400 */ 401 VALUE RepeatedField_eq(VALUE _self, VALUE _other) { 402 RepeatedField* self; 403 RepeatedField* other; 404 405 if (_self == _other) { 406 return Qtrue; 407 } 408 409 if (TYPE(_other) == T_ARRAY) { 410 VALUE self_ary = RepeatedField_to_ary(_self); 411 return rb_equal(self_ary, _other); 412 } 413 414 self = ruby_to_RepeatedField(_self); 415 other = ruby_to_RepeatedField(_other); 416 if (self->field_type != other->field_type || 417 self->field_type_class != other->field_type_class || 418 self->size != other->size) { 419 return Qfalse; 420 } 421 422 { 423 upb_fieldtype_t field_type = self->field_type; 424 size_t elem_size = native_slot_size(field_type); 425 size_t off = 0; 426 for (int i = 0; i < self->size; i++, off += elem_size) { 427 void* self_mem = ((uint8_t *)self->elements) + off; 428 void* other_mem = ((uint8_t *)other->elements) + off; 429 if (!native_slot_eq(field_type, self_mem, other_mem)) { 430 return Qfalse; 431 } 432 } 433 return Qtrue; 434 } 435 } 436 437 /* 438 * call-seq: 439 * RepeatedField.hash => hash_value 440 * 441 * Returns a hash value computed from this repeated field's elements. 442 */ 443 VALUE RepeatedField_hash(VALUE _self) { 444 RepeatedField* self = ruby_to_RepeatedField(_self); 445 446 VALUE hash = LL2NUM(0); 447 448 upb_fieldtype_t field_type = self->field_type; 449 VALUE field_type_class = self->field_type_class; 450 size_t elem_size = native_slot_size(field_type); 451 size_t off = 0; 452 for (int i = 0; i < self->size; i++, off += elem_size) { 453 void* mem = ((uint8_t *)self->elements) + off; 454 VALUE elem = native_slot_get(field_type, field_type_class, mem); 455 hash = rb_funcall(hash, rb_intern("<<"), 1, INT2NUM(2)); 456 hash = rb_funcall(hash, rb_intern("^"), 1, 457 rb_funcall(elem, rb_intern("hash"), 0)); 458 } 459 460 return hash; 461 } 462 463 /* 464 * call-seq: 465 * RepeatedField.+(other) => repeated field 466 * 467 * Returns a new repeated field that contains the concatenated list of this 468 * repeated field's elements and other's elements. The other (second) list may 469 * be either another repeated field or a Ruby array. 470 */ 471 VALUE RepeatedField_plus(VALUE _self, VALUE list) { 472 VALUE dupped = RepeatedField_dup(_self); 473 474 if (TYPE(list) == T_ARRAY) { 475 for (int i = 0; i < RARRAY_LEN(list); i++) { 476 VALUE elem = rb_ary_entry(list, i); 477 RepeatedField_push(dupped, elem); 478 } 479 } else if (RB_TYPE_P(list, T_DATA) && RTYPEDDATA_P(list) && 480 RTYPEDDATA_TYPE(list) == &RepeatedField_type) { 481 RepeatedField* self = ruby_to_RepeatedField(_self); 482 RepeatedField* list_rptfield = ruby_to_RepeatedField(list); 483 if (self->field_type != list_rptfield->field_type || 484 self->field_type_class != list_rptfield->field_type_class) { 485 rb_raise(rb_eArgError, 486 "Attempt to append RepeatedField with different element type."); 487 } 488 for (int i = 0; i < list_rptfield->size; i++) { 489 void* mem = RepeatedField_index_native(list, i); 490 RepeatedField_push_native(dupped, mem); 491 } 492 } else { 493 rb_raise(rb_eArgError, "Unknown type appending to RepeatedField"); 494 } 495 496 return dupped; 497 } 498 499 /* 500 * call-seq: 501 * RepeatedField.concat(other) => self 502 * 503 * concats the passed in array to self. Returns a Ruby array. 504 */ 505 VALUE RepeatedField_concat(VALUE _self, VALUE list) { 506 Check_Type(list, T_ARRAY); 507 for (int i = 0; i < RARRAY_LEN(list); i++) { 508 RepeatedField_push(_self, rb_ary_entry(list, i)); 509 } 510 return _self; 511 } 512 513 514 void validate_type_class(upb_fieldtype_t type, VALUE klass) { 515 if (rb_ivar_get(klass, descriptor_instancevar_interned) == Qnil) { 516 rb_raise(rb_eArgError, 517 "Type class has no descriptor. Please pass a " 518 "class or enum as returned by the DescriptorPool."); 519 } 520 if (type == UPB_TYPE_MESSAGE) { 521 VALUE desc = rb_ivar_get(klass, descriptor_instancevar_interned); 522 if (!RB_TYPE_P(desc, T_DATA) || !RTYPEDDATA_P(desc) || 523 RTYPEDDATA_TYPE(desc) != &_Descriptor_type) { 524 rb_raise(rb_eArgError, "Descriptor has an incorrect type."); 525 } 526 if (rb_get_alloc_func(klass) != &Message_alloc) { 527 rb_raise(rb_eArgError, 528 "Message class was not returned by the DescriptorPool."); 529 } 530 } else if (type == UPB_TYPE_ENUM) { 531 VALUE enumdesc = rb_ivar_get(klass, descriptor_instancevar_interned); 532 if (!RB_TYPE_P(enumdesc, T_DATA) || !RTYPEDDATA_P(enumdesc) || 533 RTYPEDDATA_TYPE(enumdesc) != &_EnumDescriptor_type) { 534 rb_raise(rb_eArgError, "Descriptor has an incorrect type."); 535 } 536 } 537 } 538 539 void RepeatedField_init_args(int argc, VALUE* argv, 540 VALUE _self) { 541 RepeatedField* self = ruby_to_RepeatedField(_self); 542 VALUE ary = Qnil; 543 if (argc < 1) { 544 rb_raise(rb_eArgError, "Expected at least 1 argument."); 545 } 546 self->field_type = ruby_to_fieldtype(argv[0]); 547 548 if (self->field_type == UPB_TYPE_MESSAGE || 549 self->field_type == UPB_TYPE_ENUM) { 550 if (argc < 2) { 551 rb_raise(rb_eArgError, "Expected at least 2 arguments for message/enum."); 552 } 553 self->field_type_class = argv[1]; 554 if (argc > 2) { 555 ary = argv[2]; 556 } 557 validate_type_class(self->field_type, self->field_type_class); 558 } else { 559 if (argc > 2) { 560 rb_raise(rb_eArgError, "Too many arguments: expected 1 or 2."); 561 } 562 if (argc > 1) { 563 ary = argv[1]; 564 } 565 } 566 567 if (ary != Qnil) { 568 if (!RB_TYPE_P(ary, T_ARRAY)) { 569 rb_raise(rb_eArgError, "Expected array as initialize argument"); 570 } 571 for (int i = 0; i < RARRAY_LEN(ary); i++) { 572 RepeatedField_push(_self, rb_ary_entry(ary, i)); 573 } 574 } 575 } 576 577 // Mark, free, alloc, init and class setup functions. 578 579 void RepeatedField_mark(void* _self) { 580 RepeatedField* self = (RepeatedField*)_self; 581 upb_fieldtype_t field_type = self->field_type; 582 int element_size = native_slot_size(field_type); 583 rb_gc_mark(self->field_type_class); 584 for (int i = 0; i < self->size; i++) { 585 void* memory = (((uint8_t *)self->elements) + i * element_size); 586 native_slot_mark(self->field_type, memory); 587 } 588 } 589 590 void RepeatedField_free(void* _self) { 591 RepeatedField* self = (RepeatedField*)_self; 592 xfree(self->elements); 593 xfree(self); 594 } 595 596 /* 597 * call-seq: 598 * RepeatedField.new(type, type_class = nil, initial_elems = []) 599 * 600 * Creates a new repeated field. The provided type must be a Ruby symbol, and 601 * can take on the same values as those accepted by FieldDescriptor#type=. If 602 * the type is :message or :enum, type_class must be non-nil, and must be the 603 * Ruby class or module returned by Descriptor#msgclass or 604 * EnumDescriptor#enummodule, respectively. An initial list of elements may also 605 * be provided. 606 */ 607 VALUE RepeatedField_alloc(VALUE klass) { 608 RepeatedField* self = ALLOC(RepeatedField); 609 self->elements = NULL; 610 self->size = 0; 611 self->capacity = 0; 612 self->field_type = -1; 613 self->field_type_class = Qnil; 614 return TypedData_Wrap_Struct(klass, &RepeatedField_type, self); 615 } 616 617 VALUE RepeatedField_init(int argc, VALUE* argv, VALUE self) { 618 RepeatedField_init_args(argc, argv, self); 619 return Qnil; 620 } 621 622 void RepeatedField_register(VALUE module) { 623 VALUE klass = rb_define_class_under( 624 module, "RepeatedField", rb_cObject); 625 rb_define_alloc_func(klass, RepeatedField_alloc); 626 cRepeatedField = klass; 627 rb_gc_register_address(&cRepeatedField); 628 629 rb_define_method(klass, "initialize", 630 RepeatedField_init, -1); 631 rb_define_method(klass, "each", RepeatedField_each, 0); 632 rb_define_method(klass, "[]", RepeatedField_index, -1); 633 rb_define_method(klass, "at", RepeatedField_index, -1); 634 rb_define_method(klass, "[]=", RepeatedField_index_set, 2); 635 rb_define_method(klass, "push", RepeatedField_push, 1); 636 rb_define_method(klass, "<<", RepeatedField_push, 1); 637 rb_define_private_method(klass, "pop_one", RepeatedField_pop_one, 0); 638 rb_define_method(klass, "replace", RepeatedField_replace, 1); 639 rb_define_method(klass, "clear", RepeatedField_clear, 0); 640 rb_define_method(klass, "length", RepeatedField_length, 0); 641 rb_define_method(klass, "size", RepeatedField_length, 0); 642 rb_define_method(klass, "dup", RepeatedField_dup, 0); 643 // Also define #clone so that we don't inherit Object#clone. 644 rb_define_method(klass, "clone", RepeatedField_dup, 0); 645 rb_define_method(klass, "==", RepeatedField_eq, 1); 646 rb_define_method(klass, "to_ary", RepeatedField_to_ary, 0); 647 rb_define_method(klass, "hash", RepeatedField_hash, 0); 648 rb_define_method(klass, "+", RepeatedField_plus, 1); 649 rb_define_method(klass, "concat", RepeatedField_concat, 1); 650 rb_include_module(klass, rb_mEnumerable); 651 } 652