google-protobuf 3.8.0 → 3.19.3

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