google-protobuf 3.7.0 → 3.16.0

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 (37) hide show
  1. checksums.yaml +4 -4
  2. data/ext/google/protobuf_c/convert.c +349 -0
  3. data/ext/google/protobuf_c/convert.h +72 -0
  4. data/ext/google/protobuf_c/defs.c +1555 -1228
  5. data/ext/google/protobuf_c/defs.h +107 -0
  6. data/ext/google/protobuf_c/extconf.rb +4 -7
  7. data/ext/google/protobuf_c/map.c +310 -470
  8. data/ext/google/protobuf_c/map.h +66 -0
  9. data/ext/google/protobuf_c/message.c +931 -346
  10. data/ext/google/protobuf_c/message.h +101 -0
  11. data/ext/google/protobuf_c/protobuf.c +384 -51
  12. data/ext/google/protobuf_c/protobuf.h +44 -544
  13. data/ext/google/protobuf_c/repeated_field.c +311 -308
  14. data/ext/google/protobuf_c/repeated_field.h +62 -0
  15. data/ext/google/protobuf_c/ruby-upb.c +8914 -0
  16. data/ext/google/protobuf_c/ruby-upb.h +4452 -0
  17. data/ext/google/protobuf_c/third_party/wyhash/wyhash.h +145 -0
  18. data/lib/google/protobuf/any_pb.rb +1 -1
  19. data/lib/google/protobuf/api_pb.rb +3 -3
  20. data/lib/google/protobuf/duration_pb.rb +1 -1
  21. data/lib/google/protobuf/empty_pb.rb +1 -1
  22. data/lib/google/protobuf/field_mask_pb.rb +1 -1
  23. data/lib/google/protobuf/source_context_pb.rb +1 -1
  24. data/lib/google/protobuf/struct_pb.rb +4 -4
  25. data/lib/google/protobuf/timestamp_pb.rb +1 -1
  26. data/lib/google/protobuf/type_pb.rb +8 -8
  27. data/lib/google/protobuf/well_known_types.rb +8 -2
  28. data/lib/google/protobuf/wrappers_pb.rb +9 -9
  29. data/lib/google/protobuf.rb +70 -0
  30. data/tests/basic.rb +315 -72
  31. data/tests/generated_code_test.rb +0 -0
  32. data/tests/stress.rb +0 -0
  33. metadata +27 -16
  34. data/ext/google/protobuf_c/encode_decode.c +0 -1574
  35. data/ext/google/protobuf_c/storage.c +0 -1019
  36. data/ext/google/protobuf_c/upb.c +0 -17318
  37. data/ext/google/protobuf_c/upb.h +0 -9755
@@ -28,48 +28,162 @@
28
28
  // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
29
  // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
30
 
31
+ #include "repeated_field.h"
32
+
33
+ #include "convert.h"
34
+ #include "defs.h"
35
+ #include "message.h"
31
36
  #include "protobuf.h"
37
+ #include "third_party/wyhash/wyhash.h"
32
38
 
33
39
  // -----------------------------------------------------------------------------
34
40
  // Repeated field container type.
35
41
  // -----------------------------------------------------------------------------
36
42
 
43
+ typedef struct {
44
+ const upb_array *array; // Can get as mutable when non-frozen.
45
+ TypeInfo type_info;
46
+ VALUE type_class; // To GC-root the msgdef/enumdef in type_info.
47
+ VALUE arena; // To GC-root the upb_array.
48
+ } RepeatedField;
49
+
50
+ VALUE cRepeatedField;
51
+
52
+ static void RepeatedField_mark(void* _self) {
53
+ RepeatedField* self = (RepeatedField*)_self;
54
+ rb_gc_mark(self->type_class);
55
+ rb_gc_mark(self->arena);
56
+ }
57
+
37
58
  const rb_data_type_t RepeatedField_type = {
38
59
  "Google::Protobuf::RepeatedField",
39
- { RepeatedField_mark, RepeatedField_free, NULL },
60
+ { RepeatedField_mark, RUBY_DEFAULT_FREE, NULL },
61
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY,
40
62
  };
41
63
 
