google-protobuf 3.7.0 → 3.11.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.

@@ -65,9 +65,10 @@ static bool is_ruby_num(VALUE value) {
65
65
  TYPE(value) == T_BIGNUM);
66
66
  }
67
67
 
68
- void native_slot_check_int_range_precision(upb_fieldtype_t type, VALUE val) {
68
+ void native_slot_check_int_range_precision(const char* name, upb_fieldtype_t type, VALUE val) {
69
69
  if (!is_ruby_num(val)) {
70
- rb_raise(cTypeError, "Expected number type for integral field.");
70
+ rb_raise(cTypeError, "Expected number type for integral field '%s' (given %s).",
71
+ name, rb_class2name(CLASS_OF(val)));
71
72
  }
72
73
 
73
74
  // NUM2{INT,UINT,LL,ULL} macros do the appropriate range checks on upper
@@ -77,13 +78,15 @@ void native_slot_check_int_range_precision(upb_fieldtype_t type, VALUE val) {
77
78
  double dbl_val = NUM2DBL(val);
78
79
  if (floor(dbl_val) != dbl_val) {
79
80
  rb_raise(rb_eRangeError,
80
- "Non-integral floating point value assigned to integer field.");
81
+ "Non-integral floating point value assigned to integer field '%s' (given %s).",
82
+ name, rb_class2name(CLASS_OF(val)));
81
83
  }
82
84
  }
83
85
  if (type == UPB_TYPE_UINT32 || type == UPB_TYPE_UINT64) {
84
86
  if (NUM2DBL(val) < 0) {
85
87
  rb_raise(rb_eRangeError,
86
- "Assigning negative value to unsigned integer field.");
88
+ "Assigning negative value to unsigned integer field '%s' (given %s).",
89
+ name, rb_class2name(CLASS_OF(val)));
87
90
  }
88
91
  }
89
92
  }
@@ -93,27 +96,31 @@ VALUE native_slot_encode_and_freeze_string(upb_fieldtype_t type, VALUE value) {
93
96
  kRubyStringUtf8Encoding : kRubyString8bitEncoding;
94
97
  VALUE desired_encoding_value = rb_enc_from_encoding(desired_encoding);
95
98
 
96
- // Note: this will not duplicate underlying string data unless necessary.
97
- value = rb_str_encode(value, desired_encoding_value, 0, Qnil);
99
+ if (rb_obj_encoding(value) != desired_encoding_value || !OBJ_FROZEN(value)) {
100
+ // Note: this will not duplicate underlying string data unless necessary.
101
+ value = rb_str_encode(value, desired_encoding_value, 0, Qnil);
98
102
 
99
- if (type == UPB_TYPE_STRING &&
100
- rb_enc_str_coderange(value) == ENC_CODERANGE_BROKEN) {
101
- rb_raise(rb_eEncodingError, "String is invalid UTF-8");
102
- }
103
+ if (type == UPB_TYPE_STRING &&
104
+ rb_enc_str_coderange(value) == ENC_CODERANGE_BROKEN) {
105
+ rb_raise(rb_eEncodingError, "String is invalid UTF-8");
106
+ }
103
107
 
104
- // Ensure the data remains valid. Since we called #encode a moment ago,
105
- // this does not freeze the string the user assigned.
106
- rb_obj_freeze(value);
108
+ // Ensure the data remains valid. Since we called #encode a moment ago,
109
+ // this does not freeze the string the user assigned.
110
+ rb_obj_freeze(value);
111
+ }
107
112
 
108
113
  return value;
109
114
  }
110
115
 
