google-protobuf 3.0.0.alpha.1.1 → 3.0.0.alpha.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


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

@@ -683,7 +683,7 @@ VALUE Map_inspect(VALUE _self) {
683
683
  first = false;
684
684
  }
685
685
  str = rb_str_append(str, rb_funcall(key, inspect_sym, 0));
686
- str = rb_str_cat2(str, " => ");
686
+ str = rb_str_cat2(str, "=>");
687
687
  str = rb_str_append(str, rb_funcall(value, inspect_sym, 0));
688
688
  }
689
689
 
@@ -70,6 +70,35 @@ VALUE Message_alloc(VALUE klass) {
70
70
  return ret;
71
71
  }
72
72
 
73
+ static VALUE which_oneof_field(MessageHeader* self, const upb_oneofdef* o) {
74
+ // If no fields in the oneof, always nil.
75
+ if (upb_oneofdef_numfields(o) == 0) {
76
+ return Qnil;
77
+ }
78
+ // Grab the first field in the oneof so we can get its layout info to find the
79
+ // oneof_case field.
80
+ upb_oneof_iter it;
81
+ upb_oneof_begin(&it, o);
82
+ assert(!upb_oneof_done(&it));
83
+ const upb_fielddef* first_field = upb_oneof_iter_field(&it);
84
+ assert(upb_fielddef_containingoneof(first_field) != NULL);
85
+
86
+ size_t case_ofs =
87
+ self->descriptor->layout->
88
+ fields[upb_fielddef_index(first_field)].case_offset;
89
+ uint32_t oneof_case = *((uint32_t*)(Message_data(self) + case_ofs));
90
+
91
+ if (oneof_case == ONEOF_CASE_NONE) {
92
+ return Qnil;
93
+ }
94
+
95
+ // oneof_case is a field index, so find that field.
96
+ const upb_fielddef* f = upb_oneofdef_itof(o, oneof_case);
97
+ assert(f != NULL);
98
+
99
+ return ID2SYM(rb_intern(upb_fielddef_name(f)));
100
+ }
101
+
73
102
  /*
74
103
  * call-seq:
75
104
  * Message.method_missing(*args)
@@ -82,6 +111,10 @@ VALUE Message_alloc(VALUE klass) {
82
111
  *
83
112
  * msg.foo = 42
84
113
  * puts msg.foo
114
+ *
115
+ * This method also provides read-only accessors for oneofs. If a oneof exists
116
+ * with name 'my_oneof', then msg.my_oneof will return a Ruby symbol equal to
117
+ * the name of the field in that oneof that is currently set, or nil if none.
85
118
  */