42
- VALUE cRepeatedField;
43
-
44
- RepeatedField* ruby_to_RepeatedField(VALUE _self) {
64
+ static RepeatedField* ruby_to_RepeatedField(VALUE _self) {
45
65
  RepeatedField* self;
46
66
  TypedData_Get_Struct(_self, RepeatedField, &RepeatedField_type, self);
47
67
  return self;
48
68
  }
49
69
 
50
- void* RepeatedField_memoryat(RepeatedField* self, int index, int element_size) {
51
- return ((uint8_t *)self->elements) + index * element_size;
70
+ static upb_array *RepeatedField_GetMutable(VALUE _self) {
71
+ rb_check_frozen(_self);
72
+ return (upb_array*)ruby_to_RepeatedField(_self)->array;
73
+ }
74
+
75
+ VALUE RepeatedField_alloc(VALUE klass) {
76
+ RepeatedField* self = ALLOC(RepeatedField);
77
+ self->arena = Qnil;
78
+ self->type_class = Qnil;
79
+ self->array = NULL;
80
+ return TypedData_Wrap_Struct(klass, &RepeatedField_type, self);
81
+ }
82
+
83
+ VALUE RepeatedField_GetRubyWrapper(upb_array* array, TypeInfo type_info,
84
+ VALUE arena) {
85
+ PBRUBY_ASSERT(array);
86
+ VALUE val = ObjectCache_Get(array);
87
+
88
+ if (val == Qnil) {
89
+ val = RepeatedField_alloc(cRepeatedField);
90
+ RepeatedField* self;
91
+ ObjectCache_Add(array, val);
92
+ TypedData_Get_Struct(val, RepeatedField, &RepeatedField_type, self);
93
+ self->array = array;
94
+ self->arena = arena;
95
+ self->type_info = type_info;
96
+ if (self->type_info.type == UPB_TYPE_MESSAGE) {
97
+ self->type_class = Descriptor_DefToClass(type_info.def.msgdef);
98
+ }
99
+ }
100
+
101
+ PBRUBY_ASSERT(ruby_to_RepeatedField(val)->type_info.type == type_info.type);
102
+ PBRUBY_ASSERT(ruby_to_RepeatedField(val)->type_info.def.msgdef ==
103
+ type_info.def.msgdef);
104
+ return val;
105
+ }
106
+
107
+ static VALUE RepeatedField_new_this_type(RepeatedField* from) {
108
+ VALUE arena_rb = Arena_new();
109
+ upb_array *array = upb_array_new(Arena_get(arena_rb), from->type_info.type);
110
+ VALUE ret = RepeatedField_GetRubyWrapper(array, from->type_info, arena_rb);
111
+ PBRUBY_ASSERT(ruby_to_RepeatedField(ret)->type_class == from->type_class);
112
+ return ret;
113
+ }
114
+
115
+ void RepeatedField_Inspect(StringBuilder* b, const upb_array* array,
116
+ TypeInfo info) {
117
+ bool first = true;
118
+ StringBuilder_Printf(b, "[");
119
+ size_t n = array ? upb_array_size(array) : 0;
120
+ for (size_t i = 0; i < n; i++) {
121
+ if (first) {
122
+ first = false;
123
+ } else {
124
+ StringBuilder_Printf(b, ", ");
125
+ }
126
+ StringBuilder_PrintMsgval(b, upb_array_get(array, i), info);
127
+ }
128
+ StringBuilder_Printf(b, "]");
129
+ }
130
+
131
+ VALUE RepeatedField_deep_copy(VALUE _self) {
132
+ RepeatedField* self = ruby_to_RepeatedField(_self);
133
+ VALUE new_rptfield = RepeatedField_new_this_type(self);
134
+ RepeatedField* new_self = ruby_to_RepeatedField(new_rptfield);
135
+ VALUE arena_rb = new_self->arena;
136
+ upb_array *new_array = RepeatedField_GetMutable(new_rptfield);
137
+ upb_arena *arena = Arena_get(arena_rb);
138
+ size_t elements = upb_array_size(self->array);
139
+
140
+ upb_array_resize(new_array, elements, arena);
141
+
142
+ size_t size = upb_array_size(self->array);
143
+ for (size_t i = 0; i < size; i++) {
144
+ upb_msgval msgval = upb_array_get(self->array, i);
145
+ upb_msgval copy = Msgval_DeepCopy(msgval, self->type_info, arena);
146
+ upb_array_set(new_array, i, copy);
147
+ }
148
+
149
+ return new_rptfield;
150
+ }
151
+
152
+ const upb_array* RepeatedField_GetUpbArray(VALUE val, const upb_fielddef *field) {
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
+ return self->array;
52
171
  }
53
172
 
54
173
  static int index_position(VALUE _index, RepeatedField* repeated_field) {
55
174
  int index = NUM2INT(_index);
56
- if (index < 0 && repeated_field->size > 0) {
57
- index = repeated_field->size + index;
58
- }
175
+ if (index < 0) index += upb_array_size(repeated_field->array);
59
176
  return index;
60
177
  }
61
178
 
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);
179
+ static VALUE RepeatedField_subarray(RepeatedField* self, long beg, long len) {
180
+ size_t size = upb_array_size(self->array);
181
+ VALUE ary = rb_ary_new2(size);
182
+ long i;
183
+
184
+ for (i = beg; i < beg + len; i++) {
185
+ upb_msgval msgval = upb_array_get(self->array, i);
186
+ VALUE elem = Convert_UpbToRuby(msgval, self->type_info, self->arena);
73
187
  rb_ary_push(ary, elem);
74
188
  }
75
189
  return ary;
@@ -83,16 +197,14 @@ VALUE RepeatedField_subarray(VALUE _self, long beg, long len) {
83
197
  * also includes Enumerable; combined with this method, the repeated field thus
84
198
  * acts like an ordinary Ruby sequence.
85
199
  */
86
- VALUE RepeatedField_each(VALUE _self) {
200
+ static VALUE RepeatedField_each(VALUE _self) {
87
201
  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);
202
+ int size = upb_array_size(self->array);
203
+ int i;
204
+
205
+ for (i = 0; i < size; i++) {
206
+ upb_msgval msgval = upb_array_get(self->array, i);
207
+ VALUE val = Convert_UpbToRuby(msgval, self->type_info, self->arena);
96
208
  rb_yield(val);
97
209
  }
98
210
  return _self;
@@ -105,11 +217,9 @@ VALUE RepeatedField_each(VALUE _self) {
105
217
  *
106
218
  * Accesses the element at the given index. Returns nil on out-of-bounds
107
219
  */
108
- VALUE RepeatedField_index(int argc, VALUE* argv, VALUE _self) {
220
+ static VALUE RepeatedField_index(int argc, VALUE* argv, VALUE _self) {
109
221
  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;
222
+ long size = upb_array_size(self->array);
113
223
 
114
224
  VALUE arg = argv[0];
115
225
  long beg, len;
@@ -117,35 +227,36 @@ VALUE RepeatedField_index(int argc, VALUE* argv, VALUE _self) {
117
227
  if (argc == 1){
118
228
  if (FIXNUM_P(arg)) {
119
229
  /* standard case */
120
- void* memory;
230
+ upb_msgval msgval;
121
231
  int index = index_position(argv[0], self);
122
- if (index < 0 || index >= self->size) {
232
+ if (index < 0 || (size_t)index >= upb_array_size(self->array)) {
123
233
  return Qnil;
124
234
  }
125
- memory = RepeatedField_memoryat(self, index, element_size);
126
- return native_slot_get(field_type, field_type_class, memory);
127
- }else{
235
+ msgval = upb_array_get(self->array, index);
236
+ return Convert_UpbToRuby(msgval, self->type_info, self->arena);
237
+ } else {
128
238
  /* check if idx is Range */
129
- switch (rb_range_beg_len(arg, &beg, &len, self->size, 0)) {
239
+ switch (rb_range_beg_len(arg, &beg, &len, size, 0)) {
130
240
  case Qfalse:
131
241
  break;
132
242
  case Qnil:
133
243
  return Qnil;
134
244
  default:
135
- return RepeatedField_subarray(_self, beg, len);
245
+ return RepeatedField_subarray(self, beg, len);
136
246
  }
137
247
  }
138
248
  }
249
+
139
250
  /* assume 2 arguments */
140
251
  beg = NUM2LONG(argv[0]);
141
252
  len = NUM2LONG(argv[1]);
142
253
  if (beg < 0) {
143
- beg += self->size;
254
+ beg += size;
144
255
  }
145
- if (beg >= self->size) {
256
+ if (beg >= size) {
146
257
  return Qnil;
147
258
  }
148
- return RepeatedField_subarray(_self, beg, len);
259
+ return RepeatedField_subarray(self, beg, len);
149
260
  }
150
261
 
151
262
  /*
@@ -155,119 +266,88 @@ VALUE RepeatedField_index(int argc, VALUE* argv, VALUE _self) {
155
266
  * Sets the element at the given index. On out-of-bounds assignments, extends
156
267
  * the array and fills the hole (if any) with default values.
157
268
  */
158
- VALUE RepeatedField_index_set(VALUE _self, VALUE _index, VALUE val) {
269
+ static VALUE RepeatedField_index_set(VALUE _self, VALUE _index, VALUE val) {
159
270
  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;
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_msgval msgval = Convert_RubyToUpb(val, "", self->type_info, arena);
164
275
 
165
276
  int index = index_position(_index, self);
166
277
  if (index < 0 || index >= (INT_MAX - 1)) {
167
278
  return Qnil;
168
279
  }
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);
280
+
281
+ if (index >= size) {
282
+ upb_array_resize(array, index + 1, arena);
283
+ upb_msgval 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);
176
289
  }
177
- self->size = index + 1;
178
290
  }
179
291
 
180
- memory = RepeatedField_memoryat(self, index, element_size);
181
- native_slot_set(field_type, field_type_class, memory, val);
292
+ upb_array_set(array, index, msgval);
182
293
  return Qnil;
183
294
  }
184
295
 
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
296
  /*
207
297
  * call-seq:
208
- * RepeatedField.push(value)
298
+ * RepeatedField.push(value, ...)
209
299
  *
210
300
  * Adds a new element to the repeated field.
211
301
  */
212
- VALUE RepeatedField_push(VALUE _self, VALUE val) {
302
+ static VALUE RepeatedField_push_vararg(int argc, VALUE* argv, VALUE _self) {
213
303
  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
- }
304
+ upb_arena *arena = Arena_get(self->arena);
305
+ upb_array *array = RepeatedField_GetMutable(_self);
306
+ int i;
225
307
 
308
+ for (i = 0; i < argc; i++) {
309
+ upb_msgval msgval = Convert_RubyToUpb(argv[i], "", self->type_info, arena);
310
+ upb_array_append(array, msgval, arena);
311
+ }
226
312
 
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++;
313
+ return _self;
238
314
  }
239
315
 
240
- void* RepeatedField_index_native(VALUE _self, int index) {
316
+ /*
317
+ * call-seq:
318
+ * RepeatedField.<<(value)
319
+ *
320
+ * Adds a new element to the repeated field.
321
+ */
322
+ static VALUE RepeatedField_push(VALUE _self, VALUE val) {
241
323
  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
- }
324
+ upb_arena *arena = Arena_get(self->arena);
325
+ upb_array *array = RepeatedField_GetMutable(_self);
246
326
 
247
- int RepeatedField_size(VALUE _self) {
248
- RepeatedField* self = ruby_to_RepeatedField(_self);
249
- return self->size;
327
+ upb_msgval msgval = Convert_RubyToUpb(val, "", self->type_info, arena);
328
+ upb_array_append(array, msgval, arena);
329
+
330
+ return _self;
250
331
  }
251
332
 
252
333
  /*
253
334
  * Private ruby method, used by RepeatedField.pop
254
335
  */
255
- VALUE RepeatedField_pop_one(VALUE _self) {
336
+ static VALUE RepeatedField_pop_one(VALUE _self) {
256
337
  RepeatedField* self = ruby_to_RepeatedField(_self);
257
- upb_fieldtype_t field_type = self->field_type;
258
- VALUE field_type_class = self->field_type_class;
259
- int element_size = native_slot_size(field_type);
260
- int index;
261
- void* memory;
338
+ size_t size = upb_array_size(self->array);
339
+ upb_array *array = RepeatedField_GetMutable(_self);
340
+ upb_msgval last;
262
341
  VALUE ret;
263
342
 
264
- if (self->size == 0) {
343
+ if (size == 0) {
265
344
  return Qnil;
266
345
  }
267
- index = self->size - 1;
268
- memory = RepeatedField_memoryat(self, index, element_size);
269
- ret = native_slot_get(field_type, field_type_class, memory);
270
- self->size--;
346
+
347
+ last = upb_array_get(self->array, size - 1);
348
+ ret = Convert_UpbToRuby(last, self->type_info, self->arena);
349
+
350
+ upb_array_resize(array, size - 1, Arena_get(self->arena));
271
351
  return ret;
272
352
  }
273
353
 
@@ -277,13 +357,18 @@ VALUE RepeatedField_pop_one(VALUE _self) {
277
357
  *
278
358
  * Replaces the contents of the repeated field with the given list of elements.
279
359
  */
280
- VALUE RepeatedField_replace(VALUE _self, VALUE list) {
360
+ static VALUE RepeatedField_replace(VALUE _self, VALUE list) {
281
361
  RepeatedField* self = ruby_to_RepeatedField(_self);
362
+ upb_array *array = RepeatedField_GetMutable(_self);
363
+ int i;
364
+
282
365
  Check_Type(list, T_ARRAY);
283
- self->size = 0;
284
- for (int i = 0; i < RARRAY_LEN(list); i++) {
366
+ upb_array_resize(array, 0, Arena_get(self->arena));
367
+
368
+ for (i = 0; i < RARRAY_LEN(list); i++) {
285
369
  RepeatedField_push(_self, rb_ary_entry(list, i));
286
370
  }
371
+
287
372
  return list;
288
373
  }
289
374
 
@@ -293,9 +378,10 @@ VALUE RepeatedField_replace(VALUE _self, VALUE list) {
293
378
  *
294
379
  * Clears (removes all elements from) this repeated field.
295
380
  */
296
- VALUE RepeatedField_clear(VALUE _self) {
381
+ static VALUE RepeatedField_clear(VALUE _self) {
297
382
  RepeatedField* self = ruby_to_RepeatedField(_self);
298
- self->size = 0;
383
+ upb_array *array = RepeatedField_GetMutable(_self);
384
+ upb_array_resize(array, 0, Arena_get(self->arena));
299
385
  return _self;
300
386
  }
301
387
 
@@ -305,23 +391,9 @@ VALUE RepeatedField_clear(VALUE _self) {
305
391
  *
306
392
  * Returns the length of this repeated field.
307
393
  */
308
- VALUE RepeatedField_length(VALUE _self) {
394
+ static VALUE RepeatedField_length(VALUE _self) {
309
395
  RepeatedField* self = ruby_to_RepeatedField(_self);
310
- return INT2NUM(self->size);
311
- }
312
-
313
- static VALUE RepeatedField_new_this_type(VALUE _self) {
314
- RepeatedField* self = ruby_to_RepeatedField(_self);
315
- VALUE new_rptfield = Qnil;
316
- VALUE element_type = fieldtype_to_ruby(self->field_type);
317
- if (self->field_type_class != Qnil) {
318
- new_rptfield = rb_funcall(CLASS_OF(_self), rb_intern("new"), 2,
319
- element_type, self->field_type_class);
320
- } else {
321
- new_rptfield = rb_funcall(CLASS_OF(_self), rb_intern("new"), 1,
322
- element_type);
323
- }
324
- return new_rptfield;
396
+ return INT2NUM(upb_array_size(self->array));
325
397
  }
326
398
 
327
399
  /*
@@ -331,38 +403,20 @@ static VALUE RepeatedField_new_this_type(VALUE _self) {
331
403
  * Duplicates this repeated field with a shallow copy. References to all
332
404
  * non-primitive element objects (e.g., submessages) are shared.
333
405
  */
334
- VALUE RepeatedField_dup(VALUE _self) {
406
+ static VALUE RepeatedField_dup(VALUE _self) {
335
407
  RepeatedField* self = ruby_to_RepeatedField(_self);
336
- VALUE new_rptfield = RepeatedField_new_this_type(_self);
408
+ VALUE new_rptfield = RepeatedField_new_this_type(self);
337
409
  RepeatedField* new_rptfield_self = ruby_to_RepeatedField(new_rptfield);
338
- upb_fieldtype_t field_type = self->field_type;
339
- size_t elem_size = native_slot_size(field_type);
340
- size_t off = 0;
341
- RepeatedField_reserve(new_rptfield_self, self->size);
342
- for (int i = 0; i < self->size; i++, off += elem_size) {
343
- void* to_mem = (uint8_t *)new_rptfield_self->elements + off;
344
- void* from_mem = (uint8_t *)self->elements + off;
345
- native_slot_dup(field_type, to_mem, from_mem);
346
- new_rptfield_self->size++;
347
- }
410
+ upb_array *new_array = RepeatedField_GetMutable(new_rptfield);
411
+ upb_arena* arena = Arena_get(new_rptfield_self->arena);
412
+ int size = upb_array_size(self->array);
413
+ int i;
348
414
 
349
- return new_rptfield;
350
- }
415
+ upb_arena_fuse(arena, Arena_get(self->arena));
351
416
 
352
- // Internal only: used by Google::Protobuf.deep_copy.
353
- VALUE RepeatedField_deep_copy(VALUE _self) {
354
- RepeatedField* self = ruby_to_RepeatedField(_self);
355
- VALUE new_rptfield = RepeatedField_new_this_type(_self);
356
- RepeatedField* new_rptfield_self = ruby_to_RepeatedField(new_rptfield);
357
- upb_fieldtype_t field_type = self->field_type;
358
- size_t elem_size = native_slot_size(field_type);
359
- size_t off = 0;
360
- RepeatedField_reserve(new_rptfield_self, self->size);
361
- for (int i = 0; i < self->size; i++, off += elem_size) {
362
- void* to_mem = (uint8_t *)new_rptfield_self->elements + off;
363
- void* from_mem = (uint8_t *)self->elements + off;
364
- native_slot_deep_copy(field_type, to_mem, from_mem);
365
- new_rptfield_self->size++;
417
+ for (i = 0; i < size; i++) {
418
+ upb_msgval msgval = upb_array_get(self->array, i);
419
+ upb_array_append(new_array, msgval, arena);
366
420
  }
367
421
 
368
422
  return new_rptfield;
@@ -377,16 +431,16 @@ VALUE RepeatedField_deep_copy(VALUE _self) {
377
431
  */
378
432
  VALUE RepeatedField_to_ary(VALUE _self) {
379
433
  RepeatedField* self = ruby_to_RepeatedField(_self);
380
- upb_fieldtype_t field_type = self->field_type;
381
-
382
- size_t elem_size = native_slot_size(field_type);
383
- size_t off = 0;
384
- VALUE ary = rb_ary_new2(self->size);
385
- for (int i = 0; i < self->size; i++, off += elem_size) {
386
- void* mem = ((uint8_t *)self->elements) + off;
387
- VALUE elem = native_slot_get(field_type, self->field_type_class, mem);
388
- rb_ary_push(ary, elem);
434
+ int size = upb_array_size(self->array);
435
+ VALUE ary = rb_ary_new2(size);
436
+ int i;
437
+
438
+ for (i = 0; i < size; i++) {
439
+ upb_msgval msgval = upb_array_get(self->array, i);
440
+ VALUE val = Convert_UpbToRuby(msgval, self->type_info, self->arena);
441
+ rb_ary_push(ary, val);
389
442
  }
443
+
390
444
  return ary;
391
445
  }
392
446
 
@@ -418,25 +472,39 @@ VALUE RepeatedField_eq(VALUE _self, VALUE _other) {
418
472
 
419
473
  self = ruby_to_RepeatedField(_self);
420
474
  other = ruby_to_RepeatedField(_other);
421
- if (self->field_type != other->field_type ||
422
- self->field_type_class != other->field_type_class ||
423
- self->size != other->size) {
475
+ size_t n = upb_array_size(self->array);
476
+
477
+ if (self->type_info.type != other->type_info.type ||
478
+ self->type_class != other->type_class ||
479
+ upb_array_size(other->array) != n) {
424
480
  return Qfalse;
425
481
  }
426
482
 
427
- {
428
- upb_fieldtype_t field_type = self->field_type;
429
- size_t elem_size = native_slot_size(field_type);
430
- size_t off = 0;
431
- for (int i = 0; i < self->size; i++, off += elem_size) {
432
- void* self_mem = ((uint8_t *)self->elements) + off;
433
- void* other_mem = ((uint8_t *)other->elements) + off;
434
- if (!native_slot_eq(field_type, self_mem, other_mem)) {
435
- return Qfalse;
436
- }
483
+ for (size_t i = 0; i < n; i++) {
484
+ upb_msgval val1 = upb_array_get(self->array, i);
485
+ upb_msgval val2 = upb_array_get(other->array, i);
486
+ if (!Msgval_IsEqual(val1, val2, self->type_info)) {
487
+ return Qfalse;
437
488
  }
438
- return Qtrue;
439
489
  }
490
+
491
+ return Qtrue;
492
+ }
493
+
494
+ /*
495
+ * call-seq:
496
+ * RepeatedField.freeze => self
497
+ *
498
+ * Freezes the repeated field. We have to intercept this so we can pin the Ruby
499
+ * object into memory so we don't forget it's frozen.
500
+ */
501
+ static VALUE RepeatedField_freeze(VALUE _self) {
502
+ RepeatedField* self = ruby_to_RepeatedField(_self);
503
+ if (!RB_OBJ_FROZEN(_self)) {
504
+ Arena_Pin(self->arena, _self);
505
+ RB_OBJ_FREEZE(_self);
506
+ }
507
+ return _self;
440
508
  }
441
509
 
442
510
  /*
@@ -447,20 +515,15 @@ VALUE RepeatedField_eq(VALUE _self, VALUE _other) {
447
515
  */
448
516
  VALUE RepeatedField_hash(VALUE _self) {
449
517
  RepeatedField* self = ruby_to_RepeatedField(_self);
450
- st_index_t h = rb_hash_start(0);
451
- VALUE hash_sym = rb_intern("hash");
452
- upb_fieldtype_t field_type = self->field_type;
453
- VALUE field_type_class = self->field_type_class;
454
- size_t elem_size = native_slot_size(field_type);
455
- size_t off = 0;
456
- for (int i = 0; i < self->size; i++, off += elem_size) {
457
- void* mem = ((uint8_t *)self->elements) + off;
458
- VALUE elem = native_slot_get(field_type, field_type_class, mem);
459
- h = rb_hash_uint(h, NUM2LONG(rb_funcall(elem, hash_sym, 0)));
518
+ uint64_t hash = 0;
519
+ size_t n = upb_array_size(self->array);
520
+
521
+ for (size_t i = 0; i < n; i++) {
522
+ upb_msgval val = upb_array_get(self->array, i);
523
+ hash = Msgval_GetHash(val, self->type_info, hash);
460
524
  }
461
- h = rb_hash_end(h);
462
525
 
463
- return INT2FIX(h);
526
+ return LL2NUM(hash);
464
527
  }
465
528
 
466
529
  /*
@@ -472,31 +535,39 @@ VALUE RepeatedField_hash(VALUE _self) {
472
535
  * be either another repeated field or a Ruby array.
473
536
  */
474
537
  VALUE RepeatedField_plus(VALUE _self, VALUE list) {
475
- VALUE dupped = RepeatedField_dup(_self);
538
+ VALUE dupped_ = RepeatedField_dup(_self);
476
539
 
477
540
  if (TYPE(list) == T_ARRAY) {
478
- for (int i = 0; i < RARRAY_LEN(list); i++) {
541
+ int i;
542
+ for (i = 0; i < RARRAY_LEN(list); i++) {
479
543
  VALUE elem = rb_ary_entry(list, i);
480
- RepeatedField_push(dupped, elem);
544
+ RepeatedField_push(dupped_, elem);
481
545
  }
482
546
  } else if (RB_TYPE_P(list, T_DATA) && RTYPEDDATA_P(list) &&
483
547
  RTYPEDDATA_TYPE(list) == &RepeatedField_type) {
484
548
  RepeatedField* self = ruby_to_RepeatedField(_self);
485
549
  RepeatedField* list_rptfield = ruby_to_RepeatedField(list);
486
- if (self->field_type != list_rptfield->field_type ||
487
- self->field_type_class != list_rptfield->field_type_class) {
550
+ RepeatedField* dupped = ruby_to_RepeatedField(dupped_);
551
+ upb_array *dupped_array = RepeatedField_GetMutable(dupped_);
552
+ upb_arena* arena = Arena_get(dupped->arena);
553
+ int size = upb_array_size(list_rptfield->array);
554
+ int i;
555
+
556
+ if (self->type_info.type != list_rptfield->type_info.type ||
557
+ self->type_class != list_rptfield->type_class) {
488
558
  rb_raise(rb_eArgError,
489
559
  "Attempt to append RepeatedField with different element type.");
490
560
  }
491
- for (int i = 0; i < list_rptfield->size; i++) {
492
- void* mem = RepeatedField_index_native(list, i);
493
- RepeatedField_push_native(dupped, mem);
561
+
562
+ for (i = 0; i < size; i++) {
563
+ upb_msgval msgval = upb_array_get(list_rptfield->array, i);
564
+ upb_array_append(dupped_array, msgval, arena);
494
565
  }
495
566
  } else {
496
567
  rb_raise(rb_eArgError, "Unknown type appending to RepeatedField");
497
568
  }
498
569
 
499
- return dupped;
570
+ return dupped_;
500
571
  }
501
572
 
502
573
  /*
@@ -506,66 +577,41 @@ VALUE RepeatedField_plus(VALUE _self, VALUE list) {
506
577
  * concats the passed in array to self. Returns a Ruby array.
507
578
  */
508
579
  VALUE RepeatedField_concat(VALUE _self, VALUE list) {
580
+ int i;
581
+
509
582
  Check_Type(list, T_ARRAY);
510
- for (int i = 0; i < RARRAY_LEN(list); i++) {
583
+ for (i = 0; i < RARRAY_LEN(list); i++) {
511
584
  RepeatedField_push(_self, rb_ary_entry(list, i));
512
585
  }
513
586
  return _self;
514
587
  }
515
588
 
516
-
517
- void validate_type_class(upb_fieldtype_t type, VALUE klass) {
518
- if (rb_ivar_get(klass, descriptor_instancevar_interned) == Qnil) {
519
- rb_raise(rb_eArgError,
520
- "Type class has no descriptor. Please pass a "
521
- "class or enum as returned by the DescriptorPool.");
522
- }
523
- if (type == UPB_TYPE_MESSAGE) {
524
- VALUE desc = rb_ivar_get(klass, descriptor_instancevar_interned);
525
- if (!RB_TYPE_P(desc, T_DATA) || !RTYPEDDATA_P(desc) ||
526
- RTYPEDDATA_TYPE(desc) != &_Descriptor_type) {
527
- rb_raise(rb_eArgError, "Descriptor has an incorrect type.");
528
- }
529
- if (rb_get_alloc_func(klass) != &Message_alloc) {
530
- rb_raise(rb_eArgError,
531
- "Message class was not returned by the DescriptorPool.");
532
- }
533
- } else if (type == UPB_TYPE_ENUM) {
534
- VALUE enumdesc = rb_ivar_get(klass, descriptor_instancevar_interned);
535
- if (!RB_TYPE_P(enumdesc, T_DATA) || !RTYPEDDATA_P(enumdesc) ||
536
- RTYPEDDATA_TYPE(enumdesc) != &_EnumDescriptor_type) {
537
- rb_raise(rb_eArgError, "Descriptor has an incorrect type.");
538
- }
539
- }
540
- }
541
-
542
- void RepeatedField_init_args(int argc, VALUE* argv,
543
- VALUE _self) {
589
+ /*
590
+ * call-seq:
591
+ * RepeatedField.new(type, type_class = nil, initial_elems = [])
592
+ *
593
+ * Creates a new repeated field. The provided type must be a Ruby symbol, and
594
+ * can take on the same values as those accepted by FieldDescriptor#type=. If
595
+ * the type is :message or :enum, type_class must be non-nil, and must be the
596
+ * Ruby class or module returned by Descriptor#msgclass or
597
+ * EnumDescriptor#enummodule, respectively. An initial list of elements may also
598
+ * be provided.
599
+ */
600
+ VALUE RepeatedField_init(int argc, VALUE* argv, VALUE _self) {
544
601
  RepeatedField* self = ruby_to_RepeatedField(_self);
602
+ upb_arena *arena;
545
603
  VALUE ary = Qnil;
604
+
605
+ self->arena = Arena_new();
606
+ arena = Arena_get(self->arena);
607
+
546
608
  if (argc < 1) {
547
609
  rb_raise(rb_eArgError, "Expected at least 1 argument.");
548
610
  }
549
- self->field_type = ruby_to_fieldtype(argv[0]);
550
611
 
551
- if (self->field_type == UPB_TYPE_MESSAGE ||
552
- self->field_type == UPB_TYPE_ENUM) {
553
- if (argc < 2) {
554
- rb_raise(rb_eArgError, "Expected at least 2 arguments for message/enum.");
555
- }
556
- self->field_type_class = argv[1];
557
- if (argc > 2) {
558
- ary = argv[2];
559
- }
560
- validate_type_class(self->field_type, self->field_type_class);
561
- } else {
562
- if (argc > 2) {
563
- rb_raise(rb_eArgError, "Too many arguments: expected 1 or 2.");
564
- }
565
- if (argc > 1) {
566
- ary = argv[1];
567
- }
568
- }
612
+ self->type_info = TypeInfo_FromClass(argc, argv, 0, &self->type_class, &ary);
613
+ self->array = upb_array_new(arena, self->type_info.type);
614
+ ObjectCache_Add(self->array, _self);
569
615
 
570
616
  if (ary != Qnil) {
571
617
  if (!RB_TYPE_P(ary, T_ARRAY)) {
@@ -575,50 +621,6 @@ void RepeatedField_init_args(int argc, VALUE* argv,
575
621
  RepeatedField_push(_self, rb_ary_entry(ary, i));
576
622
  }
577
623
  }
578
- }
579
-
580
- // Mark, free, alloc, init and class setup functions.
581
-
582
- void RepeatedField_mark(void* _self) {
583
- RepeatedField* self = (RepeatedField*)_self;
584
- upb_fieldtype_t field_type = self->field_type;
585
- int element_size = native_slot_size(field_type);
586
- rb_gc_mark(self->field_type_class);
587
- for (int i = 0; i < self->size; i++) {
588
- void* memory = (((uint8_t *)self->elements) + i * element_size);
589
- native_slot_mark(self->field_type, memory);
590
- }
591
- }
592
-
593
- void RepeatedField_free(void* _self) {
594
- RepeatedField* self = (RepeatedField*)_self;
595
- xfree(self->elements);
596
- xfree(self);
597
- }
598
-
599
- /*
600
- * call-seq:
601
- * RepeatedField.new(type, type_class = nil, initial_elems = [])
602
- *
603
- * Creates a new repeated field. The provided type must be a Ruby symbol, and
604
- * can take on the same values as those accepted by FieldDescriptor#type=. If
605
- * the type is :message or :enum, type_class must be non-nil, and must be the
606
- * Ruby class or module returned by Descriptor#msgclass or
607
- * EnumDescriptor#enummodule, respectively. An initial list of elements may also
608
- * be provided.
609
- */
610
- VALUE RepeatedField_alloc(VALUE klass) {
611
- RepeatedField* self = ALLOC(RepeatedField);
612
- self->elements = NULL;
613
- self->size = 0;
614
- self->capacity = 0;
615
- self->field_type = -1;
616
- self->field_type_class = Qnil;
617
- return TypedData_Wrap_Struct(klass, &RepeatedField_type, self);
618
- }
619
-
620
- VALUE RepeatedField_init(int argc, VALUE* argv, VALUE self) {
621
- RepeatedField_init_args(argc, argv, self);
622
624
  return Qnil;
623
625
  }
624
626
 
@@ -635,7 +637,7 @@ void RepeatedField_register(VALUE module) {
635
637
  rb_define_method(klass, "[]", RepeatedField_index, -1);
636
638
  rb_define_method(klass, "at", RepeatedField_index, -1);
637
639
  rb_define_method(klass, "[]=", RepeatedField_index_set, 2);
638
- rb_define_method(klass, "push", RepeatedField_push, 1);
640
+ rb_define_method(klass, "push", RepeatedField_push_vararg, -1);
639
641
  rb_define_method(klass, "<<", RepeatedField_push, 1);
640
642
  rb_define_private_method(klass, "pop_one", RepeatedField_pop_one, 0);
641
643
  rb_define_method(klass, "replace", RepeatedField_replace, 1);
@@ -647,6 +649,7 @@ void RepeatedField_register(VALUE module) {
647
649
  rb_define_method(klass, "clone", RepeatedField_dup, 0);
648
650
  rb_define_method(klass, "==", RepeatedField_eq, 1);
649
651
  rb_define_method(klass, "to_ary", RepeatedField_to_ary, 0);
652
+ rb_define_method(klass, "freeze", RepeatedField_freeze, 0);
650
653
  rb_define_method(klass, "hash", RepeatedField_hash, 0);
651
654
  rb_define_method(klass, "+", RepeatedField_plus, 1);
652
655
  rb_define_method(klass, "concat", RepeatedField_concat, 1);