google-protobuf 3.21.0.rc.2-x64-mingw-ucrt

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of google-protobuf might be problematic. Click here for more details.

Files changed (43) hide show
  1. checksums.yaml +7 -0
  2. data/ext/google/protobuf_c/convert.c +361 -0
  3. data/ext/google/protobuf_c/convert.h +75 -0
  4. data/ext/google/protobuf_c/defs.c +1280 -0
  5. data/ext/google/protobuf_c/defs.h +107 -0
  6. data/ext/google/protobuf_c/extconf.rb +28 -0
  7. data/ext/google/protobuf_c/map.c +702 -0
  8. data/ext/google/protobuf_c/map.h +66 -0
  9. data/ext/google/protobuf_c/message.c +1402 -0
  10. data/ext/google/protobuf_c/message.h +104 -0
  11. data/ext/google/protobuf_c/protobuf.c +480 -0
  12. data/ext/google/protobuf_c/protobuf.h +120 -0
  13. data/ext/google/protobuf_c/repeated_field.c +657 -0
  14. data/ext/google/protobuf_c/repeated_field.h +63 -0
  15. data/ext/google/protobuf_c/ruby-upb.c +11115 -0
  16. data/ext/google/protobuf_c/ruby-upb.h +5612 -0
  17. data/ext/google/protobuf_c/third_party/utf8_range/LICENSE +21 -0
  18. data/ext/google/protobuf_c/third_party/utf8_range/naive.c +92 -0
  19. data/ext/google/protobuf_c/third_party/utf8_range/range2-neon.c +157 -0
  20. data/ext/google/protobuf_c/third_party/utf8_range/range2-sse.c +170 -0
  21. data/ext/google/protobuf_c/third_party/utf8_range/utf8_range.h +9 -0
  22. data/ext/google/protobuf_c/wrap_memcpy.c +52 -0
  23. data/lib/google/3.1/protobuf_c.so +0 -0
  24. data/lib/google/protobuf/any_pb.rb +19 -0
  25. data/lib/google/protobuf/api_pb.rb +42 -0
  26. data/lib/google/protobuf/descriptor_dsl.rb +465 -0
  27. data/lib/google/protobuf/descriptor_pb.rb +269 -0
  28. data/lib/google/protobuf/duration_pb.rb +19 -0
  29. data/lib/google/protobuf/empty_pb.rb +17 -0
  30. data/lib/google/protobuf/field_mask_pb.rb +18 -0
  31. data/lib/google/protobuf/message_exts.rb +53 -0
  32. data/lib/google/protobuf/repeated_field.rb +201 -0
  33. data/lib/google/protobuf/source_context_pb.rb +18 -0
  34. data/lib/google/protobuf/struct_pb.rb +37 -0
  35. data/lib/google/protobuf/timestamp_pb.rb +19 -0
  36. data/lib/google/protobuf/type_pb.rb +92 -0
  37. data/lib/google/protobuf/well_known_types.rb +240 -0
  38. data/lib/google/protobuf/wrappers_pb.rb +50 -0
  39. data/lib/google/protobuf.rb +79 -0
  40. data/tests/basic.rb +739 -0
  41. data/tests/generated_code_test.rb +23 -0
  42. data/tests/stress.rb +38 -0
  43. metadata +138 -0
