google-protobuf 3.7.0 → 3.14.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,25 +487,55 @@ 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_numrealoneofs(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
+ int i;
505
+
506
+ (void)i;
507
+
508
+ layout->empty_template = NULL;
509
+ layout->desc = desc;
510
+ desc->layout = layout;
429
511
 
430
512
  layout->fields = ALLOC_N(MessageField, nfields);
513
+ layout->oneofs = NULL;
514
+
515
+ if (noneofs > 0) {
516
+ layout->oneofs = ALLOC_N(MessageOneof, noneofs);
517
+ }
518
+
519
+ #ifndef NDEBUG
520
+ for (i = 0; i < nfields; i++) {
521
+ layout->fields[i].offset = -1;
522
+ }
523
+
524
+ for (i = 0; i < noneofs; i++) {
525
+ layout->oneofs[i].offset = -1;
526
+ }
527
+ #endif
431
528
 
432
- size_t hasbit = 0;
433
529
  for (upb_msg_field_begin(&it, msgdef);
434
530
  !upb_msg_field_done(&it);
435
531
  upb_msg_field_next(&it)) {
436
532
  const upb_fielddef* field = upb_msg_iter_field(&it);
437
- if (upb_fielddef_haspresence(field)) {
533
+ if (upb_fielddef_haspresence(field) &&
534
+ !upb_fielddef_realcontainingoneof(field)) {
438
535
  layout->fields[upb_fielddef_index(field)].hasbit = hasbit++;
439
536
  } else {
440
537
  layout->fields[upb_fielddef_index(field)].hasbit =
441
- MESSAGE_FIELD_NO_HASBIT;
538
+ MESSAGE_FIELD_NO_HASBIT;
442
539
  }
443
540
  }
444
541
 
@@ -446,29 +543,76 @@ MessageLayout* create_layout(const upb_msgdef* msgdef) {
446
543
  off += (hasbit + 8 - 1) / 8;
447
544
  }
448
545
 
546
+ off = align_up_to(off, sizeof(VALUE));
547
+ layout->value_offset = off;
548
+ layout->repeated_count = 0;
549
+ layout->map_count = 0;
550
+ layout->value_count = 0;
551
+
552
+ // Place all VALUE fields for repeated fields.
553
+ for (upb_msg_field_begin(&it, msgdef);
554
+ !upb_msg_field_done(&it);
555
+ upb_msg_field_next(&it)) {
556
+ const upb_fielddef* field = upb_msg_iter_field(&it);
557
+ if (upb_fielddef_realcontainingoneof(field) || !upb_fielddef_isseq(field) ||
558
+ upb_fielddef_ismap(field)) {
559
+ continue;
560
+ }
561
+
562
+ layout->fields[upb_fielddef_index(field)].offset = off;
563
+ off += sizeof(VALUE);
564
+ layout->repeated_count++;
565
+ }
566
+
567
+ // Place all VALUE fields for map fields.
568
+ for (upb_msg_field_begin(&it, msgdef);
569
+ !upb_msg_field_done(&it);
570
+ upb_msg_field_next(&it)) {
571
+ const upb_fielddef* field = upb_msg_iter_field(&it);
572
+ if (upb_fielddef_realcontainingoneof(field) || !upb_fielddef_isseq(field) ||
573
+ !upb_fielddef_ismap(field)) {
574
+ continue;
575
+ }
576
+
577
+ layout->fields[upb_fielddef_index(field)].offset = off;
578
+ off += sizeof(VALUE);
579
+ layout->map_count++;
580
+ }
581
+
582
+ layout->value_count = layout->repeated_count + layout->map_count;
583
+
584
+ // Next place all other (non-oneof) VALUE fields.
585
+ for (upb_msg_field_begin(&it, msgdef);
586
+ !upb_msg_field_done(&it);
587
+ upb_msg_field_next(&it)) {
588
+ const upb_fielddef* field = upb_msg_iter_field(&it);
589
+ if (upb_fielddef_realcontainingoneof(field) || !is_value_field(field) ||
590
+ upb_fielddef_isseq(field)) {
591
+ continue;
592
+ }
593
+
594
+ layout->fields[upb_fielddef_index(field)].offset = off;
595
+ off += sizeof(VALUE);
596
+ layout->value_count++;
597
+ }
598
+
599
+ // Now place all other (non-oneof) fields.
449
600
  for (upb_msg_field_begin(&it, msgdef);
450
601
  !upb_msg_field_done(&it);
451
602
  upb_msg_field_next(&it)) {
452
603
  const upb_fielddef* field = upb_msg_iter_field(&it);
453
604
  size_t field_size;
454
605
 
455
- if (upb_fielddef_containingoneof(field)) {
456
- // Oneofs are handled separately below.
606
+ if (upb_fielddef_realcontainingoneof(field) || is_value_field(field)) {
457
607
  continue;
458
608
  }
459
609
 
460
610
  // 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
- }
611
+ field_size = native_slot_size(upb_fielddef_type(field));
612
+
467
613
  // Align current offset up to |size| granularity.
468
614
  off = align_up_to(off, field_size);
469
615
  layout->fields[upb_fielddef_index(field)].offset = off;
470
- layout->fields[upb_fielddef_index(field)].case_offset =
471
- MESSAGE_FIELD_NO_CASE;
472
616
  off += field_size;
473
617
  }
474
618
 
@@ -494,6 +638,10 @@ MessageLayout* create_layout(const upb_msgdef* msgdef) {
494
638
  // Always allocate NATIVE_SLOT_MAX_SIZE bytes, but share the slot between
495
639
  // all fields.
496
640
  size_t field_size = NATIVE_SLOT_MAX_SIZE;
641
+
642
+ if (upb_oneofdef_issynthetic(oneof)) continue;
643
+ assert(upb_oneofdef_index(oneof) < noneofs);
644
+
497
645
  // Align the offset.
498
646
  off = align_up_to(off, field_size);
499
647
  // Assign all fields in the oneof this same offset.
@@ -502,6 +650,7 @@ MessageLayout* create_layout(const upb_msgdef* msgdef) {
502
650
  upb_oneof_next(&fit)) {
503
651
  const upb_fielddef* field = upb_oneof_iter_field(&fit);
504
652
  layout->fields[upb_fielddef_index(field)].offset = off;
653
+ layout->oneofs[upb_oneofdef_index(oneof)].offset = off;
505
654
  }
506
655
  off += field_size;
507
656
  }
@@ -511,44 +660,55 @@ MessageLayout* create_layout(const upb_msgdef* msgdef) {
511
660
  !upb_msg_oneof_done(&oit);
512
661
  upb_msg_oneof_next(&oit)) {
513
662
  const upb_oneofdef* oneof = upb_msg_iter_oneof(&oit);
514
- upb_oneof_iter fit;
515
-
516
663
  size_t field_size = sizeof(uint32_t);
664
+ if (upb_oneofdef_issynthetic(oneof)) continue;
665
+ assert(upb_oneofdef_index(oneof) < noneofs);
517
666
  // Align the offset.
518
667
  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
- }
668
+ layout->oneofs[upb_oneofdef_index(oneof)].case_offset = off;
526
669
  off += field_size;
527
670
  }
528
671
 
529
672
  layout->size = off;
530
-
531
673
  layout->msgdef = msgdef;
532
- upb_msgdef_ref(layout->msgdef, &layout->msgdef);
533
674
 
534
- return layout;
675
+ #ifndef NDEBUG
676
+ for (i = 0; i < nfields; i++) {
677
+ assert(layout->fields[i].offset != -1);
678
+ }
679
+
680
+ for (i = 0; i < noneofs; i++) {
681
+ assert(layout->oneofs[i].offset != -1);
682
+ }
683
+ #endif
684
+
685
+ // Create the empty message template.
686
+ layout->empty_template = ALLOC_N(char, layout->size);
687
+ memset(layout->empty_template, 0, layout->size);
688
+
689
+ for (upb_msg_field_begin(&it, layout->msgdef);
690
+ !upb_msg_field_done(&it);
691
+ upb_msg_field_next(&it)) {
692
+ layout_clear(layout, layout->empty_template, upb_msg_iter_field(&it));
693
+ }
535
694
  }