86
119
  VALUE Message_method_missing(int argc, VALUE* argv, VALUE _self) {
87
120
  MessageHeader* self;
@@ -104,6 +137,17 @@ VALUE Message_method_missing(int argc, VALUE* argv, VALUE _self) {
104
137
  name_len--;
105
138
  }
106
139
 
140
+ // Check for a oneof name first.
141
+ const upb_oneofdef* o = upb_msgdef_ntoo(self->descriptor->msgdef,
142
+ name, name_len);
143
+ if (o != NULL) {
144
+ if (setter) {
145
+ rb_raise(rb_eRuntimeError, "Oneof accessors are read-only.");
146
+ }
147
+ return which_oneof_field(self, o);
148
+ }
149
+
150
+ // Otherwise, check for a field with that name.
107
151
  const upb_fielddef* f = upb_msgdef_ntof(self->descriptor->msgdef,
108
152
  name, name_len);
109
153
 
@@ -77,8 +77,10 @@ void Init_protobuf_c() {
77
77
  DescriptorPool_register(protobuf);
78
78
  Descriptor_register(protobuf);
79
79
  FieldDescriptor_register(protobuf);
80
+ OneofDescriptor_register(protobuf);
80
81
  EnumDescriptor_register(protobuf);
81
82
  MessageBuilderContext_register(internal);
83
+ OneofBuilderContext_register(internal);
82
84
  EnumBuilderContext_register(internal);
83
85
  Builder_register(internal);
84
86
  RepeatedField_register(protobuf);
@@ -43,6 +43,7 @@ struct Descriptor;
43
43
  struct FieldDescriptor;
44
44
  struct EnumDescriptor;
45
45
  struct MessageLayout;
46
+ struct MessageField;
46
47
  struct MessageHeader;
47
48
  struct MessageBuilderContext;
48
49
  struct EnumBuilderContext;
@@ -51,10 +52,13 @@ struct Builder;
51
52
  typedef struct DescriptorPool DescriptorPool;
52
53
  typedef struct Descriptor Descriptor;
53
54
  typedef struct FieldDescriptor FieldDescriptor;
55
+ typedef struct OneofDescriptor OneofDescriptor;
54
56
  typedef struct EnumDescriptor EnumDescriptor;
55
57
  typedef struct MessageLayout MessageLayout;
58
+ typedef struct MessageField MessageField;
56
59
  typedef struct MessageHeader MessageHeader;
57
60
  typedef struct MessageBuilderContext MessageBuilderContext;
61
+ typedef struct OneofBuilderContext OneofBuilderContext;
58
62
  typedef struct EnumBuilderContext EnumBuilderContext;
59
63
  typedef struct Builder Builder;
60
64
 
@@ -120,6 +124,10 @@ struct FieldDescriptor {
120
124
  const upb_fielddef* fielddef;
121
125
  };
122
126
 
127
+ struct OneofDescriptor {
128
+ const upb_oneofdef* oneofdef;
129
+ };
130
+
123
131
  struct EnumDescriptor {
124
132
  const upb_enumdef* enumdef;
125
133
  VALUE module; // begins as nil
@@ -130,6 +138,11 @@ struct MessageBuilderContext {
130
138
  VALUE builder;
131
139
  };
132
140
 
141
+ struct OneofBuilderContext {
142
+ VALUE descriptor;
143
+ VALUE builder;
144
+ };
145
+
133
146
  struct EnumBuilderContext {
134
147
  VALUE enumdesc;
135
148
  };
@@ -144,6 +157,7 @@ extern VALUE cDescriptor;
144
157
  extern VALUE cFieldDescriptor;
145
158
  extern VALUE cEnumDescriptor;
146
159
  extern VALUE cMessageBuilderContext;
160
+ extern VALUE cOneofBuilderContext;
147
161
  extern VALUE cEnumBuilderContext;
148
162
  extern VALUE cBuilder;
149
163
 
@@ -175,6 +189,9 @@ VALUE Descriptor_name_set(VALUE _self, VALUE str);
175
189
  VALUE Descriptor_each(VALUE _self);
176
190
  VALUE Descriptor_lookup(VALUE _self, VALUE name);
177
191
  VALUE Descriptor_add_field(VALUE _self, VALUE obj);
192
+ VALUE Descriptor_add_oneof(VALUE _self, VALUE obj);
193
+ VALUE Descriptor_each_oneof(VALUE _self);
194
+ VALUE Descriptor_lookup_oneof(VALUE _self, VALUE name);
178
195
  VALUE Descriptor_msgclass(VALUE _self);
179
196
  extern const rb_data_type_t _Descriptor_type;
180
197
 
@@ -199,6 +216,16 @@ VALUE FieldDescriptor_set(VALUE _self, VALUE msg_rb, VALUE value);
199
216
  upb_fieldtype_t ruby_to_fieldtype(VALUE type);
200
217
  VALUE fieldtype_to_ruby(upb_fieldtype_t type);
201
218
 
219
+ void OneofDescriptor_mark(void* _self);
220
+ void OneofDescriptor_free(void* _self);
221
+ VALUE OneofDescriptor_alloc(VALUE klass);
222
+ void OneofDescriptor_register(VALUE module);
223
+ OneofDescriptor* ruby_to_OneofDescriptor(VALUE value);
224
+ VALUE OneofDescriptor_name(VALUE _self);
225
+ VALUE OneofDescriptor_name_set(VALUE _self, VALUE value);
226
+ VALUE OneofDescriptor_add_field(VALUE _self, VALUE field);
227
+ VALUE OneofDescriptor_each(VALUE _self, VALUE field);
228
+
202
229
  void EnumDescriptor_mark(void* _self);
203
230
  void EnumDescriptor_free(void* _self);
204
231
  VALUE EnumDescriptor_alloc(VALUE klass);
@@ -225,6 +252,17 @@ VALUE MessageBuilderContext_optional(int argc, VALUE* argv, VALUE _self);
225
252
  VALUE MessageBuilderContext_required(int argc, VALUE* argv, VALUE _self);
226
253
  VALUE MessageBuilderContext_repeated(int argc, VALUE* argv, VALUE _self);
227
254
  VALUE MessageBuilderContext_map(int argc, VALUE* argv, VALUE _self);
255
+ VALUE MessageBuilderContext_oneof(VALUE _self, VALUE name);
256
+
257
+ void OneofBuilderContext_mark(void* _self);
258
+ void OneofBuilderContext_free(void* _self);
259
+ VALUE OneofBuilderContext_alloc(VALUE klass);
260
+ void OneofBuilderContext_register(VALUE module);
261
+ OneofBuilderContext* ruby_to_OneofBuilderContext(VALUE value);
262
+ VALUE OneofBuilderContext_initialize(VALUE _self,
263
+ VALUE descriptor,
264
+ VALUE builder);
265
+ VALUE OneofBuilderContext_optional(int argc, VALUE* argv, VALUE _self);
228
266
 
229
267
  void EnumBuilderContext_mark(void* _self);
230
268
  void EnumBuilderContext_free(void* _self);
@@ -247,13 +285,22 @@ VALUE Builder_finalize_to_pool(VALUE _self, VALUE pool_rb);
247
285
  // Native slot storage abstraction.
248
286
  // -----------------------------------------------------------------------------
249
287
 
250
- #define NATIVE_SLOT_MAX_SIZE sizeof(void*)
288
+ #define NATIVE_SLOT_MAX_SIZE sizeof(uint64_t)
251
289
 
252
290
  size_t native_slot_size(upb_fieldtype_t type);
253
291
  void native_slot_set(upb_fieldtype_t type,
254
292
  VALUE type_class,
255
293
  void* memory,
256
294
  VALUE value);
295
+ // Atomically (with respect to Ruby VM calls) either update the value and set a
296
+ // oneof case, or do neither. If |case_memory| is null, then no case value is
297
+ // set.
298
+ void native_slot_set_value_and_case(upb_fieldtype_t type,
299
+ VALUE type_class,
300
+ void* memory,
301
+ VALUE value,
302
+ uint32_t* case_memory,
303
+ uint32_t case_number);
257
304
  VALUE native_slot_get(upb_fieldtype_t type,
258
305
  VALUE type_class,
259
306
  const void* memory);
@@ -275,6 +322,11 @@ VALUE field_type_class(const upb_fielddef* field);
275
322
  #define MAP_KEY_FIELD 1
276
323
  #define MAP_VALUE_FIELD 2
277
324
 
325
+ // Oneof case slot value to indicate that no oneof case is set. The value `0` is
326
+ // safe because field numbers are used as case identifiers, and no field can
327
+ // have a number of 0.
328
+ #define ONEOF_CASE_NONE 0
329
+
278
330
  // These operate on a map field (i.e., a repeated field of submessages whose
279
331
  // submessage type is a map-entry msgdef).
280
332
  bool is_map_field(const upb_fielddef* field);
@@ -384,9 +436,16 @@ VALUE Map_iter_value(Map_iter* iter);
384
436
  // Message layout / storage.
385
437
  // -----------------------------------------------------------------------------
386
438
 
439
+ #define MESSAGE_FIELD_NO_CASE ((size_t)-1)
440
+
441
+ struct MessageField {
442
+ size_t offset;
443
+ size_t case_offset; // for oneofs, a uint32. Else, MESSAGE_FIELD_NO_CASE.
444
+ };
445
+
387
446
  struct MessageLayout {
388
447
  const upb_msgdef* msgdef;
389
- size_t* offsets;
448
+ MessageField* fields;
390
449
  size_t size;
391
450
  };
392
451
 
@@ -316,6 +316,29 @@ VALUE RepeatedField_deep_copy(VALUE _self) {
316
316
  return new_rptfield;
317
317
  }
318
318
 
319
+ /*
320
+ * call-seq:
321
+ * RepeatedField.to_ary => array
322
+ *
323
+ * Used when converted implicitly into array, e.g. compared to an Array.
324
+ * Also called as a fallback of Object#to_a
325
+ */
326
+ VALUE RepeatedField_to_ary(VALUE _self) {
327
+ RepeatedField* self = ruby_to_RepeatedField(_self);
328
+ upb_fieldtype_t field_type = self->field_type;
329
+
330
+ size_t elem_size = native_slot_size(field_type);
331
+ size_t off = 0;
332
+ VALUE ary = rb_ary_new2(self->size);
333
+ for (int i = 0; i < self->size; i++, off += elem_size) {
334
+ void* mem = ((uint8_t *)self->elements) + off;
335
+ VALUE elem = native_slot_get(field_type, self->field_type_class, mem);
336
+
337
+ rb_ary_push(ary, elem);
338
+ }
339
+ return ary;
340
+ }
341
+
319
342
  /*
320
343
  * call-seq:
321
344
  * RepeatedField.==(other) => boolean
@@ -335,15 +358,9 @@ VALUE RepeatedField_eq(VALUE _self, VALUE _other) {
335
358
  }
336
359
  RepeatedField* self = ruby_to_RepeatedField(_self);
337
360
 
338
- // Inefficient but workable: to support comparison to a generic array, we
339
- // build a temporary RepeatedField of our type.
340
361
  if (TYPE(_other) == T_ARRAY) {
341
- VALUE new_rptfield = RepeatedField_new_this_type(_self);
342
- for (int i = 0; i < RARRAY_LEN(_other); i++) {
343
- VALUE elem = rb_ary_entry(_other, i);
344
- RepeatedField_push(new_rptfield, elem);
345
- }
346
- _other = new_rptfield;
362
+ VALUE self_ary = RepeatedField_to_ary(_self);
363
+ return rb_equal(self_ary, _other);
347
364
  }
348
365
 
349
366
  RepeatedField* other = ruby_to_RepeatedField(_other);
@@ -401,29 +418,8 @@ VALUE RepeatedField_hash(VALUE _self) {
401
418
  * representation computed by its own #inspect method.
402
419
  */
403
420
  VALUE RepeatedField_inspect(VALUE _self) {
404
- RepeatedField* self = ruby_to_RepeatedField(_self);
405
-
406
- VALUE str = rb_str_new2("[");
407
-
408
- bool first = true;
409
-
410
- upb_fieldtype_t field_type = self->field_type;
411
- VALUE field_type_class = self->field_type_class;
412
- size_t elem_size = native_slot_size(field_type);
413
- size_t off = 0;
414
- for (int i = 0; i < self->size; i++, off += elem_size) {
415
- void* mem = ((uint8_t *)self->elements) + off;
416
- VALUE elem = native_slot_get(field_type, field_type_class, mem);
417
- if (!first) {
418
- str = rb_str_cat2(str, ", ");
419
- } else {
420
- first = false;
421
- }
422
- str = rb_str_append(str, rb_funcall(elem, rb_intern("inspect"), 0));
423
- }
424
-
425
- str = rb_str_cat2(str, "]");
426
- return str;
421
+ VALUE self_ary = RepeatedField_to_ary(_self);
422
+ return rb_funcall(self_ary, rb_intern("inspect"), 0);
427
423
  }
428
424
 
429
425
  /*
@@ -594,6 +590,7 @@ void RepeatedField_register(VALUE module) {
594
590
  // Also define #clone so that we don't inherit Object#clone.
595
591
  rb_define_method(klass, "clone", RepeatedField_dup, 0);
596
592
  rb_define_method(klass, "==", RepeatedField_eq, 1);
593
+ rb_define_method(klass, "to_ary", RepeatedField_to_ary, 0);
597
594
  rb_define_method(klass, "hash", RepeatedField_hash, 0);
598
595
  rb_define_method(klass, "inspect", RepeatedField_inspect, 0);
599
596
  rb_define_method(klass, "+", RepeatedField_plus, 1);
@@ -109,6 +109,17 @@ void native_slot_validate_string_encoding(upb_fieldtype_t type, VALUE value) {
109
109
 
110
110
  void native_slot_set(upb_fieldtype_t type, VALUE type_class,
111
111
  void* memory, VALUE value) {
112
+ native_slot_set_value_and_case(type, type_class, memory, value, NULL, 0);
113
+ }
114
+
115
+ void native_slot_set_value_and_case(upb_fieldtype_t type, VALUE type_class,
116
+ void* memory, VALUE value,
117
+ uint32_t* case_memory,
118
+ uint32_t case_number) {
119
+ // Note that in order to atomically change the value in memory and the case
120
+ // value (w.r.t. Ruby VM calls), we must set the value at |memory| only after
121
+ // all Ruby VM calls are complete. The case is then set at the bottom of this
122
+ // function.
112
123
  switch (type) {
113
124
  case UPB_TYPE_FLOAT:
114
125
  if (!is_ruby_num(value)) {
@@ -198,6 +209,10 @@ void native_slot_set(upb_fieldtype_t type, VALUE type_class,
198
209
  default:
199
210
  break;
200
211
  }
212
+
213
+ if (case_memory != NULL) {
214
+ *case_memory = case_number;
215
+ }
201
216
  }
202
217
 
203
218
  VALUE native_slot_get(upb_fieldtype_t type,
@@ -366,24 +381,94 @@ const upb_fielddef* map_entry_value(const upb_msgdef* msgdef) {
366
381
  // Memory layout management.
367
382
  // -----------------------------------------------------------------------------
368
383
 
384
+ static size_t align_up_to(size_t offset, size_t granularity) {
385
+ // Granularity must be a power of two.
386
+ return (offset + granularity - 1) & ~(granularity - 1);
387
+ }
388
+
369
389
  MessageLayout* create_layout(const upb_msgdef* msgdef) {
370
390
  MessageLayout* layout = ALLOC(MessageLayout);
371
391
  int nfields = upb_msgdef_numfields(msgdef);
372
- layout->offsets = ALLOC_N(size_t, nfields);
392
+ layout->fields = ALLOC_N(MessageField, nfields);
373
393
 
374
- upb_msg_iter it;
394
+ upb_msg_field_iter it;
375
395
  size_t off = 0;
376
- for (upb_msg_begin(&it, msgdef); !upb_msg_done(&it); upb_msg_next(&it)) {
396
+ for (upb_msg_field_begin(&it, msgdef);
397
+ !upb_msg_field_done(&it);
398
+ upb_msg_field_next(&it)) {
377
399
  const upb_fielddef* field = upb_msg_iter_field(&it);
400
+
401
+ if (upb_fielddef_containingoneof(field)) {
402
+ // Oneofs are handled separately below.
403
+ continue;
404
+ }
405
+
406
+ // Allocate |field_size| bytes for this field in the layout.
378
407
  size_t field_size = 0;
379
408
  if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
380
409
  field_size = sizeof(VALUE);
381
410
  } else {
382
411
  field_size = native_slot_size(upb_fielddef_type(field));
383
412
  }
384
- // align current offset
413
+ // Align current offset up to |size| granularity.
414
+ off = align_up_to(off, field_size);
415
+ layout->fields[upb_fielddef_index(field)].offset = off;
416
+ layout->fields[upb_fielddef_index(field)].case_offset = MESSAGE_FIELD_NO_CASE;
417
+ off += field_size;
418
+ }
419
+
420
+ // Handle oneofs now -- we iterate over oneofs specifically and allocate only
421
+ // one slot per oneof.
422
+ //
423
+ // We assign all value slots first, then pack the 'case' fields at the end,
424
+ // since in the common case (modern 64-bit platform) these are 8 bytes and 4
425
+ // bytes respectively and we want to avoid alignment overhead.
426
+ //
427
+ // Note that we reserve 4 bytes (a uint32) per 'case' slot because the value
428
+ // space for oneof cases is conceptually as wide as field tag numbers. In
429
+ // practice, it's unlikely that a oneof would have more than e.g. 256 or 64K
430
+ // members (8 or 16 bits respectively), so conceivably we could assign
431
+ // consecutive case numbers and then pick a smaller oneof case slot size, but
432
+ // the complexity to implement this indirection is probably not worthwhile.
433
+ upb_msg_oneof_iter oit;
434
+ for (upb_msg_oneof_begin(&oit, msgdef);
435
+ !upb_msg_oneof_done(&oit);
436
+ upb_msg_oneof_next(&oit)) {
437
+ const upb_oneofdef* oneof = upb_msg_iter_oneof(&oit);
438
+
439
+ // Always allocate NATIVE_SLOT_MAX_SIZE bytes, but share the slot between
440
+ // all fields.
441
+ size_t field_size = NATIVE_SLOT_MAX_SIZE;
442
+ // Align the offset.
443
+ off = align_up_to(off, field_size);
444
+ // Assign all fields in the oneof this same offset.
445
+ upb_oneof_iter fit;
446
+ for (upb_oneof_begin(&fit, oneof);
447
+ !upb_oneof_done(&fit);
448
+ upb_oneof_next(&fit)) {
449
+ const upb_fielddef* field = upb_oneof_iter_field(&fit);
450
+ layout->fields[upb_fielddef_index(field)].offset = off;
451
+ }
452
+ off += field_size;
453
+ }
454
+
455
+ // Now the case fields.
456
+ for (upb_msg_oneof_begin(&oit, msgdef);
457
+ !upb_msg_oneof_done(&oit);
458
+ upb_msg_oneof_next(&oit)) {
459
+ const upb_oneofdef* oneof = upb_msg_iter_oneof(&oit);
460
+
461
+ size_t field_size = sizeof(uint32_t);
462
+ // Align the offset.
385
463
  off = (off + field_size - 1) & ~(field_size - 1);
386
- layout->offsets[upb_fielddef_index(field)] = off;
464
+ // Assign all fields in the oneof this same offset.
465
+ upb_oneof_iter fit;
466
+ for (upb_oneof_begin(&fit, oneof);
467
+ !upb_oneof_done(&fit);
468
+ upb_oneof_next(&fit)) {
469
+ const upb_fielddef* field = upb_oneof_iter_field(&fit);
470
+ layout->fields[upb_fielddef_index(field)].case_offset = off;
471
+ }
387
472
  off += field_size;
388
473
  }
389
474
 
@@ -396,7 +481,7 @@ MessageLayout* create_layout(const upb_msgdef* msgdef) {
396
481
  }
397
482
 
398
483
  void free_layout(MessageLayout* layout) {
399
- xfree(layout->offsets);
484
+ xfree(layout->fields);
400
485
  upb_msgdef_unref(layout->msgdef, &layout->msgdef);
401
486
  xfree(layout);
402
487
  }
@@ -415,12 +500,35 @@ VALUE field_type_class(const upb_fielddef* field) {
415
500
  return type_class;
416
501
  }
417
502
 
503
+ static void* slot_memory(MessageLayout* layout,
504
+ const void* storage,
505
+ const upb_fielddef* field) {
506
+ return ((uint8_t *)storage) +
507
+ layout->fields[upb_fielddef_index(field)].offset;
508
+ }
509
+
510
+ static uint32_t* slot_oneof_case(MessageLayout* layout,
511
+ const void* storage,
512
+ const upb_fielddef* field) {
513
+ return (uint32_t *)(((uint8_t *)storage) +
514
+ layout->fields[upb_fielddef_index(field)].case_offset);
515
+ }
516
+
517
+
418
518
  VALUE layout_get(MessageLayout* layout,
419
519
  const void* storage,
420
520
  const upb_fielddef* field) {
421
- void* memory = ((uint8_t *)storage) +
422
- layout->offsets[upb_fielddef_index(field)];
423
- if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
521
+ void* memory = slot_memory(layout, storage, field);
522
+ uint32_t* oneof_case = slot_oneof_case(layout, storage, field);
523
+
524
+ if (upb_fielddef_containingoneof(field)) {
525
+ if (*oneof_case != upb_fielddef_number(field)) {
526
+ return Qnil;
527
+ }
528
+ return native_slot_get(upb_fielddef_type(field),
529
+ field_type_class(field),
530
+ memory);
531
+ } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
424
532
  return *((VALUE *)memory);
425
533
  } else {
426
534
  return native_slot_get(upb_fielddef_type(field),
@@ -484,9 +592,33 @@ void layout_set(MessageLayout* layout,
484
592
  void* storage,
485
593
  const upb_fielddef* field,
486
594
  VALUE val) {
487
- void* memory = ((uint8_t *)storage) +
488
- layout->offsets[upb_fielddef_index(field)];
489
- if (is_map_field(field)) {
595
+ void* memory = slot_memory(layout, storage, field);
596
+ uint32_t* oneof_case = slot_oneof_case(layout, storage, field);
597
+
598
+ if (upb_fielddef_containingoneof(field)) {
599
+ if (val == Qnil) {
600
+ // Assigning nil to a oneof field clears the oneof completely.
601
+ *oneof_case = ONEOF_CASE_NONE;
602
+ memset(memory, 0, NATIVE_SLOT_MAX_SIZE);
603
+ } else {
604
+ // The transition between field types for a single oneof (union) slot is
605
+ // somewhat complex because we need to ensure that a GC triggered at any
606
+ // point by a call into the Ruby VM sees a valid state for this field and
607
+ // does not either go off into the weeds (following what it thinks is a
608
+ // VALUE but is actually a different field type) or miss an object (seeing
609
+ // what it thinks is a primitive field but is actually a VALUE for the new
610
+ // field type).
611
+ //
612
+ // In order for the transition to be safe, the oneof case slot must be in
613
+ // sync with the value slot whenever the Ruby VM has been called. Thus, we
614
+ // use native_slot_set_value_and_case(), which ensures that both the value
615
+ // and case number are altered atomically (w.r.t. the Ruby VM).
616
+ native_slot_set_value_and_case(
617
+ upb_fielddef_type(field), field_type_class(field),
618
+ memory, val,
619
+ oneof_case, upb_fielddef_number(field));
620
+ }
621
+ } else if (is_map_field(field)) {
490
622
  check_map_field_type(val, field);
491
623
  DEREF(memory, VALUE) = val;
492
624
  } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
@@ -500,15 +632,18 @@ void layout_set(MessageLayout* layout,
500
632
 
501
633
  void layout_init(MessageLayout* layout,
502
634
  void* storage) {
503
- upb_msg_iter it;
504
- for (upb_msg_begin(&it, layout->msgdef);
505
- !upb_msg_done(&it);
506
- upb_msg_next(&it)) {
635
+ upb_msg_field_iter it;
636
+ for (upb_msg_field_begin(&it, layout->msgdef);
637
+ !upb_msg_field_done(&it);
638
+ upb_msg_field_next(&it)) {
507
639
  const upb_fielddef* field = upb_msg_iter_field(&it);
508
- void* memory = ((uint8_t *)storage) +
509
- layout->offsets[upb_fielddef_index(field)];
640
+ void* memory = slot_memory(layout, storage, field);
641
+ uint32_t* oneof_case = slot_oneof_case(layout, storage, field);
510
642
 
511
- if (is_map_field(field)) {
643
+ if (upb_fielddef_containingoneof(field)) {
644
+ memset(memory, 0, NATIVE_SLOT_MAX_SIZE);
645
+ *oneof_case = ONEOF_CASE_NONE;
646
+ } else if (is_map_field(field)) {
512
647
  VALUE map = Qnil;
513
648
 
514
649
  const upb_fielddef* key_field = map_field_key(field);
@@ -555,15 +690,19 @@ void layout_init(MessageLayout* layout,
555
690
  }
556
691
 
557
692
  void layout_mark(MessageLayout* layout, void* storage) {
558
- upb_msg_iter it;
559
- for (upb_msg_begin(&it, layout->msgdef);
560
- !upb_msg_done(&it);
561
- upb_msg_next(&it)) {
693
+ upb_msg_field_iter it;
694
+ for (upb_msg_field_begin(&it, layout->msgdef);
695
+ !upb_msg_field_done(&it);
696
+ upb_msg_field_next(&it)) {
562
697
  const upb_fielddef* field = upb_msg_iter_field(&it);
563
- void* memory = ((uint8_t *)storage) +
564
- layout->offsets[upb_fielddef_index(field)];
698
+ void* memory = slot_memory(layout, storage, field);
699
+ uint32_t* oneof_case = slot_oneof_case(layout, storage, field);
565
700
 
566
- if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
701
+ if (upb_fielddef_containingoneof(field)) {
702
+ if (*oneof_case == upb_fielddef_number(field)) {
703
+ native_slot_mark(upb_fielddef_type(field), memory);
704
+ }
705
+ } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
567
706
  rb_gc_mark(DEREF(memory, VALUE));
568
707
  } else {
569
708
  native_slot_mark(upb_fielddef_type(field), memory);
@@ -572,17 +711,23 @@ void layout_mark(MessageLayout* layout, void* storage) {
572
711
  }
573
712
 
574
713
  void layout_dup(MessageLayout* layout, void* to, void* from) {
575
- upb_msg_iter it;
576
- for (upb_msg_begin(&it, layout->msgdef);
577
- !upb_msg_done(&it);
578
- upb_msg_next(&it)) {
714
+ upb_msg_field_iter it;
715
+ for (upb_msg_field_begin(&it, layout->msgdef);
716
+ !upb_msg_field_done(&it);
717
+ upb_msg_field_next(&it)) {
579
718
  const upb_fielddef* field = upb_msg_iter_field(&it);
580
- void* to_memory = ((uint8_t *)to) +
581
- layout->offsets[upb_fielddef_index(field)];
582
- void* from_memory = ((uint8_t *)from) +
583
- layout->offsets[upb_fielddef_index(field)];
584
719
 
585
- if (is_map_field(field)) {
720
+ void* to_memory = slot_memory(layout, to, field);
721
+ uint32_t* to_oneof_case = slot_oneof_case(layout, to, field);
722
+ void* from_memory = slot_memory(layout, from, field);
723
+ uint32_t* from_oneof_case = slot_oneof_case(layout, from, field);
724
+
725
+ if (upb_fielddef_containingoneof(field)) {
726
+ if (*from_oneof_case == upb_fielddef_number(field)) {
727
+ *to_oneof_case = *from_oneof_case;
728
+ native_slot_dup(upb_fielddef_type(field), to_memory, from_memory);
729
+ }
730
+ } else if (is_map_field(field)) {
586
731
  DEREF(to_memory, VALUE) = Map_dup(DEREF(from_memory, VALUE));
587
732
  } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
588
733
  DEREF(to_memory, VALUE) = RepeatedField_dup(DEREF(from_memory, VALUE));
@@ -593,17 +738,23 @@ void layout_dup(MessageLayout* layout, void* to, void* from) {
593
738
  }
594
739
 
595
740
  void layout_deep_copy(MessageLayout* layout, void* to, void* from) {
596
- upb_msg_iter it;
597
- for (upb_msg_begin(&it, layout->msgdef);
598
- !upb_msg_done(&it);
599
- upb_msg_next(&it)) {
741
+ upb_msg_field_iter it;
742
+ for (upb_msg_field_begin(&it, layout->msgdef);
743
+ !upb_msg_field_done(&it);
744
+ upb_msg_field_next(&it)) {
600
745
  const upb_fielddef* field = upb_msg_iter_field(&it);
601
- void* to_memory = ((uint8_t *)to) +
602
- layout->offsets[upb_fielddef_index(field)];
603
- void* from_memory = ((uint8_t *)from) +
604
- layout->offsets[upb_fielddef_index(field)];
605
746
 
606
- if (is_map_field(field)) {
747
+ void* to_memory = slot_memory(layout, to, field);
748
+ uint32_t* to_oneof_case = slot_oneof_case(layout, to, field);
749
+ void* from_memory = slot_memory(layout, from, field);
750
+ uint32_t* from_oneof_case = slot_oneof_case(layout, from, field);
751
+
752
+ if (upb_fielddef_containingoneof(field)) {
753
+ if (*from_oneof_case == upb_fielddef_number(field)) {
754
+ *to_oneof_case = *from_oneof_case;
755
+ native_slot_deep_copy(upb_fielddef_type(field), to_memory, from_memory);
756
+ }
757
+ } else if (is_map_field(field)) {
607
758
  DEREF(to_memory, VALUE) =
608
759
  Map_deep_copy(DEREF(from_memory, VALUE));
609
760
  } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
@@ -616,22 +767,35 @@ void layout_deep_copy(MessageLayout* layout, void* to, void* from) {
616
767
  }
617
768
 
618
769
  VALUE layout_eq(MessageLayout* layout, void* msg1, void* msg2) {
619
- upb_msg_iter it;
620
- for (upb_msg_begin(&it, layout->msgdef);
621
- !upb_msg_done(&it);
622
- upb_msg_next(&it)) {
770
+ upb_msg_field_iter it;
771
+ for (upb_msg_field_begin(&it, layout->msgdef);
772
+ !upb_msg_field_done(&it);
773
+ upb_msg_field_next(&it)) {
623
774
  const upb_fielddef* field = upb_msg_iter_field(&it);
624
- void* msg1_memory = ((uint8_t *)msg1) +
625
- layout->offsets[upb_fielddef_index(field)];
626
- void* msg2_memory = ((uint8_t *)msg2) +
627
- layout->offsets[upb_fielddef_index(field)];
628
-
629
- if (is_map_field(field)) {
630
- return Map_eq(DEREF(msg1_memory, VALUE),
631
- DEREF(msg2_memory, VALUE));
775
+
776
+ void* msg1_memory = slot_memory(layout, msg1, field);
777
+ uint32_t* msg1_oneof_case = slot_oneof_case(layout, msg1, field);
778
+ void* msg2_memory = slot_memory(layout, msg2, field);
779
+ uint32_t* msg2_oneof_case = slot_oneof_case(layout, msg2, field);
780
+
781
+ if (upb_fielddef_containingoneof(field)) {
782
+ if (*msg1_oneof_case != *msg2_oneof_case ||
783
+ (*msg1_oneof_case == upb_fielddef_number(field) &&
784
+ !native_slot_eq(upb_fielddef_type(field),
785
+ msg1_memory,
786
+ msg2_memory))) {
787
+ return Qfalse;
788
+ }
789
+ } else if (is_map_field(field)) {
790
+ if (!Map_eq(DEREF(msg1_memory, VALUE),
791
+ DEREF(msg2_memory, VALUE))) {
792
+ return Qfalse;
793
+ }
632
794
  } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
633
- return RepeatedField_eq(DEREF(msg1_memory, VALUE),
634
- DEREF(msg2_memory, VALUE));
795
+ if (!RepeatedField_eq(DEREF(msg1_memory, VALUE),
796
+ DEREF(msg2_memory, VALUE))) {
797
+ return Qfalse;
798
+ }
635
799
  } else {
636
800
  if (!native_slot_eq(upb_fielddef_type(field),
637
801
  msg1_memory, msg2_memory)) {
@@ -643,12 +807,12 @@ VALUE layout_eq(MessageLayout* layout, void* msg1, void* msg2) {
643
807
  }
644
808
 
645
809
  VALUE layout_hash(MessageLayout* layout, void* storage) {
646
- upb_msg_iter it;
810
+ upb_msg_field_iter it;
647
811
  st_index_t h = rb_hash_start(0);
648
812
  VALUE hash_sym = rb_intern("hash");
649
- for (upb_msg_begin(&it, layout->msgdef);
650
- !upb_msg_done(&it);
651
- upb_msg_next(&it)) {
813
+ for (upb_msg_field_begin(&it, layout->msgdef);
814
+ !upb_msg_field_done(&it);
815
+ upb_msg_field_next(&it)) {
652
816
  const upb_fielddef* field = upb_msg_iter_field(&it);
653
817
  VALUE field_val = layout_get(layout, storage, field);
654
818
  h = rb_hash_uint(h, NUM2LONG(rb_funcall(field_val, hash_sym, 0)));
@@ -661,11 +825,11 @@ VALUE layout_hash(MessageLayout* layout, void* storage) {
661
825
  VALUE layout_inspect(MessageLayout* layout, void* storage) {
662
826
  VALUE str = rb_str_new2("");
663
827
 
664
- upb_msg_iter it;
828
+ upb_msg_field_iter it;
665
829
  bool first = true;
666
- for (upb_msg_begin(&it, layout->msgdef);
667
- !upb_msg_done(&it);
668
- upb_msg_next(&it)) {
830
+ for (upb_msg_field_begin(&it, layout->msgdef);
831
+ !upb_msg_field_done(&it);
832
+ upb_msg_field_next(&it)) {
669
833
  const upb_fielddef* field = upb_msg_iter_field(&it);
670
834
  VALUE field_val = layout_get(layout, storage, field);
671
835