@@ -0,0 +1,657 @@
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 "repeated_field.h"
32
+
33
+ #include "convert.h"
34
+ #include "defs.h"
35
+ #include "message.h"
36
+ #include "protobuf.h"
37
+
38
+ // -----------------------------------------------------------------------------
39
+ // Repeated field container type.
40
+ // -----------------------------------------------------------------------------
41
+
42
+ typedef struct {
43
+ const upb_Array* array; // Can get as mutable when non-frozen.
44
+ TypeInfo type_info;
45
+ VALUE type_class; // To GC-root the msgdef/enumdef in type_info.
46
+ VALUE arena; // To GC-root the upb_Array.
47
+ } RepeatedField;
48
+
49
+ VALUE cRepeatedField;
50
+
51
+ static void RepeatedField_mark(void* _self) {
52
+ RepeatedField* self = (RepeatedField*)_self;
53
+ rb_gc_mark(self->type_class);
54
+ rb_gc_mark(self->arena);
55
+ }
56
+
57
+ const rb_data_type_t RepeatedField_type = {
58
+ "Google::Protobuf::RepeatedField",
59
+ {RepeatedField_mark, RUBY_DEFAULT_FREE, NULL},
60
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY,
61
+ };
62
+
63
+ static RepeatedField* ruby_to_RepeatedField(VALUE _self) {
64
+ RepeatedField* self;
65
+ TypedData_Get_Struct(_self, RepeatedField, &RepeatedField_type, self);
66
+ return self;
67
+ }
68
+
69
+ static upb_Array* RepeatedField_GetMutable(VALUE _self) {
70
+ rb_check_frozen(_self);
71
+ return (upb_Array*)ruby_to_RepeatedField(_self)->array;
72
+ }
73
+
74
+ VALUE RepeatedField_alloc(VALUE klass) {
75
+ RepeatedField* self = ALLOC(RepeatedField);
76
+ self->arena = Qnil;
77
+ self->type_class = Qnil;
78
+ self->array = NULL;
79
+ return TypedData_Wrap_Struct(klass, &RepeatedField_type, self);
80
+ }
81
+
82
+ VALUE RepeatedField_GetRubyWrapper(upb_Array* array, TypeInfo type_info,
83
+ VALUE arena) {
84
+ PBRUBY_ASSERT(array);
85
+ VALUE val = ObjectCache_Get(array);
86
+
87
+ if (val == Qnil) {
88
+ val = RepeatedField_alloc(cRepeatedField);
89
+ RepeatedField* self;
90
+ ObjectCache_Add(array, val);
91
+ TypedData_Get_Struct(val, RepeatedField, &RepeatedField_type, self);
92
+ self->array = array;
93
+ self->arena = arena;
94
+ self->type_info = type_info;
95
+ if (self->type_info.type == kUpb_CType_Message) {
96
+ self->type_class = Descriptor_DefToClass(type_info.def.msgdef);
97
+ }
98
+ }
99
+
100
+ PBRUBY_ASSERT(ruby_to_RepeatedField(val)->type_info.type == type_info.type);
101
+ PBRUBY_ASSERT(ruby_to_RepeatedField(val)->type_info.def.msgdef ==
102
+ type_info.def.msgdef);
103
+ return val;
104
+ }
105
+
106
+ static VALUE RepeatedField_new_this_type(RepeatedField* from) {
107
+ VALUE arena_rb = Arena_new();
108
+ upb_Array* array = upb_Array_New(Arena_get(arena_rb), from->type_info.type);
109
+ VALUE ret = RepeatedField_GetRubyWrapper(array, from->type_info, arena_rb);
110
+ PBRUBY_ASSERT(ruby_to_RepeatedField(ret)->type_class == from->type_class);
111
+ return ret;
112
+ }
113
+
114
+ void RepeatedField_Inspect(StringBuilder* b, const upb_Array* array,
115
+ TypeInfo info) {
116
+ bool first = true;
117
+ StringBuilder_Printf(b, "[");
118
+ size_t n = array ? upb_Array_Size(array) : 0;
119
+ for (size_t i = 0; i < n; i++) {
120
+ if (first) {
121
+ first = false;
122
+ } else {
123
+ StringBuilder_Printf(b, ", ");
124
+ }
125
+ StringBuilder_PrintMsgval(b, upb_Array_Get(array, i), info);
126
+ }
127
+ StringBuilder_Printf(b, "]");
128
+ }
129
+
130
+ VALUE RepeatedField_deep_copy(VALUE _self) {
131
+ RepeatedField* self = ruby_to_RepeatedField(_self);
132
+ VALUE new_rptfield = RepeatedField_new_this_type(self);
133
+ RepeatedField* new_self = ruby_to_RepeatedField(new_rptfield);
134
+ VALUE arena_rb = new_self->arena;
135
+ upb_Array* new_array = RepeatedField_GetMutable(new_rptfield);
136
+ upb_Arena* arena = Arena_get(arena_rb);
137
+ size_t elements = upb_Array_Size(self->array);
138
+
139
+ upb_Array_Resize(new_array, elements, arena);
140
+
141
+ size_t size = upb_Array_Size(self->array);
142
+ for (size_t i = 0; i < size; i++) {
143
+ upb_MessageValue msgval = upb_Array_Get(self->array, i);
144
+ upb_MessageValue copy = Msgval_DeepCopy(msgval, self->type_info, arena);
145
+ upb_Array_Set(new_array, i, copy);
146
+ }
147
+
148
+ return new_rptfield;
149
+ }
150
+
151
+ const upb_Array* RepeatedField_GetUpbArray(VALUE val, const upb_FieldDef* field,
152
+ upb_Arena* arena) {
153
+ RepeatedField* self;
154
+ TypeInfo type_info = TypeInfo_get(field);
155
+
156
+ if (!RB_TYPE_P(val, T_DATA) || !RTYPEDDATA_P(val) ||
157
+ RTYPEDDATA_TYPE(val) != &RepeatedField_type) {
158
+ rb_raise(cTypeError, "Expected repeated field array");
159
+ }
160
+
161
+ self = ruby_to_RepeatedField(val);
162
+ if (self->type_info.type != type_info.type) {
163
+ rb_raise(cTypeError, "Repeated field array has wrong element type");
164
+ }
165
+
166
+ if (self->type_info.def.msgdef != type_info.def.msgdef) {
167
+ rb_raise(cTypeError, "Repeated field array has wrong message/enum class");
168
+ }
169
+
170
+ Arena_fuse(self->arena, arena);
171
+ return self->array;
172
+ }
173
+
174
+ static int index_position(VALUE _index, RepeatedField* repeated_field) {
175
+ int index = NUM2INT(_index);
176
+ if (index < 0) index += upb_Array_Size(repeated_field->array);
177
+ return index;
178
+ }
179
+
180
+ static VALUE RepeatedField_subarray(RepeatedField* self, long beg, long len) {
181
+ size_t size = upb_Array_Size(self->array);
182
+ VALUE ary = rb_ary_new2(size);
183
+ long i;
184
+
185
+ for (i = beg; i < beg + len; i++) {
186
+ upb_MessageValue msgval = upb_Array_Get(self->array, i);
187
+ VALUE elem = Convert_UpbToRuby(msgval, self->type_info, self->arena);
188
+ rb_ary_push(ary, elem);
189
+ }
190
+ return ary;
191
+ }
192
+
193
+ /*
194
+ * call-seq:
195
+ * RepeatedField.each(&block)
196
+ *
197
+ * Invokes the block once for each element of the repeated field. RepeatedField
198
+ * also includes Enumerable; combined with this method, the repeated field thus
199
+ * acts like an ordinary Ruby sequence.
200
+ */
201
+ static VALUE RepeatedField_each(VALUE _self) {
202
+ RepeatedField* self = ruby_to_RepeatedField(_self);
203
+ int size = upb_Array_Size(self->array);
204
+ int i;
205
+
206
+ for (i = 0; i < size; i++) {
207
+ upb_MessageValue msgval = upb_Array_Get(self->array, i);
208
+ VALUE val = Convert_UpbToRuby(msgval, self->type_info, self->arena);
209
+ rb_yield(val);
210
+ }
211
+ return _self;
212
+ }
213
+
214
+ /*
215
+ * call-seq:
216
+ * RepeatedField.[](index) => value
217
+ *
218
+ * Accesses the element at the given index. Returns nil on out-of-bounds
219
+ */
220
+ static VALUE RepeatedField_index(int argc, VALUE* argv, VALUE _self) {
221
+ RepeatedField* self = ruby_to_RepeatedField(_self);
222
+ long size = upb_Array_Size(self->array);
223
+
224
+ VALUE arg = argv[0];
225
+ long beg, len;
226
+
227
+ if (argc == 1) {
228
+ if (FIXNUM_P(arg)) {
229
+ /* standard case */
230
+ upb_MessageValue msgval;
231
+ int index = index_position(argv[0], self);
232
+ if (index < 0 || (size_t)index >= upb_Array_Size(self->array)) {
233
+ return Qnil;
234
+ }
235
+ msgval = upb_Array_Get(self->array, index);
236
+ return Convert_UpbToRuby(msgval, self->type_info, self->arena);
237
+ } else {
238
+ /* check if idx is Range */
239
+ switch (rb_range_beg_len(arg, &beg, &len, size, 0)) {
240
+ case Qfalse:
241
+ break;
242
+ case Qnil:
243
+ return Qnil;
244
+ default:
245
+ return RepeatedField_subarray(self, beg, len);
246
+ }
247
+ }
248
+ }
249
+
250
+ /* assume 2 arguments */
251
+ beg = NUM2LONG(argv[0]);
252
+ len = NUM2LONG(argv[1]);
253
+ if (beg < 0) {
254
+ beg += size;
255
+ }
256
+ if (beg >= size) {
257
+ return Qnil;
258
+ }
259
+ return RepeatedField_subarray(self, beg, len);
260
+ }
261
+
262
+ /*
263
+ * call-seq:
264
+ * RepeatedField.[]=(index, value)
265
+ *
266
+ * Sets the element at the given index. On out-of-bounds assignments, extends
267
+ * the array and fills the hole (if any) with default values.
268
+ */
269
+ static VALUE RepeatedField_index_set(VALUE _self, VALUE _index, VALUE val) {
270
+ RepeatedField* self = ruby_to_RepeatedField(_self);
271
+ int size = upb_Array_Size(self->array);
272
+ upb_Array* array = RepeatedField_GetMutable(_self);
273
+ upb_Arena* arena = Arena_get(self->arena);
274
+ upb_MessageValue msgval = Convert_RubyToUpb(val, "", self->type_info, arena);
275
+
276
+ int index = index_position(_index, self);
277
+ if (index < 0 || index >= (INT_MAX - 1)) {
278
+ return Qnil;
279
+ }
280
+
281
+ if (index >= size) {
282
+ upb_Array_Resize(array, index + 1, arena);
283
+ upb_MessageValue fill;
284
+ memset(&fill, 0, sizeof(fill));
285
+ for (int i = size; i < index; i++) {
286
+ // Fill default values.
287
+ // TODO(haberman): should this happen at the upb level?
288
+ upb_Array_Set(array, i, fill);
289
+ }
290
+ }
291
+
292
+ upb_Array_Set(array, index, msgval);
293
+ return Qnil;
294
+ }
295
+
296
+ /*
297
+ * call-seq:
298
+ * RepeatedField.push(value, ...)
299
+ *
300
+ * Adds a new element to the repeated field.
301
+ */
302
+ static VALUE RepeatedField_push_vararg(int argc, VALUE* argv, VALUE _self) {
303
+ RepeatedField* self = ruby_to_RepeatedField(_self);
304
+ upb_Arena* arena = Arena_get(self->arena);
305
+ upb_Array* array = RepeatedField_GetMutable(_self);
306
+ int i;
307
+
308
+ for (i = 0; i < argc; i++) {
309
+ upb_MessageValue msgval =
310
+ Convert_RubyToUpb(argv[i], "", self->type_info, arena);
311
+ upb_Array_Append(array, msgval, arena);
312
+ }
313
+
314
+ return _self;
315
+ }
316
+
317
+ /*
318
+ * call-seq:
319
+ * RepeatedField.<<(value)
320
+ *
321
+ * Adds a new element to the repeated field.
322
+ */
323
+ static VALUE RepeatedField_push(VALUE _self, VALUE val) {
324
+ RepeatedField* self = ruby_to_RepeatedField(_self);
325
+ upb_Arena* arena = Arena_get(self->arena);
326
+ upb_Array* array = RepeatedField_GetMutable(_self);
327
+
328
+ upb_MessageValue msgval = Convert_RubyToUpb(val, "", self->type_info, arena);
329
+ upb_Array_Append(array, msgval, arena);
330
+
331
+ return _self;
332
+ }
333
+
334
+ /*
335
+ * Private ruby method, used by RepeatedField.pop
336
+ */
337
+ static VALUE RepeatedField_pop_one(VALUE _self) {
338
+ RepeatedField* self = ruby_to_RepeatedField(_self);
339
+ size_t size = upb_Array_Size(self->array);
340
+ upb_Array* array = RepeatedField_GetMutable(_self);
341
+ upb_MessageValue last;
342
+ VALUE ret;
343
+
344
+ if (size == 0) {
345
+ return Qnil;
346
+ }
347
+
348
+ last = upb_Array_Get(self->array, size - 1);
349
+ ret = Convert_UpbToRuby(last, self->type_info, self->arena);
350
+
351
+ upb_Array_Resize(array, size - 1, Arena_get(self->arena));
352
+ return ret;
353
+ }
354
+
355
+ /*
356
+ * call-seq:
357
+ * RepeatedField.replace(list)
358
+ *
359
+ * Replaces the contents of the repeated field with the given list of elements.
360
+ */
361
+ static VALUE RepeatedField_replace(VALUE _self, VALUE list) {
362
+ RepeatedField* self = ruby_to_RepeatedField(_self);
363
+ upb_Array* array = RepeatedField_GetMutable(_self);
364
+ int i;
365
+
366
+ Check_Type(list, T_ARRAY);
367
+ upb_Array_Resize(array, 0, Arena_get(self->arena));
368
+
369
+ for (i = 0; i < RARRAY_LEN(list); i++) {
370
+ RepeatedField_push(_self, rb_ary_entry(list, i));
371
+ }
372
+
373
+ return list;
374
+ }
375
+
376
+ /*
377
+ * call-seq:
378
+ * RepeatedField.clear
379
+ *
380
+ * Clears (removes all elements from) this repeated field.
381
+ */
382
+ static VALUE RepeatedField_clear(VALUE _self) {
383
+ RepeatedField* self = ruby_to_RepeatedField(_self);
384
+ upb_Array* array = RepeatedField_GetMutable(_self);
385
+ upb_Array_Resize(array, 0, Arena_get(self->arena));
386
+ return _self;
387
+ }
388
+
389
+ /*
390
+ * call-seq:
391
+ * RepeatedField.length
392
+ *
393
+ * Returns the length of this repeated field.
394
+ */
395
+ static VALUE RepeatedField_length(VALUE _self) {
396
+ RepeatedField* self = ruby_to_RepeatedField(_self);
397
+ return INT2NUM(upb_Array_Size(self->array));
398
+ }
399
+
400
+ /*
401
+ * call-seq:
402
+ * RepeatedField.dup => repeated_field
403
+ *
404
+ * Duplicates this repeated field with a shallow copy. References to all
405
+ * non-primitive element objects (e.g., submessages) are shared.
406
+ */
407
+ static VALUE RepeatedField_dup(VALUE _self) {
408
+ RepeatedField* self = ruby_to_RepeatedField(_self);
409
+ VALUE new_rptfield = RepeatedField_new_this_type(self);
410
+ RepeatedField* new_rptfield_self = ruby_to_RepeatedField(new_rptfield);
411
+ upb_Array* new_array = RepeatedField_GetMutable(new_rptfield);
412
+ upb_Arena* arena = Arena_get(new_rptfield_self->arena);
413
+ int size = upb_Array_Size(self->array);
414
+ int i;
415
+
416
+ Arena_fuse(self->arena, arena);
417
+
418
+ for (i = 0; i < size; i++) {
419
+ upb_MessageValue msgval = upb_Array_Get(self->array, i);
420
+ upb_Array_Append(new_array, msgval, arena);
421
+ }
422
+
423
+ return new_rptfield;
424
+ }
425
+
426
+ /*
427
+ * call-seq:
428
+ * RepeatedField.to_ary => array
429
+ *
430
+ * Used when converted implicitly into array, e.g. compared to an Array.
431
+ * Also called as a fallback of Object#to_a
432
+ */
433
+ VALUE RepeatedField_to_ary(VALUE _self) {
434
+ RepeatedField* self = ruby_to_RepeatedField(_self);
435
+ int size = upb_Array_Size(self->array);
436
+ VALUE ary = rb_ary_new2(size);
437
+ int i;
438
+
439
+ for (i = 0; i < size; i++) {
440
+ upb_MessageValue msgval = upb_Array_Get(self->array, i);
441
+ VALUE val = Convert_UpbToRuby(msgval, self->type_info, self->arena);
442
+ rb_ary_push(ary, val);
443
+ }
444
+
445
+ return ary;
446
+ }
447
+
448
+ /*
449
+ * call-seq:
450
+ * RepeatedField.==(other) => boolean
451
+ *
452
+ * Compares this repeated field to another. Repeated fields are equal if their
453
+ * element types are equal, their lengths are equal, and each element is equal.
454
+ * Elements are compared as per normal Ruby semantics, by calling their :==
455
+ * methods (or performing a more efficient comparison for primitive types).
456
+ *
457
+ * Repeated fields with dissimilar element types are never equal, even if value
458
+ * comparison (for example, between integers and floats) would have otherwise
459
+ * indicated that every element has equal value.
460
+ */
461
+ VALUE RepeatedField_eq(VALUE _self, VALUE _other) {
462
+ RepeatedField* self;
463
+ RepeatedField* other;
464
+
465
+ if (_self == _other) {
466
+ return Qtrue;
467
+ }
468
+
469
+ if (TYPE(_other) == T_ARRAY) {
470
+ VALUE self_ary = RepeatedField_to_ary(_self);
471
+ return rb_equal(self_ary, _other);
472
+ }
473
+
474
+ self = ruby_to_RepeatedField(_self);
475
+ other = ruby_to_RepeatedField(_other);
476
+ size_t n = upb_Array_Size(self->array);
477
+
478
+ if (self->type_info.type != other->type_info.type ||
479
+ self->type_class != other->type_class ||
480
+ upb_Array_Size(other->array) != n) {
481
+ return Qfalse;
482
+ }
483
+
484
+ for (size_t i = 0; i < n; i++) {
485
+ upb_MessageValue val1 = upb_Array_Get(self->array, i);
486
+ upb_MessageValue val2 = upb_Array_Get(other->array, i);
487
+ if (!Msgval_IsEqual(val1, val2, self->type_info)) {
488
+ return Qfalse;
489
+ }
490
+ }
491
+
492
+ return Qtrue;
493
+ }
494
+
495
+ /*
496
+ * call-seq:
497
+ * RepeatedField.freeze => self
498
+ *
499
+ * Freezes the repeated field. We have to intercept this so we can pin the Ruby
500
+ * object into memory so we don't forget it's frozen.
501
+ */
502
+ static VALUE RepeatedField_freeze(VALUE _self) {
503
+ RepeatedField* self = ruby_to_RepeatedField(_self);
504
+ if (!RB_OBJ_FROZEN(_self)) {
505
+ Arena_Pin(self->arena, _self);
506
+ RB_OBJ_FREEZE(_self);
507
+ }
508
+ return _self;
509
+ }
510
+
511
+ /*
512
+ * call-seq:
513
+ * RepeatedField.hash => hash_value
514
+ *
515
+ * Returns a hash value computed from this repeated field's elements.
516
+ */
517
+ VALUE RepeatedField_hash(VALUE _self) {
518
+ RepeatedField* self = ruby_to_RepeatedField(_self);
519
+ uint64_t hash = 0;
520
+ size_t n = upb_Array_Size(self->array);
521
+
522
+ for (size_t i = 0; i < n; i++) {
523
+ upb_MessageValue val = upb_Array_Get(self->array, i);
524
+ hash = Msgval_GetHash(val, self->type_info, hash);
525
+ }
526
+
527
+ return LL2NUM(hash);
528
+ }
529
+
530
+ /*
531
+ * call-seq:
532
+ * RepeatedField.+(other) => repeated field
533
+ *
534
+ * Returns a new repeated field that contains the concatenated list of this
535
+ * repeated field's elements and other's elements. The other (second) list may
536
+ * be either another repeated field or a Ruby array.
537
+ */
538
+ VALUE RepeatedField_plus(VALUE _self, VALUE list) {
539
+ VALUE dupped_ = RepeatedField_dup(_self);
540
+
541
+ if (TYPE(list) == T_ARRAY) {
542
+ int i;
543
+ for (i = 0; i < RARRAY_LEN(list); i++) {
544
+ VALUE elem = rb_ary_entry(list, i);
545
+ RepeatedField_push(dupped_, elem);
546
+ }
547
+ } else if (RB_TYPE_P(list, T_DATA) && RTYPEDDATA_P(list) &&
548
+ RTYPEDDATA_TYPE(list) == &RepeatedField_type) {
549
+ RepeatedField* self = ruby_to_RepeatedField(_self);
550
+ RepeatedField* list_rptfield = ruby_to_RepeatedField(list);
551
+ RepeatedField* dupped = ruby_to_RepeatedField(dupped_);
552
+ upb_Array* dupped_array = RepeatedField_GetMutable(dupped_);
553
+ upb_Arena* arena = Arena_get(dupped->arena);
554
+ Arena_fuse(list_rptfield->arena, arena);
555
+ int size = upb_Array_Size(list_rptfield->array);
556
+ int i;
557
+
558
+ if (self->type_info.type != list_rptfield->type_info.type ||
559
+ self->type_class != list_rptfield->type_class) {
560
+ rb_raise(rb_eArgError,
561
+ "Attempt to append RepeatedField with different element type.");
562
+ }
563
+
564
+ for (i = 0; i < size; i++) {
565
+ upb_MessageValue msgval = upb_Array_Get(list_rptfield->array, i);
566
+ upb_Array_Append(dupped_array, msgval, arena);
567
+ }
568
+ } else {
569
+ rb_raise(rb_eArgError, "Unknown type appending to RepeatedField");
570
+ }
571
+
572
+ return dupped_;
573
+ }
574
+
575
+ /*
576
+ * call-seq:
577
+ * RepeatedField.concat(other) => self
578
+ *
579
+ * concats the passed in array to self. Returns a Ruby array.
580
+ */
581
+ VALUE RepeatedField_concat(VALUE _self, VALUE list) {
582
+ int i;
583
+
584
+ Check_Type(list, T_ARRAY);
585
+ for (i = 0; i < RARRAY_LEN(list); i++) {
586
+ RepeatedField_push(_self, rb_ary_entry(list, i));
587
+ }
588
+ return _self;
589
+ }
590
+
591
+ /*
592
+ * call-seq:
593
+ * RepeatedField.new(type, type_class = nil, initial_elems = [])
594
+ *
595
+ * Creates a new repeated field. The provided type must be a Ruby symbol, and
596
+ * can take on the same values as those accepted by FieldDescriptor#type=. If
597
+ * the type is :message or :enum, type_class must be non-nil, and must be the
598
+ * Ruby class or module returned by Descriptor#msgclass or
599
+ * EnumDescriptor#enummodule, respectively. An initial list of elements may also
600
+ * be provided.
601
+ */
602
+ VALUE RepeatedField_init(int argc, VALUE* argv, VALUE _self) {
603
+ RepeatedField* self = ruby_to_RepeatedField(_self);
604
+ upb_Arena* arena;
605
+ VALUE ary = Qnil;
606
+
607
+ self->arena = Arena_new();
608
+ arena = Arena_get(self->arena);
609
+
610
+ if (argc < 1) {
611
+ rb_raise(rb_eArgError, "Expected at least 1 argument.");
612
+ }
613
+
614
+ self->type_info = TypeInfo_FromClass(argc, argv, 0, &self->type_class, &ary);
615
+ self->array = upb_Array_New(arena, self->type_info.type);
616
+ ObjectCache_Add(self->array, _self);
617
+
618
+ if (ary != Qnil) {
619
+ if (!RB_TYPE_P(ary, T_ARRAY)) {
620
+ rb_raise(rb_eArgError, "Expected array as initialize argument");
621
+ }
622
+ for (int i = 0; i < RARRAY_LEN(ary); i++) {
623
+ RepeatedField_push(_self, rb_ary_entry(ary, i));
624
+ }
625
+ }
626
+ return Qnil;
627
+ }
628
+
629
+ void RepeatedField_register(VALUE module) {
630
+ VALUE klass = rb_define_class_under(module, "RepeatedField", rb_cObject);
631
+ rb_define_alloc_func(klass, RepeatedField_alloc);
632
+ rb_gc_register_address(&cRepeatedField);
633
+ cRepeatedField = klass;
634
+
635
+ rb_define_method(klass, "initialize", RepeatedField_init, -1);
636
+ rb_define_method(klass, "each", RepeatedField_each, 0);
637
+ rb_define_method(klass, "[]", RepeatedField_index, -1);
638
+ rb_define_method(klass, "at", RepeatedField_index, -1);
639
+ rb_define_method(klass, "[]=", RepeatedField_index_set, 2);
640
+ rb_define_method(klass, "push", RepeatedField_push_vararg, -1);
641
+ rb_define_method(klass, "<<", RepeatedField_push, 1);
642
+ rb_define_private_method(klass, "pop_one", RepeatedField_pop_one, 0);
643
+ rb_define_method(klass, "replace", RepeatedField_replace, 1);
644
+ rb_define_method(klass, "clear", RepeatedField_clear, 0);
645
+ rb_define_method(klass, "length", RepeatedField_length, 0);
646
+ rb_define_method(klass, "size", RepeatedField_length, 0);
647
+ rb_define_method(klass, "dup", RepeatedField_dup, 0);
648
+ // Also define #clone so that we don't inherit Object#clone.
649
+ rb_define_method(klass, "clone", RepeatedField_dup, 0);
650
+ rb_define_method(klass, "==", RepeatedField_eq, 1);
651
+ rb_define_method(klass, "to_ary", RepeatedField_to_ary, 0);
652
+ rb_define_method(klass, "freeze", RepeatedField_freeze, 0);
653
+ rb_define_method(klass, "hash", RepeatedField_hash, 0);
654
+ rb_define_method(klass, "+", RepeatedField_plus, 1);
655
+ rb_define_method(klass, "concat", RepeatedField_concat, 1);
656
+ rb_include_module(klass, rb_mEnumerable);
657
+ }