536
695
 
537
696
  void free_layout(MessageLayout* layout) {
697
+ xfree(layout->empty_template);
538
698
  xfree(layout->fields);
539
- upb_msgdef_unref(layout->msgdef, &layout->msgdef);
699
+ xfree(layout->oneofs);
540
700
  xfree(layout);
541
701
  }
542
702
 
543
- VALUE field_type_class(const upb_fielddef* field) {
703
+ VALUE field_type_class(const MessageLayout* layout, const upb_fielddef* field) {
544
704
  VALUE type_class = Qnil;
545
705
  if (upb_fielddef_type(field) == UPB_TYPE_MESSAGE) {
546
- VALUE submsgdesc =
547
- get_def_obj(upb_fielddef_subdef(field));
706
+ VALUE submsgdesc = get_msgdef_obj(layout->desc->descriptor_pool,
707
+ upb_fielddef_msgsubdef(field));
548
708
  type_class = Descriptor_msgclass(submsgdesc);
549
709
  } else if (upb_fielddef_type(field) == UPB_TYPE_ENUM) {
550
- VALUE subenumdesc =
551
- get_def_obj(upb_fielddef_subdef(field));
710
+ VALUE subenumdesc = get_enumdef_obj(layout->desc->descriptor_pool,
711
+ upb_fielddef_enumsubdef(field));
552
712
  type_class = EnumDescriptor_enummodule(subenumdesc);
553
713
  }
554
714
  return type_class;
@@ -563,9 +723,15 @@ static void* slot_memory(MessageLayout* layout,
563
723
 
564
724
  static uint32_t* slot_oneof_case(MessageLayout* layout,
565
725
  const void* storage,
566
- const upb_fielddef* field) {
567
- return (uint32_t *)(((uint8_t *)storage) +
568
- layout->fields[upb_fielddef_index(field)].case_offset);
726
+ const upb_oneofdef* oneof) {
727
+ return (uint32_t*)(((uint8_t*)storage) +
728
+ layout->oneofs[upb_oneofdef_index(oneof)].case_offset);
729
+ }
730
+
731
+ uint32_t slot_read_oneof_case(MessageLayout* layout, const void* storage,
732
+ const upb_oneofdef* oneof) {
733
+ uint32_t* ptr = slot_oneof_case(layout, storage, oneof);
734
+ return *ptr & ~ONEOF_CASE_MASK;
569
735
  }
570
736
 
571
737
  static void slot_set_hasbit(MessageLayout* layout,
@@ -589,10 +755,7 @@ static bool slot_is_hasbit_set(MessageLayout* layout,
589
755
  const void* storage,
590
756
  const upb_fielddef* field) {
591
757
  size_t hasbit = layout->fields[upb_fielddef_index(field)].hasbit;
592
- if (hasbit == MESSAGE_FIELD_NO_HASBIT) {
593
- return false;
594
- }
595
-
758
+ assert(field_contains_hasbit(layout, field));
596
759
  return DEREF_OFFSET(
597
760
  (uint8_t*)storage, hasbit / 8, char) & (1 << (hasbit % 8));
598
761
  }
@@ -600,21 +763,28 @@ static bool slot_is_hasbit_set(MessageLayout* layout,
600
763
  VALUE layout_has(MessageLayout* layout,
601
764
  const void* storage,
602
765
  const upb_fielddef* field) {
603
- assert(field_contains_hasbit(layout, field));
604
- return slot_is_hasbit_set(layout, storage, field) ? Qtrue : Qfalse;
766
+ const upb_oneofdef* oneof = upb_fielddef_realcontainingoneof(field);
767
+ assert(upb_fielddef_haspresence(field));
768
+ if (oneof) {
769
+ uint32_t oneof_case = slot_read_oneof_case(layout, storage, oneof);
770
+ return oneof_case == upb_fielddef_number(field) ? Qtrue : Qfalse;
771
+ } else {
772
+ return slot_is_hasbit_set(layout, storage, field) ? Qtrue : Qfalse;
773
+ }
605
774
  }
606
775
 
607
776
  void layout_clear(MessageLayout* layout,
608
777
  const void* storage,
609
778
  const upb_fielddef* field) {
610
779
  void* memory = slot_memory(layout, storage, field);
611
- uint32_t* oneof_case = slot_oneof_case(layout, storage, field);
780
+ const upb_oneofdef* oneof = upb_fielddef_realcontainingoneof(field);
612
781
 
613
782
  if (field_contains_hasbit(layout, field)) {
614
783
  slot_clear_hasbit(layout, storage, field);
615
784
  }
616
785
 
617
- if (upb_fielddef_containingoneof(field)) {
786
+ if (oneof) {
787
+ uint32_t* oneof_case = slot_oneof_case(layout, storage, oneof);
618
788
  memset(memory, 0, NATIVE_SLOT_MAX_SIZE);
619
789
  *oneof_case = ONEOF_CASE_NONE;
620
790
  } else if (is_map_field(field)) {
@@ -622,7 +792,7 @@ void layout_clear(MessageLayout* layout,
622
792
 
623
793
  const upb_fielddef* key_field = map_field_key(field);
624
794
  const upb_fielddef* value_field = map_field_value(field);
625
- VALUE type_class = field_type_class(value_field);
795
+ VALUE type_class = field_type_class(layout, value_field);
626
796
 
627
797
  if (type_class != Qnil) {
628
798
  VALUE args[3] = {
@@ -643,7 +813,7 @@ void layout_clear(MessageLayout* layout,
643
813
  } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
644
814
  VALUE ary = Qnil;
645
815
 
646
- VALUE type_class = field_type_class(field);
816
+ VALUE type_class = field_type_class(layout, field);
647
817
 
648
818
  if (type_class != Qnil) {
649
819
  VALUE args[2] = {
@@ -658,8 +828,9 @@ void layout_clear(MessageLayout* layout,
658
828
 
659
829
  DEREF(memory, VALUE) = ary;
660
830
  } else {
661
- native_slot_set(upb_fielddef_type(field), field_type_class(field),
662
- memory, layout_get_default(field));
831
+ native_slot_set(upb_fielddef_name(field), upb_fielddef_type(field),
832
+ field_type_class(layout, field), memory,
833
+ layout_get_default(field));
663
834
  }
664
835
  }
665
836
 
@@ -688,12 +859,8 @@ VALUE layout_get_default(const upb_fielddef *field) {
688
859
  case UPB_TYPE_BYTES: {
689
860
  size_t size;
690
861
  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;
862
+ return get_frozen_string(str, size,
863
+ upb_fielddef_type(field) == UPB_TYPE_BYTES);
697
864
  }
698
865
  default: return Qnil;
699
866
  }
@@ -703,8 +870,7 @@ VALUE layout_get(MessageLayout* layout,
703
870
  const void* storage,
704
871
  const upb_fielddef* field) {
705
872
  void* memory = slot_memory(layout, storage, field);
706
- uint32_t* oneof_case = slot_oneof_case(layout, storage, field);
707
-
873
+ const upb_oneofdef* oneof = upb_fielddef_realcontainingoneof(field);
708
874
  bool field_set;
709
875
  if (field_contains_hasbit(layout, field)) {
710
876
  field_set = slot_is_hasbit_set(layout, storage, field);
@@ -712,25 +878,25 @@ VALUE layout_get(MessageLayout* layout,
712
878
  field_set = true;
713
879
  }
714
880
 
715
- if (upb_fielddef_containingoneof(field)) {
716
- if (*oneof_case != upb_fielddef_number(field)) {
881
+ if (oneof) {
882
+ uint32_t oneof_case = slot_read_oneof_case(layout, storage, oneof);
883
+ if (oneof_case != upb_fielddef_number(field)) {
717
884
  return layout_get_default(field);
718
885
  }
719
886
  return native_slot_get(upb_fielddef_type(field),
720
- field_type_class(field),
721
- memory);
887
+ field_type_class(layout, field), memory);
722
888
  } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
723
889
  return *((VALUE *)memory);
724
890
  } else if (!field_set) {
725
891
  return layout_get_default(field);
726
892
  } else {
727
893
  return native_slot_get(upb_fielddef_type(field),
728
- field_type_class(field),
729
- memory);
894
+ field_type_class(layout, field), memory);
730
895
  }
731
896
  }
732
897
 
733
- static void check_repeated_field_type(VALUE val, const upb_fielddef* field) {
898
+ static void check_repeated_field_type(const MessageLayout* layout, VALUE val,
899
+ const upb_fielddef* field) {
734
900
  RepeatedField* self;
735
901
  assert(upb_fielddef_label(field) == UPB_LABEL_REPEATED);
736
902
 
@@ -744,25 +910,13 @@ static void check_repeated_field_type(VALUE val, const upb_fielddef* field) {
744
910
  rb_raise(cTypeError, "Repeated field array has wrong element type");
745
911
  }
746
912
 
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
- }
913
+ if (self->field_type_class != field_type_class(layout, field)) {
914
+ rb_raise(cTypeError, "Repeated field array has wrong message/enum class");
762
915
  }
763
916
  }
764
917
 
765
- static void check_map_field_type(VALUE val, const upb_fielddef* field) {
918
+ static void check_map_field_type(const MessageLayout* layout, VALUE val,
919
+ const upb_fielddef* field) {
766
920
  const upb_fielddef* key_field = map_field_key(field);
767
921
  const upb_fielddef* value_field = map_field_value(field);
768
922
  Map* self;
@@ -779,25 +933,20 @@ static void check_map_field_type(VALUE val, const upb_fielddef* field) {
779
933
  if (self->value_type != upb_fielddef_type(value_field)) {
780
934
  rb_raise(cTypeError, "Map value type does not match field's value type");
781
935
  }
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
- }
936
+ if (self->value_type_class != field_type_class(layout, value_field)) {
937
+ rb_raise(cTypeError, "Map value type has wrong message/enum class");
789
938
  }
790
939
  }
791
940
 
792
-
793
941
  void layout_set(MessageLayout* layout,
794
942
  void* storage,
795
943
  const upb_fielddef* field,
796
944
  VALUE val) {
797
945
  void* memory = slot_memory(layout, storage, field);
798
- uint32_t* oneof_case = slot_oneof_case(layout, storage, field);
946
+ const upb_oneofdef* oneof = upb_fielddef_realcontainingoneof(field);
799
947
 
800
- if (upb_fielddef_containingoneof(field)) {
948
+ if (oneof) {
949
+ uint32_t* oneof_case = slot_oneof_case(layout, storage, oneof);
801
950
  if (val == Qnil) {
802
951
  // Assigning nil to a oneof field clears the oneof completely.
803
952
  *oneof_case = ONEOF_CASE_NONE;
@@ -815,56 +964,68 @@ void layout_set(MessageLayout* layout,
815
964
  // sync with the value slot whenever the Ruby VM has been called. Thus, we
816
965
  // use native_slot_set_value_and_case(), which ensures that both the value
817
966
  // and case number are altered atomically (w.r.t. the Ruby VM).
967
+ uint32_t case_value = upb_fielddef_number(field);
968
+ if (upb_fielddef_issubmsg(field) || upb_fielddef_isstring(field)) {
969
+ case_value |= ONEOF_CASE_MASK;
970
+ }
971
+
818
972
  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));
973
+ upb_fielddef_name(field), upb_fielddef_type(field),
974
+ field_type_class(layout, field), memory, val, oneof_case, case_value);
822
975
  }
823
976
  } else if (is_map_field(field)) {
824
- check_map_field_type(val, field);
977
+ check_map_field_type(layout, val, field);
825
978
  DEREF(memory, VALUE) = val;
826
979
  } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
827
- check_repeated_field_type(val, field);
980
+ check_repeated_field_type(layout, val, field);
828
981
  DEREF(memory, VALUE) = val;
829
982
  } else {
830
- native_slot_set(upb_fielddef_type(field), field_type_class(field), memory,
831
- val);
983
+ native_slot_set(upb_fielddef_name(field), upb_fielddef_type(field),
984
+ field_type_class(layout, field), memory, val);
832
985
  }
833
986
 
834
987
  if (layout->fields[upb_fielddef_index(field)].hasbit !=
835
988
  MESSAGE_FIELD_NO_HASBIT) {
836
- slot_set_hasbit(layout, storage, field);
989
+ if (val == Qnil) {
990
+ // No other field type has a hasbit and allows nil assignment.
991
+ if (upb_fielddef_type(field) != UPB_TYPE_MESSAGE) {
992
+ fprintf(stderr, "field: %s\n", upb_fielddef_fullname(field));
993
+ }
994
+ assert(upb_fielddef_type(field) == UPB_TYPE_MESSAGE);
995
+ slot_clear_hasbit(layout, storage, field);
996
+ } else {
997
+ slot_set_hasbit(layout, storage, field);
998
+ }
837
999
  }
838
1000
  }
839
1001
 
840
- void layout_init(MessageLayout* layout,
841
- void* storage) {
1002
+ void layout_init(MessageLayout* layout, void* storage) {
1003
+ VALUE* value = (VALUE*)CHARPTR_AT(storage, layout->value_offset);
1004
+ int i;
842
1005
 
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));
1006
+ for (i = 0; i < layout->repeated_count; i++, value++) {
1007
+ *value = RepeatedField_new_this_type(*value);
1008
+ }
1009
+
1010
+ for (i = 0; i < layout->map_count; i++, value++) {
1011
+ *value = Map_new_this_type(*value);
848
1012
  }
849
1013
  }
850
1014
 
851
1015
  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);
1016
+ VALUE* values = (VALUE*)CHARPTR_AT(storage, layout->value_offset);
1017
+ int noneofs = upb_msgdef_numrealoneofs(layout->msgdef);
1018
+ int i;
859
1019
 
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);
1020
+ for (i = 0; i < layout->value_count; i++) {
1021
+ rb_gc_mark(values[i]);
1022
+ }
1023
+
1024
+ for (i = 0; i < noneofs; i++) {
1025
+ MessageOneof* oneof = &layout->oneofs[i];
1026
+ uint32_t* case_ptr = (uint32_t*)CHARPTR_AT(storage, oneof->case_offset);
1027
+ if (*case_ptr & ONEOF_CASE_MASK) {
1028
+ rb_gc_mark(DEREF_OFFSET(storage, oneof->offset, VALUE));
868
1029
  }
869
1030
  }
870
1031
  }
@@ -875,14 +1036,16 @@ void layout_dup(MessageLayout* layout, void* to, void* from) {
875
1036
  !upb_msg_field_done(&it);
876
1037
  upb_msg_field_next(&it)) {
877
1038
  const upb_fielddef* field = upb_msg_iter_field(&it);
1039
+ const upb_oneofdef* oneof = upb_fielddef_realcontainingoneof(field);
878
1040
 
879
1041
  void* to_memory = slot_memory(layout, to, field);
880
- uint32_t* to_oneof_case = slot_oneof_case(layout, to, field);
881
1042
  void* from_memory = slot_memory(layout, from, field);
882
- uint32_t* from_oneof_case = slot_oneof_case(layout, from, field);
883
1043
 
884
- if (upb_fielddef_containingoneof(field)) {
885
- if (*from_oneof_case == upb_fielddef_number(field)) {
1044
+ if (oneof) {
1045
+ uint32_t* to_oneof_case = slot_oneof_case(layout, to, oneof);
1046
+ uint32_t* from_oneof_case = slot_oneof_case(layout, from, oneof);
1047
+ if (slot_read_oneof_case(layout, from, oneof) ==
1048
+ upb_fielddef_number(field)) {
886
1049
  *to_oneof_case = *from_oneof_case;
887
1050
  native_slot_dup(upb_fielddef_type(field), to_memory, from_memory);
888
1051
  }
@@ -907,16 +1070,20 @@ void layout_deep_copy(MessageLayout* layout, void* to, void* from) {
907
1070
  !upb_msg_field_done(&it);
908
1071
  upb_msg_field_next(&it)) {
909
1072
  const upb_fielddef* field = upb_msg_iter_field(&it);
1073
+ const upb_oneofdef* oneof = upb_fielddef_realcontainingoneof(field);
910
1074
 
911
1075
  void* to_memory = slot_memory(layout, to, field);
912
- uint32_t* to_oneof_case = slot_oneof_case(layout, to, field);
913
1076
  void* from_memory = slot_memory(layout, from, field);
914
- uint32_t* from_oneof_case = slot_oneof_case(layout, from, field);
915
1077
 
916
- if (upb_fielddef_containingoneof(field)) {
917
- if (*from_oneof_case == upb_fielddef_number(field)) {
1078
+ if (oneof) {
1079
+ uint32_t* to_oneof_case = slot_oneof_case(layout, to, oneof);
1080
+ uint32_t* from_oneof_case = slot_oneof_case(layout, from, oneof);
1081
+ if (slot_read_oneof_case(layout, from, oneof) ==
1082
+ upb_fielddef_number(field)) {
918
1083
  *to_oneof_case = *from_oneof_case;
919
- native_slot_deep_copy(upb_fielddef_type(field), to_memory, from_memory);
1084
+ native_slot_deep_copy(upb_fielddef_type(field),
1085
+ field_type_class(layout, field), to_memory,
1086
+ from_memory);
920
1087
  }
921
1088
  } else if (is_map_field(field)) {
922
1089
  DEREF(to_memory, VALUE) =
@@ -930,7 +1097,9 @@ void layout_deep_copy(MessageLayout* layout, void* to, void* from) {
930
1097
  slot_set_hasbit(layout, to, field);
931
1098
  }
932
1099
 
933
- native_slot_deep_copy(upb_fielddef_type(field), to_memory, from_memory);
1100
+ native_slot_deep_copy(upb_fielddef_type(field),
1101
+ field_type_class(layout, field), to_memory,
1102
+ from_memory);
934
1103
  }
935
1104
  }
936
1105
  }
@@ -941,17 +1110,19 @@ VALUE layout_eq(MessageLayout* layout, void* msg1, void* msg2) {
941
1110
  !upb_msg_field_done(&it);
942
1111
  upb_msg_field_next(&it)) {
943
1112
  const upb_fielddef* field = upb_msg_iter_field(&it);
1113
+ const upb_oneofdef* oneof = upb_fielddef_realcontainingoneof(field);
944
1114
 
945
1115
  void* msg1_memory = slot_memory(layout, msg1, field);
946
- uint32_t* msg1_oneof_case = slot_oneof_case(layout, msg1, field);
947
1116
  void* msg2_memory = slot_memory(layout, msg2, field);
948
- uint32_t* msg2_oneof_case = slot_oneof_case(layout, msg2, field);
949
1117
 
950
- if (upb_fielddef_containingoneof(field)) {
1118
+ if (oneof) {
1119
+ uint32_t* msg1_oneof_case = slot_oneof_case(layout, msg1, oneof);
1120
+ uint32_t* msg2_oneof_case = slot_oneof_case(layout, msg2, oneof);
951
1121
  if (*msg1_oneof_case != *msg2_oneof_case ||
952
- (*msg1_oneof_case == upb_fielddef_number(field) &&
1122
+ (slot_read_oneof_case(layout, msg1, oneof) ==
1123
+ upb_fielddef_number(field) &&
953
1124
  !native_slot_eq(upb_fielddef_type(field),
954
- msg1_memory,
1125
+ field_type_class(layout, field), msg1_memory,
955
1126
  msg2_memory))) {
956
1127
  return Qfalse;
957
1128
  }
@@ -966,10 +1137,18 @@ VALUE layout_eq(MessageLayout* layout, void* msg1, void* msg2) {
966
1137
  return Qfalse;
967
1138
  }
968
1139
  } else {
969
- if (slot_is_hasbit_set(layout, msg1, field) !=
970
- slot_is_hasbit_set(layout, msg2, field) ||
971
- !native_slot_eq(upb_fielddef_type(field),
972
- msg1_memory, msg2_memory)) {
1140
+ if (field_contains_hasbit(layout, field) &&
1141
+ slot_is_hasbit_set(layout, msg1, field) !=
1142
+ slot_is_hasbit_set(layout, msg2, field)) {
1143
+ // TODO(haberman): I don't think we should actually care about hasbits
1144
+ // here: an unset default should be able to equal a set default. But we
1145
+ // can address this later (will also have to make sure defaults are
1146
+ // being properly set when hasbit is clear).
1147
+ return Qfalse;
1148
+ }
1149
+ if (!native_slot_eq(upb_fielddef_type(field),
1150
+ field_type_class(layout, field), msg1_memory,
1151
+ msg2_memory)) {
973
1152
  return Qfalse;
974
1153
  }
975
1154
  }