google-protobuf 3.0.0.alpha.1.1 → 3.0.0.alpha.2.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.

@@ -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