111
- void native_slot_set(upb_fieldtype_t type, VALUE type_class,
116
+ void native_slot_set(const char* name,
117
+ upb_fieldtype_t type, VALUE type_class,
112
118
  void* memory, VALUE value) {
113
- native_slot_set_value_and_case(type, type_class, memory, value, NULL, 0);
119
+ native_slot_set_value_and_case(name, type, type_class, memory, value, NULL, 0);
114
120
  }
115
121
 
116
- void native_slot_set_value_and_case(upb_fieldtype_t type, VALUE type_class,
122
+ void native_slot_set_value_and_case(const char* name,
123
+ upb_fieldtype_t type, VALUE type_class,
117
124
  void* memory, VALUE value,
118
125
  uint32_t* case_memory,
119
126
  uint32_t case_number) {
@@ -124,13 +131,15 @@ void native_slot_set_value_and_case(upb_fieldtype_t type, VALUE type_class,
124
131
  switch (type) {
125
132
  case UPB_TYPE_FLOAT:
126
133
  if (!is_ruby_num(value)) {
127
- rb_raise(cTypeError, "Expected number type for float field.");
134
+ rb_raise(cTypeError, "Expected number type for float field '%s' (given %s).",
135
+ name, rb_class2name(CLASS_OF(value)));
128
136
  }
129
137
  DEREF(memory, float) = NUM2DBL(value);
130
138
  break;
131
139
  case UPB_TYPE_DOUBLE:
132
140
  if (!is_ruby_num(value)) {
133
- rb_raise(cTypeError, "Expected number type for double field.");
141
+ rb_raise(cTypeError, "Expected number type for double field '%s' (given %s).",
142
+ name, rb_class2name(CLASS_OF(value)));
134
143
  }
135
144
  DEREF(memory, double) = NUM2DBL(value);
136
145
  break;
@@ -141,7 +150,8 @@ void native_slot_set_value_and_case(upb_fieldtype_t type, VALUE type_class,
141
150
  } else if (value == Qfalse) {
142
151
  val = 0;
143
152
  } else {
144
- rb_raise(cTypeError, "Invalid argument for boolean field.");
153
+ rb_raise(cTypeError, "Invalid argument for boolean field '%s' (given %s).",
154
+ name, rb_class2name(CLASS_OF(value)));
145
155
  }
146
156
  DEREF(memory, int8_t) = val;
147
157
  break;
@@ -150,7 +160,8 @@ void native_slot_set_value_and_case(upb_fieldtype_t type, VALUE type_class,
150
160
  if (CLASS_OF(value) == rb_cSymbol) {
151
161
  value = rb_funcall(value, rb_intern("to_s"), 0);
152
162
  } else if (CLASS_OF(value) != rb_cString) {
153
- rb_raise(cTypeError, "Invalid argument for string field.");
163
+ rb_raise(cTypeError, "Invalid argument for string field '%s' (given %s).",
164
+ name, rb_class2name(CLASS_OF(value)));
154
165
  }
155
166
 
156
167
  DEREF(memory, VALUE) = native_slot_encode_and_freeze_string(type, value);
@@ -158,7 +169,8 @@ void native_slot_set_value_and_case(upb_fieldtype_t type, VALUE type_class,
158
169
 
159
170
  case UPB_TYPE_BYTES: {
160
171
  if (CLASS_OF(value) != rb_cString) {
161
- rb_raise(cTypeError, "Invalid argument for string field.");
172
+ rb_raise(cTypeError, "Invalid argument for bytes field '%s' (given %s).",
173
+ name, rb_class2name(CLASS_OF(value)));
162
174
  }
163
175
 
164
176
  DEREF(memory, VALUE) = native_slot_encode_and_freeze_string(type, value);
@@ -168,9 +180,50 @@ void native_slot_set_value_and_case(upb_fieldtype_t type, VALUE type_class,
168
180
  if (CLASS_OF(value) == CLASS_OF(Qnil)) {
169
181
  value = Qnil;
170
182
  } else if (CLASS_OF(value) != type_class) {
171
- rb_raise(cTypeError,
172
- "Invalid type %s to assign to submessage field.",
173
- rb_class2name(CLASS_OF(value)));
183
+ // check for possible implicit conversions
184
+ VALUE converted_value = Qnil;
185
+ const char* field_type_name = rb_class2name(type_class);
186
+
187
+ if (strcmp(field_type_name, "Google::Protobuf::Timestamp") == 0 &&
188
+ rb_obj_is_kind_of(value, rb_cTime)) {
189
+ // Time -> Google::Protobuf::Timestamp
190
+ VALUE hash = rb_hash_new();
191
+ rb_hash_aset(hash, rb_str_new2("seconds"),
192
+ rb_funcall(value, rb_intern("to_i"), 0));
193
+ rb_hash_aset(hash, rb_str_new2("nanos"),
194
+ rb_funcall(value, rb_intern("nsec"), 0));
195
+ {
196
+ VALUE args[1] = {hash};
197
+ converted_value = rb_class_new_instance(1, args, type_class);
198
+ }
199
+ } else if (strcmp(field_type_name, "Google::Protobuf::Duration") == 0 &&
200
+ rb_obj_is_kind_of(value, rb_cNumeric)) {
201
+ // Numeric -> Google::Protobuf::Duration
202
+ VALUE hash = rb_hash_new();
203
+ rb_hash_aset(hash, rb_str_new2("seconds"),
204
+ rb_funcall(value, rb_intern("to_i"), 0));
205
+ {
206
+ VALUE n_value =
207
+ rb_funcall(value, rb_intern("remainder"), 1, INT2NUM(1));
208
+ n_value =
209
+ rb_funcall(n_value, rb_intern("*"), 1, INT2NUM(1000000000));
210
+ n_value = rb_funcall(n_value, rb_intern("round"), 0);
211
+ rb_hash_aset(hash, rb_str_new2("nanos"), n_value);
212
+ }
213
+ {
214
+ VALUE args[1] = { hash };
215
+ converted_value = rb_class_new_instance(1, args, type_class);
216
+ }
217
+ }
218
+
219
+ // raise if no suitable conversaion could be found
220
+ if (converted_value == Qnil) {
221
+ rb_raise(cTypeError,
222
+ "Invalid type %s to assign to submessage field '%s'.",
223
+ rb_class2name(CLASS_OF(value)), name);
224
+ } else {
225
+ value = converted_value;
226
+ }
174
227
  }
175
228
  DEREF(memory, VALUE) = value;
176
229
  break;
@@ -181,18 +234,18 @@ void native_slot_set_value_and_case(upb_fieldtype_t type, VALUE type_class,
181
234
  value = rb_funcall(value, rb_intern("to_sym"), 0);
182
235
  } else if (!is_ruby_num(value) && TYPE(value) != T_SYMBOL) {
183
236
  rb_raise(cTypeError,
184
- "Expected number or symbol type for enum field.");
237
+ "Expected number or symbol type for enum field '%s'.", name);
185
238
  }
186
239
  if (TYPE(value) == T_SYMBOL) {
187
240
  // Ensure that the given symbol exists in the enum module.
188
241
  VALUE lookup = rb_funcall(type_class, rb_intern("resolve"), 1, value);
189
242
  if (lookup == Qnil) {
190
- rb_raise(rb_eRangeError, "Unknown symbol value for enum field.");
243
+ rb_raise(rb_eRangeError, "Unknown symbol value for enum field '%s'.", name);
191
244
  } else {
192
245
  int_val = NUM2INT(lookup);
193
246
  }
194
247
  } else {
195
- native_slot_check_int_range_precision(UPB_TYPE_INT32, value);
248
+ native_slot_check_int_range_precision(name, UPB_TYPE_INT32, value);
196
249
  int_val = NUM2INT(value);
197
250
  }
198
251
  DEREF(memory, int32_t) = int_val;
@@ -202,7 +255,7 @@ void native_slot_set_value_and_case(upb_fieldtype_t type, VALUE type_class,
202
255
  case UPB_TYPE_INT64:
203
256
  case UPB_TYPE_UINT32:
204
257
  case UPB_TYPE_UINT64:
205
- native_slot_check_int_range_precision(type, value);
258
+ native_slot_check_int_range_precision(name, type, value);
206
259
  switch (type) {
207
260
  case UPB_TYPE_INT32:
208
261
  DEREF(memory, int32_t) = NUM2INT(value);
@@ -241,8 +294,20 @@ VALUE native_slot_get(upb_fieldtype_t type,
241
294
  return DEREF(memory, int8_t) ? Qtrue : Qfalse;
242
295
  case UPB_TYPE_STRING:
243
296
  case UPB_TYPE_BYTES:
244
- case UPB_TYPE_MESSAGE:
245
297
  return DEREF(memory, VALUE);
298
+ case UPB_TYPE_MESSAGE: {
299
+ VALUE val = DEREF(memory, VALUE);
300
+
301
+ // Lazily expand wrapper type if necessary.
302
+ int type = TYPE(val);
303
+ if (type != T_DATA && type != T_NIL) {
304
+ // This must be a wrapper type.
305
+ val = ruby_wrapper_type(type_class, val);
306
+ DEREF(memory, VALUE) = val;
307
+ }
308
+
309
+ return val;
310
+ }
246
311
  case UPB_TYPE_ENUM: {
247
312
  int32_t val = DEREF(memory, int32_t);
248
313
  VALUE symbol = enum_lookup(type_class, INT2NUM(val));
@@ -319,7 +384,8 @@ void native_slot_dup(upb_fieldtype_t type, void* to, void* from) {
319
384
  memcpy(to, from, native_slot_size(type));
320
385
  }
321
386
 
322
- void native_slot_deep_copy(upb_fieldtype_t type, void* to, void* from) {
387
+ void native_slot_deep_copy(upb_fieldtype_t type, VALUE type_class, void* to,
388
+ void* from) {
323
389
  switch (type) {
324
390
  case UPB_TYPE_STRING:
325
391
  case UPB_TYPE_BYTES: {
@@ -329,7 +395,7 @@ void native_slot_deep_copy(upb_fieldtype_t type, void* to, void* from) {
329
395
  break;
330
396
  }
331
397
  case UPB_TYPE_MESSAGE: {
332
- VALUE from_val = DEREF(from, VALUE);
398
+ VALUE from_val = native_slot_get(type, type_class, from);
333
399
  DEREF(to, VALUE) = (from_val != Qnil) ?
334
400
  Message_deep_copy(from_val) : Qnil;
335
401
  break;
@@ -339,13 +405,14 @@ void native_slot_deep_copy(upb_fieldtype_t type, void* to, void* from) {
339
405
  }
340
406
  }
341
407
 
342
- bool native_slot_eq(upb_fieldtype_t type, void* mem1, void* mem2) {
408
+ bool native_slot_eq(upb_fieldtype_t type, VALUE type_class, void* mem1,
409
+ void* mem2) {
343
410
  switch (type) {
344
411
  case UPB_TYPE_STRING:
345
412
  case UPB_TYPE_BYTES:
346
413
  case UPB_TYPE_MESSAGE: {
347
- VALUE val1 = DEREF(mem1, VALUE);
348
- VALUE val2 = DEREF(mem2, VALUE);
414
+ VALUE val1 = native_slot_get(type, type_class, mem1);
415
+ VALUE val2 = native_slot_get(type, type_class, mem2);
349
416
  VALUE ret = rb_funcall(val1, rb_intern("=="), 1, val2);
350
417
  return ret == Qtrue;
351
418
  }
@@ -420,16 +487,32 @@ static size_t align_up_to(size_t offset, size_t granularity) {
420
487
  return (offset + granularity - 1) & ~(granularity - 1);
421
488
  }
422
489
 
423
- MessageLayout* create_layout(const upb_msgdef* msgdef) {
490
+ bool is_value_field(const upb_fielddef* f) {
491
+ return upb_fielddef_isseq(f) || upb_fielddef_issubmsg(f) ||
492
+ upb_fielddef_isstring(f);
493
+ }
494
+
495
+ void create_layout(Descriptor* desc) {
496
+ const upb_msgdef *msgdef = desc->msgdef;
424
497
  MessageLayout* layout = ALLOC(MessageLayout);
425
498
  int nfields = upb_msgdef_numfields(msgdef);
499
+ int noneofs = upb_msgdef_numoneofs(msgdef);
426
500
  upb_msg_field_iter it;
427
501
  upb_msg_oneof_iter oit;
428
502
  size_t off = 0;
503
+ size_t hasbit = 0;
504
+
505
+ layout->empty_template = NULL;
506
+ layout->desc = desc;
507
+ desc->layout = layout;
429
508
 
430
509
  layout->fields = ALLOC_N(MessageField, nfields);
510
+ layout->oneofs = NULL;
511
+
512
+ if (noneofs > 0) {
513
+ layout->oneofs = ALLOC_N(MessageOneof, noneofs);
514
+ }
431
515
 
432
- size_t hasbit = 0;
433
516
  for (upb_msg_field_begin(&it, msgdef);
434
517
  !upb_msg_field_done(&it);
435
518
  upb_msg_field_next(&it)) {
@@ -438,7 +521,7 @@ MessageLayout* create_layout(const upb_msgdef* msgdef) {
438
521
  layout->fields[upb_fielddef_index(field)].hasbit = hasbit++;
439
522
  } else {
440
523
  layout->fields[upb_fielddef_index(field)].hasbit =
441
- MESSAGE_FIELD_NO_HASBIT;
524
+ MESSAGE_FIELD_NO_HASBIT;
442
525
  }
443
526
  }
444
527
 
@@ -446,29 +529,76 @@ MessageLayout* create_layout(const upb_msgdef* msgdef) {
446
529
  off += (hasbit + 8 - 1) / 8;
447
530
  }
448
531
 
532
+ off = align_up_to(off, sizeof(VALUE));
533
+ layout->value_offset = off;
534
+ layout->repeated_count = 0;
535
+ layout->map_count = 0;
536
+ layout->value_count = 0;
537
+
538
+ // Place all VALUE fields for repeated fields.
539
+ for (upb_msg_field_begin(&it, msgdef);
540
+ !upb_msg_field_done(&it);
541
+ upb_msg_field_next(&it)) {
542
+ const upb_fielddef* field = upb_msg_iter_field(&it);
543
+ if (upb_fielddef_containingoneof(field) || !upb_fielddef_isseq(field) ||
544
+ upb_fielddef_ismap(field)) {
545
+ continue;
546
+ }
547
+
548
+ layout->fields[upb_fielddef_index(field)].offset = off;
549
+ off += sizeof(VALUE);
550
+ layout->repeated_count++;
551
+ }
552
+
553
+ // Place all VALUE fields for map fields.
554
+ for (upb_msg_field_begin(&it, msgdef);
555
+ !upb_msg_field_done(&it);
556
+ upb_msg_field_next(&it)) {
557
+ const upb_fielddef* field = upb_msg_iter_field(&it);
558
+ if (upb_fielddef_containingoneof(field) || !upb_fielddef_isseq(field) ||
559
+ !upb_fielddef_ismap(field)) {
560
+ continue;
561
+ }
562
+
563
+ layout->fields[upb_fielddef_index(field)].offset = off;
564
+ off += sizeof(VALUE);
565
+ layout->map_count++;
566
+ }
567
+
568
+ layout->value_count = layout->repeated_count + layout->map_count;
569
+
570
+ // Next place all other (non-oneof) VALUE fields.
571
+ for (upb_msg_field_begin(&it, msgdef);
572
+ !upb_msg_field_done(&it);
573
+ upb_msg_field_next(&it)) {
574
+ const upb_fielddef* field = upb_msg_iter_field(&it);
575
+ if (upb_fielddef_containingoneof(field) || !is_value_field(field) ||
576
+ upb_fielddef_isseq(field)) {
577
+ continue;
578
+ }
579
+
580
+ layout->fields[upb_fielddef_index(field)].offset = off;
581
+ off += sizeof(VALUE);
582
+ layout->value_count++;
583
+ }
584
+
585
+ // Now place all other (non-oneof) fields.
449
586
  for (upb_msg_field_begin(&it, msgdef);
450
587
  !upb_msg_field_done(&it);
451
588
  upb_msg_field_next(&it)) {
452
589
  const upb_fielddef* field = upb_msg_iter_field(&it);
453
590
  size_t field_size;
454
591
 
455
- if (upb_fielddef_containingoneof(field)) {
456
- // Oneofs are handled separately below.
592
+ if (upb_fielddef_containingoneof(field) || is_value_field(field)) {
457
593
  continue;
458
594
  }
459
595
 
460
596
  // Allocate |field_size| bytes for this field in the layout.
461
- field_size = 0;
462
- if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
463
- field_size = sizeof(VALUE);
464
- } else {
465
- field_size = native_slot_size(upb_fielddef_type(field));
466
- }
597
+ field_size = native_slot_size(upb_fielddef_type(field));
598
+
467
599
  // Align current offset up to |size| granularity.
468
600
  off = align_up_to(off, field_size);
469
601
  layout->fields[upb_fielddef_index(field)].offset = off;
470
- layout->fields[upb_fielddef_index(field)].case_offset =
471
- MESSAGE_FIELD_NO_CASE;
472
602
  off += field_size;
473
603
  }
474
604
 
@@ -502,6 +632,7 @@ MessageLayout* create_layout(const upb_msgdef* msgdef) {
502
632
  upb_oneof_next(&fit)) {
503
633
  const upb_fielddef* field = upb_oneof_iter_field(&fit);
504
634
  layout->fields[upb_fielddef_index(field)].offset = off;
635
+ layout->oneofs[upb_oneofdef_index(oneof)].offset = off;
505
636
  }
506
637
  off += field_size;
507
638
  }
@@ -511,44 +642,43 @@ MessageLayout* create_layout(const upb_msgdef* msgdef) {
511
642
  !upb_msg_oneof_done(&oit);
512
643
  upb_msg_oneof_next(&oit)) {
513
644
  const upb_oneofdef* oneof = upb_msg_iter_oneof(&oit);
514
- upb_oneof_iter fit;
515
-
516
645
  size_t field_size = sizeof(uint32_t);
517
646
  // Align the offset.
518
647
  off = (off + field_size - 1) & ~(field_size - 1);
519
- // Assign all fields in the oneof this same offset.
520
- for (upb_oneof_begin(&fit, oneof);
521
- !upb_oneof_done(&fit);
522
- upb_oneof_next(&fit)) {
523
- const upb_fielddef* field = upb_oneof_iter_field(&fit);
524
- layout->fields[upb_fielddef_index(field)].case_offset = off;
525
- }
648
+ layout->oneofs[upb_oneofdef_index(oneof)].case_offset = off;
526
649
  off += field_size;
527
650
  }
528
651
 
529
652
  layout->size = off;
530
-
531
653
  layout->msgdef = msgdef;
532
- upb_msgdef_ref(layout->msgdef, &layout->msgdef);
533
654
 
534
- return layout;
655
+ // Create the empty message template.
656
+ layout->empty_template = ALLOC_N(char, layout->size);
657
+ memset(layout->empty_template, 0, layout->size);
658
+
659
+ for (upb_msg_field_begin(&it, layout->msgdef);
660
+ !upb_msg_field_done(&it);
661
+ upb_msg_field_next(&it)) {
662
+ layout_clear(layout, layout->empty_template, upb_msg_iter_field(&it));
663
+ }
535
664
  }
536
665
 
537
666
  void free_layout(MessageLayout* layout) {
667
+ xfree(layout->empty_template);
538
668
  xfree(layout->fields);
539
- upb_msgdef_unref(layout->msgdef, &layout->msgdef);
669
+ xfree(layout->oneofs);
540
670
  xfree(layout);
541
671
  }
542
672
 
543
- VALUE field_type_class(const upb_fielddef* field) {
673
+ VALUE field_type_class(const MessageLayout* layout, const upb_fielddef* field) {
544
674
  VALUE type_class = Qnil;
545
675
  if (upb_fielddef_type(field) == UPB_TYPE_MESSAGE) {
546
- VALUE submsgdesc =
547
- get_def_obj(upb_fielddef_subdef(field));
676
+ VALUE submsgdesc = get_msgdef_obj(layout->desc->descriptor_pool,
677
+ upb_fielddef_msgsubdef(field));
548
678
  type_class = Descriptor_msgclass(submsgdesc);
549
679
  } else if (upb_fielddef_type(field) == UPB_TYPE_ENUM) {
550
- VALUE subenumdesc =
551
- get_def_obj(upb_fielddef_subdef(field));
680
+ VALUE subenumdesc = get_enumdef_obj(layout->desc->descriptor_pool,
681
+ upb_fielddef_enumsubdef(field));
552
682
  type_class = EnumDescriptor_enummodule(subenumdesc);
553
683
  }
554
684
  return type_class;
@@ -563,9 +693,15 @@ static void* slot_memory(MessageLayout* layout,
563
693
 
564
694
  static uint32_t* slot_oneof_case(MessageLayout* layout,
565
695
  const void* storage,
566
- const upb_fielddef* field) {
567
- return (uint32_t *)(((uint8_t *)storage) +
568
- layout->fields[upb_fielddef_index(field)].case_offset);
696
+ const upb_oneofdef* oneof) {
697
+ return (uint32_t*)(((uint8_t*)storage) +
698
+ layout->oneofs[upb_oneofdef_index(oneof)].case_offset);
699
+ }
700
+
701
+ uint32_t slot_read_oneof_case(MessageLayout* layout, const void* storage,
702
+ const upb_oneofdef* oneof) {
703
+ uint32_t* ptr = slot_oneof_case(layout, storage, oneof);
704
+ return *ptr & ~ONEOF_CASE_MASK;
569
705
  }
570
706
 
571
707
  static void slot_set_hasbit(MessageLayout* layout,
@@ -608,13 +744,14 @@ void layout_clear(MessageLayout* layout,
608
744
  const void* storage,
609
745
  const upb_fielddef* field) {
610
746
  void* memory = slot_memory(layout, storage, field);
611
- uint32_t* oneof_case = slot_oneof_case(layout, storage, field);
747
+ const upb_oneofdef* oneof = upb_fielddef_containingoneof(field);
612
748
 
613
749
  if (field_contains_hasbit(layout, field)) {
614
750
  slot_clear_hasbit(layout, storage, field);
615
751
  }
616
752
 
617
- if (upb_fielddef_containingoneof(field)) {
753
+ if (oneof) {
754
+ uint32_t* oneof_case = slot_oneof_case(layout, storage, oneof);
618
755
  memset(memory, 0, NATIVE_SLOT_MAX_SIZE);
619
756
  *oneof_case = ONEOF_CASE_NONE;
620
757
  } else if (is_map_field(field)) {
@@ -622,7 +759,7 @@ void layout_clear(MessageLayout* layout,
622
759
 
623
760
  const upb_fielddef* key_field = map_field_key(field);
624
761
  const upb_fielddef* value_field = map_field_value(field);
625
- VALUE type_class = field_type_class(value_field);
762
+ VALUE type_class = field_type_class(layout, value_field);
626
763
 
627
764
  if (type_class != Qnil) {
628
765
  VALUE args[3] = {
@@ -643,7 +780,7 @@ void layout_clear(MessageLayout* layout,
643
780
  } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
644
781
  VALUE ary = Qnil;
645
782
 
646
- VALUE type_class = field_type_class(field);
783
+ VALUE type_class = field_type_class(layout, field);
647
784
 
648
785
  if (type_class != Qnil) {
649
786
  VALUE args[2] = {
@@ -658,8 +795,9 @@ void layout_clear(MessageLayout* layout,
658
795
 
659
796
  DEREF(memory, VALUE) = ary;
660
797
  } else {
661
- native_slot_set(upb_fielddef_type(field), field_type_class(field),
662
- memory, layout_get_default(field));
798
+ native_slot_set(upb_fielddef_name(field), upb_fielddef_type(field),
799
+ field_type_class(layout, field), memory,
800
+ layout_get_default(field));
663
801
  }
664
802
  }
665
803
 
@@ -688,12 +826,8 @@ VALUE layout_get_default(const upb_fielddef *field) {
688
826
  case UPB_TYPE_BYTES: {
689
827
  size_t size;
690
828
  const char *str = upb_fielddef_defaultstr(field, &size);
691
- VALUE str_rb = rb_str_new(str, size);
692
-
693
- rb_enc_associate(str_rb, (upb_fielddef_type(field) == UPB_TYPE_BYTES) ?
694
- kRubyString8bitEncoding : kRubyStringUtf8Encoding);
695
- rb_obj_freeze(str_rb);
696
- return str_rb;
829
+ return get_frozen_string(str, size,
830
+ upb_fielddef_type(field) == UPB_TYPE_BYTES);
697
831
  }
698
832
  default: return Qnil;
699
833
  }
@@ -703,8 +837,7 @@ VALUE layout_get(MessageLayout* layout,
703
837
  const void* storage,
704
838
  const upb_fielddef* field) {
705
839
  void* memory = slot_memory(layout, storage, field);
706
- uint32_t* oneof_case = slot_oneof_case(layout, storage, field);
707
-
840
+ const upb_oneofdef* oneof = upb_fielddef_containingoneof(field);
708
841
  bool field_set;
709
842
  if (field_contains_hasbit(layout, field)) {
710
843
  field_set = slot_is_hasbit_set(layout, storage, field);
@@ -712,25 +845,25 @@ VALUE layout_get(MessageLayout* layout,
712
845
  field_set = true;
713
846
  }
714
847
 
715
- if (upb_fielddef_containingoneof(field)) {
716
- if (*oneof_case != upb_fielddef_number(field)) {
848
+ if (oneof) {
849
+ uint32_t oneof_case = slot_read_oneof_case(layout, storage, oneof);
850
+ if (oneof_case != upb_fielddef_number(field)) {
717
851
  return layout_get_default(field);
718
852
  }
719
853
  return native_slot_get(upb_fielddef_type(field),
720
- field_type_class(field),
721
- memory);
854
+ field_type_class(layout, field), memory);
722
855
  } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
723
856
  return *((VALUE *)memory);
724
857
  } else if (!field_set) {
725
858
  return layout_get_default(field);
726
859
  } else {
727
860
  return native_slot_get(upb_fielddef_type(field),
728
- field_type_class(field),
729
- memory);
861
+ field_type_class(layout, field), memory);
730
862
  }
731
863
  }
732
864
 
733
- static void check_repeated_field_type(VALUE val, const upb_fielddef* field) {
865
+ static void check_repeated_field_type(const MessageLayout* layout, VALUE val,
866
+ const upb_fielddef* field) {
734
867
  RepeatedField* self;
735
868
  assert(upb_fielddef_label(field) == UPB_LABEL_REPEATED);
736
869
 
@@ -744,25 +877,13 @@ static void check_repeated_field_type(VALUE val, const upb_fielddef* field) {
744
877
  rb_raise(cTypeError, "Repeated field array has wrong element type");
745
878
  }
746
879
 
747
- if (self->field_type == UPB_TYPE_MESSAGE) {
748
- if (self->field_type_class !=
749
- Descriptor_msgclass(get_def_obj(upb_fielddef_subdef(field)))) {
750
- rb_raise(cTypeError,
751
- "Repeated field array has wrong message class");
752
- }
753
- }
754
-
755
-
756
- if (self->field_type == UPB_TYPE_ENUM) {
757
- if (self->field_type_class !=
758
- EnumDescriptor_enummodule(get_def_obj(upb_fielddef_subdef(field)))) {
759
- rb_raise(cTypeError,
760
- "Repeated field array has wrong enum class");
761
- }
880
+ if (self->field_type_class != field_type_class(layout, field)) {
881
+ rb_raise(cTypeError, "Repeated field array has wrong message/enum class");
762
882
  }
763
883
  }
764
884
 
765
- static void check_map_field_type(VALUE val, const upb_fielddef* field) {
885
+ static void check_map_field_type(const MessageLayout* layout, VALUE val,
886
+ const upb_fielddef* field) {
766
887
  const upb_fielddef* key_field = map_field_key(field);
767
888
  const upb_fielddef* value_field = map_field_value(field);
768
889
  Map* self;
@@ -779,25 +900,20 @@ static void check_map_field_type(VALUE val, const upb_fielddef* field) {
779
900
  if (self->value_type != upb_fielddef_type(value_field)) {
780
901
  rb_raise(cTypeError, "Map value type does not match field's value type");
781
902
  }
782
- if (upb_fielddef_type(value_field) == UPB_TYPE_MESSAGE ||
783
- upb_fielddef_type(value_field) == UPB_TYPE_ENUM) {
784
- if (self->value_type_class !=
785
- get_def_obj(upb_fielddef_subdef(value_field))) {
786
- rb_raise(cTypeError,
787
- "Map value type has wrong message/enum class");
788
- }
903
+ if (self->value_type_class != field_type_class(layout, value_field)) {
904
+ rb_raise(cTypeError, "Map value type has wrong message/enum class");
789
905
  }
790
906
  }
791
907
 
792
-
793
908
  void layout_set(MessageLayout* layout,
794
909
  void* storage,
795
910
  const upb_fielddef* field,
796
911
  VALUE val) {
797
912
  void* memory = slot_memory(layout, storage, field);
798
- uint32_t* oneof_case = slot_oneof_case(layout, storage, field);
913
+ const upb_oneofdef* oneof = upb_fielddef_containingoneof(field);
799
914
 
800
- if (upb_fielddef_containingoneof(field)) {
915
+ if (oneof) {
916
+ uint32_t* oneof_case = slot_oneof_case(layout, storage, oneof);
801
917
  if (val == Qnil) {
802
918
  // Assigning nil to a oneof field clears the oneof completely.
803
919
  *oneof_case = ONEOF_CASE_NONE;
@@ -815,20 +931,24 @@ void layout_set(MessageLayout* layout,
815
931
  // sync with the value slot whenever the Ruby VM has been called. Thus, we
816
932
  // use native_slot_set_value_and_case(), which ensures that both the value
817
933
  // and case number are altered atomically (w.r.t. the Ruby VM).
934
+ uint32_t case_value = upb_fielddef_number(field);
935
+ if (upb_fielddef_issubmsg(field) || upb_fielddef_isstring(field)) {
936
+ case_value |= ONEOF_CASE_MASK;
937
+ }
938
+
818
939
  native_slot_set_value_and_case(
819
- upb_fielddef_type(field), field_type_class(field),
820
- memory, val,
821
- oneof_case, upb_fielddef_number(field));
940
+ upb_fielddef_name(field), upb_fielddef_type(field),
941
+ field_type_class(layout, field), memory, val, oneof_case, case_value);
822
942
  }
823
943
  } else if (is_map_field(field)) {
824
- check_map_field_type(val, field);
944
+ check_map_field_type(layout, val, field);
825
945
  DEREF(memory, VALUE) = val;
826
946
  } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
827
- check_repeated_field_type(val, field);
947
+ check_repeated_field_type(layout, val, field);
828
948
  DEREF(memory, VALUE) = val;
829
949
  } else {
830
- native_slot_set(upb_fielddef_type(field), field_type_class(field), memory,
831
- val);
950
+ native_slot_set(upb_fielddef_name(field), upb_fielddef_type(field),
951
+ field_type_class(layout, field), memory, val);
832
952
  }
833
953
 
834
954
  if (layout->fields[upb_fielddef_index(field)].hasbit !=
@@ -837,34 +957,33 @@ void layout_set(MessageLayout* layout,
837
957
  }
838
958
  }
839
959
 
840
- void layout_init(MessageLayout* layout,
841
- void* storage) {
960
+ void layout_init(MessageLayout* layout, void* storage) {
961
+ VALUE* value = (VALUE*)CHARPTR_AT(storage, layout->value_offset);
962
+ int i;
842
963
 
843
- upb_msg_field_iter it;
844
- for (upb_msg_field_begin(&it, layout->msgdef);
845
- !upb_msg_field_done(&it);
846
- upb_msg_field_next(&it)) {
847
- layout_clear(layout, storage, upb_msg_iter_field(&it));
964
+ for (i = 0; i < layout->repeated_count; i++, value++) {
965
+ *value = RepeatedField_new_this_type(*value);
966
+ }
967
+
968
+ for (i = 0; i < layout->map_count; i++, value++) {
969
+ *value = Map_new_this_type(*value);
848
970
  }
849
971
  }
850
972
 
851
973
  void layout_mark(MessageLayout* layout, void* storage) {
852
- upb_msg_field_iter it;
853
- for (upb_msg_field_begin(&it, layout->msgdef);
854
- !upb_msg_field_done(&it);
855
- upb_msg_field_next(&it)) {
856
- const upb_fielddef* field = upb_msg_iter_field(&it);
857
- void* memory = slot_memory(layout, storage, field);
858
- uint32_t* oneof_case = slot_oneof_case(layout, storage, field);
974
+ VALUE* values = (VALUE*)CHARPTR_AT(storage, layout->value_offset);
975
+ int noneofs = upb_msgdef_numoneofs(layout->msgdef);
976
+ int i;
859
977
 
860
- if (upb_fielddef_containingoneof(field)) {
861
- if (*oneof_case == upb_fielddef_number(field)) {
862
- native_slot_mark(upb_fielddef_type(field), memory);
863
- }
864
- } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
865
- rb_gc_mark(DEREF(memory, VALUE));
866
- } else {
867
- native_slot_mark(upb_fielddef_type(field), memory);
978
+ for (i = 0; i < layout->value_count; i++) {
979
+ rb_gc_mark(values[i]);
980
+ }
981
+
982
+ for (i = 0; i < noneofs; i++) {
983
+ MessageOneof* oneof = &layout->oneofs[i];
984
+ uint32_t* case_ptr = (uint32_t*)CHARPTR_AT(storage, oneof->case_offset);
985
+ if (*case_ptr & ONEOF_CASE_MASK) {
986
+ rb_gc_mark(DEREF_OFFSET(storage, oneof->offset, VALUE));
868
987
  }
869
988
  }
870
989
  }
@@ -875,14 +994,16 @@ void layout_dup(MessageLayout* layout, void* to, void* from) {
875
994
  !upb_msg_field_done(&it);
876
995
  upb_msg_field_next(&it)) {
877
996
  const upb_fielddef* field = upb_msg_iter_field(&it);
997
+ const upb_oneofdef* oneof = upb_fielddef_containingoneof(field);
878
998
 
879
999
  void* to_memory = slot_memory(layout, to, field);
880
- uint32_t* to_oneof_case = slot_oneof_case(layout, to, field);
881
1000
  void* from_memory = slot_memory(layout, from, field);
882
- uint32_t* from_oneof_case = slot_oneof_case(layout, from, field);
883
1001
 
884
- if (upb_fielddef_containingoneof(field)) {
885
- if (*from_oneof_case == upb_fielddef_number(field)) {
1002
+ if (oneof) {
1003
+ uint32_t* to_oneof_case = slot_oneof_case(layout, to, oneof);
1004
+ uint32_t* from_oneof_case = slot_oneof_case(layout, from, oneof);
1005
+ if (slot_read_oneof_case(layout, from, oneof) ==
1006
+ upb_fielddef_number(field)) {
886
1007
  *to_oneof_case = *from_oneof_case;
887
1008
  native_slot_dup(upb_fielddef_type(field), to_memory, from_memory);
888
1009
  }
@@ -907,16 +1028,20 @@ void layout_deep_copy(MessageLayout* layout, void* to, void* from) {
907
1028
  !upb_msg_field_done(&it);
908
1029
  upb_msg_field_next(&it)) {
909
1030
  const upb_fielddef* field = upb_msg_iter_field(&it);
1031
+ const upb_oneofdef* oneof = upb_fielddef_containingoneof(field);
910
1032
 
911
1033
  void* to_memory = slot_memory(layout, to, field);
912
- uint32_t* to_oneof_case = slot_oneof_case(layout, to, field);
913
1034
  void* from_memory = slot_memory(layout, from, field);
914
- uint32_t* from_oneof_case = slot_oneof_case(layout, from, field);
915
1035
 
916
- if (upb_fielddef_containingoneof(field)) {
917
- if (*from_oneof_case == upb_fielddef_number(field)) {
1036
+ if (oneof) {
1037
+ uint32_t* to_oneof_case = slot_oneof_case(layout, to, oneof);
1038
+ uint32_t* from_oneof_case = slot_oneof_case(layout, from, oneof);
1039
+ if (slot_read_oneof_case(layout, from, oneof) ==
1040
+ upb_fielddef_number(field)) {
918
1041
  *to_oneof_case = *from_oneof_case;
919
- native_slot_deep_copy(upb_fielddef_type(field), to_memory, from_memory);
1042
+ native_slot_deep_copy(upb_fielddef_type(field),
1043
+ field_type_class(layout, field), to_memory,
1044
+ from_memory);
920
1045
  }
921
1046
  } else if (is_map_field(field)) {
922
1047
  DEREF(to_memory, VALUE) =
@@ -930,7 +1055,9 @@ void layout_deep_copy(MessageLayout* layout, void* to, void* from) {
930
1055
  slot_set_hasbit(layout, to, field);
931
1056
  }
932
1057
 
933
- native_slot_deep_copy(upb_fielddef_type(field), to_memory, from_memory);
1058
+ native_slot_deep_copy(upb_fielddef_type(field),
1059
+ field_type_class(layout, field), to_memory,
1060
+ from_memory);
934
1061
  }
935
1062
  }
936
1063
  }
@@ -941,17 +1068,19 @@ VALUE layout_eq(MessageLayout* layout, void* msg1, void* msg2) {
941
1068
  !upb_msg_field_done(&it);
942
1069
  upb_msg_field_next(&it)) {
943
1070
  const upb_fielddef* field = upb_msg_iter_field(&it);
1071
+ const upb_oneofdef* oneof = upb_fielddef_containingoneof(field);
944
1072
 
945
1073
  void* msg1_memory = slot_memory(layout, msg1, field);
946
- uint32_t* msg1_oneof_case = slot_oneof_case(layout, msg1, field);
947
1074
  void* msg2_memory = slot_memory(layout, msg2, field);
948
- uint32_t* msg2_oneof_case = slot_oneof_case(layout, msg2, field);
949
1075
 
950
- if (upb_fielddef_containingoneof(field)) {
1076
+ if (oneof) {
1077
+ uint32_t* msg1_oneof_case = slot_oneof_case(layout, msg1, oneof);
1078
+ uint32_t* msg2_oneof_case = slot_oneof_case(layout, msg2, oneof);
951
1079
  if (*msg1_oneof_case != *msg2_oneof_case ||
952
- (*msg1_oneof_case == upb_fielddef_number(field) &&
1080
+ (slot_read_oneof_case(layout, msg1, oneof) ==
1081
+ upb_fielddef_number(field) &&
953
1082
  !native_slot_eq(upb_fielddef_type(field),
954
- msg1_memory,
1083
+ field_type_class(layout, field), msg1_memory,
955
1084
  msg2_memory))) {
956
1085
  return Qfalse;
957
1086
  }
@@ -967,9 +1096,10 @@ VALUE layout_eq(MessageLayout* layout, void* msg1, void* msg2) {
967
1096
  }
968
1097
  } else {
969
1098
  if (slot_is_hasbit_set(layout, msg1, field) !=
970
- slot_is_hasbit_set(layout, msg2, field) ||
1099
+ slot_is_hasbit_set(layout, msg2, field) ||
971
1100
  !native_slot_eq(upb_fielddef_type(field),
972
- msg1_memory, msg2_memory)) {
1101
+ field_type_class(layout, field), msg1_memory,
1102
+ msg2_memory)) {
973
1103
  return Qfalse;
974
1104
  }
975
1105
  }