google-protobuf 3.7.0 → 3.14.0

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

Potentially problematic release.


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

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