google-protobuf 3.8.0 → 3.13.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.

@@ -96,17 +96,19 @@ VALUE native_slot_encode_and_freeze_string(upb_fieldtype_t type, VALUE value) {
96
96
  kRubyStringUtf8Encoding : kRubyString8bitEncoding;
97
97
  VALUE desired_encoding_value = rb_enc_from_encoding(desired_encoding);
98
98
 
99
- // Note: this will not duplicate underlying string data unless necessary.
100
- 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);
101
102
 
102
- if (type == UPB_TYPE_STRING &&
103
- rb_enc_str_coderange(value) == ENC_CODERANGE_BROKEN) {
104
- rb_raise(rb_eEncodingError, "String is invalid UTF-8");
105
- }
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
+ }
106
107
 
107
- // Ensure the data remains valid. Since we called #encode a moment ago,
108
- // this does not freeze the string the user assigned.
109
- 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
+ }
110
112
 
111
113
  return value;
112
114
  }
@@ -179,32 +181,43 @@ void native_slot_set_value_and_case(const char* name,
179
181
  value = Qnil;
180
182
  } else if (CLASS_OF(value) != type_class) {
181
183
  // check for possible implicit conversions
182
- VALUE converted_value = NULL;
183
- char* field_type_name = rb_class2name(type_class);
184
+ VALUE converted_value = Qnil;
185
+ const char* field_type_name = rb_class2name(type_class);
184
186
 
185
187
  if (strcmp(field_type_name, "Google::Protobuf::Timestamp") == 0 &&
186
188
  rb_obj_is_kind_of(value, rb_cTime)) {
187
189
  // Time -> Google::Protobuf::Timestamp
188
190
  VALUE hash = rb_hash_new();
189
- rb_hash_aset(hash, rb_str_new2("seconds"), rb_funcall(value, rb_intern("to_i"), 0));
190
- rb_hash_aset(hash, rb_str_new2("nanos"), rb_funcall(value, rb_intern("nsec"), 0));
191
- VALUE args[1] = { hash };
192
- converted_value = rb_class_new_instance(1, args, type_class);
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
+ }
193
199
  } else if (strcmp(field_type_name, "Google::Protobuf::Duration") == 0 &&
194
200
  rb_obj_is_kind_of(value, rb_cNumeric)) {
195
201
  // Numeric -> Google::Protobuf::Duration
196
202
  VALUE hash = rb_hash_new();
197
- rb_hash_aset(hash, rb_str_new2("seconds"), rb_funcall(value, rb_intern("to_i"), 0));
198
- VALUE n_value = rb_funcall(value, rb_intern("remainder"), 1, INT2NUM(1));
199
- n_value = rb_funcall(n_value, rb_intern("*"), 1, INT2NUM(1000000000));
200
- n_value = rb_funcall(n_value, rb_intern("round"), 0);
201
- rb_hash_aset(hash, rb_str_new2("nanos"), n_value);
202
- VALUE args[1] = { hash };
203
- converted_value = rb_class_new_instance(1, args, type_class);
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
+ }
204
217
  }
205
218
 
206
219
  // raise if no suitable conversaion could be found
207
- if (converted_value == NULL) {
220
+ if (converted_value == Qnil) {
208
221
  rb_raise(cTypeError,
209
222
  "Invalid type %s to assign to submessage field '%s'.",
210
223
  rb_class2name(CLASS_OF(value)), name);
@@ -281,8 +294,20 @@ VALUE native_slot_get(upb_fieldtype_t type,
281
294
  return DEREF(memory, int8_t) ? Qtrue : Qfalse;
282
295
  case UPB_TYPE_STRING:
283
296
  case UPB_TYPE_BYTES:
284
- case UPB_TYPE_MESSAGE:
285
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
+ }
286
311
  case UPB_TYPE_ENUM: {
287
312
  int32_t val = DEREF(memory, int32_t);
288
313
  VALUE symbol = enum_lookup(type_class, INT2NUM(val));
@@ -359,7 +384,8 @@ void native_slot_dup(upb_fieldtype_t type, void* to, void* from) {
359
384
  memcpy(to, from, native_slot_size(type));
360
385
  }
361
386
 
362
- 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) {
363
389
  switch (type) {
364
390
  case UPB_TYPE_STRING:
365
391
  case UPB_TYPE_BYTES: {
@@ -369,7 +395,7 @@ void native_slot_deep_copy(upb_fieldtype_t type, void* to, void* from) {
369
395
  break;
370
396
  }
371
397
  case UPB_TYPE_MESSAGE: {
372
- VALUE from_val = DEREF(from, VALUE);
398
+ VALUE from_val = native_slot_get(type, type_class, from);
373
399
  DEREF(to, VALUE) = (from_val != Qnil) ?
374
400
  Message_deep_copy(from_val) : Qnil;
375
401
  break;
@@ -379,13 +405,14 @@ void native_slot_deep_copy(upb_fieldtype_t type, void* to, void* from) {
379
405
  }
380
406
  }
381
407
 
382
- 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) {
383
410
  switch (type) {
384
411
  case UPB_TYPE_STRING:
385
412
  case UPB_TYPE_BYTES:
386
413
  case UPB_TYPE_MESSAGE: {
387
- VALUE val1 = DEREF(mem1, VALUE);
388
- 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);
389
416
  VALUE ret = rb_funcall(val1, rb_intern("=="), 1, val2);
390
417
  return ret == Qtrue;
391
418
  }
@@ -460,25 +487,55 @@ static size_t align_up_to(size_t offset, size_t granularity) {
460
487
  return (offset + granularity - 1) & ~(granularity - 1);
461
488
  }
462
489
 
463
- 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;
464
497
  MessageLayout* layout = ALLOC(MessageLayout);
465
498
  int nfields = upb_msgdef_numfields(msgdef);
499
+ int noneofs = upb_msgdef_numrealoneofs(msgdef);
466
500
  upb_msg_field_iter it;
467
501
  upb_msg_oneof_iter oit;
468
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;
469
511
 
470
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
471
528
 
472
- size_t hasbit = 0;
473
529
  for (upb_msg_field_begin(&it, msgdef);
474
530
  !upb_msg_field_done(&it);
475
531
  upb_msg_field_next(&it)) {
476
532
  const upb_fielddef* field = upb_msg_iter_field(&it);
477
- if (upb_fielddef_haspresence(field)) {
533
+ if (upb_fielddef_haspresence(field) &&
534
+ !upb_fielddef_realcontainingoneof(field)) {
478
535
  layout->fields[upb_fielddef_index(field)].hasbit = hasbit++;
479
536
  } else {
480
537
  layout->fields[upb_fielddef_index(field)].hasbit =
481
- MESSAGE_FIELD_NO_HASBIT;
538
+ MESSAGE_FIELD_NO_HASBIT;
482
539
  }
483
540
  }
484
541
 
@@ -486,29 +543,76 @@ MessageLayout* create_layout(const upb_msgdef* msgdef) {
486
543
  off += (hasbit + 8 - 1) / 8;
487
544
  }
488
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.
489
600
  for (upb_msg_field_begin(&it, msgdef);
490
601
  !upb_msg_field_done(&it);
491
602
  upb_msg_field_next(&it)) {
492
603
  const upb_fielddef* field = upb_msg_iter_field(&it);
493
604
  size_t field_size;
494
605
 
495
- if (upb_fielddef_containingoneof(field)) {
496
- // Oneofs are handled separately below.
606
+ if (upb_fielddef_realcontainingoneof(field) || is_value_field(field)) {
497
607
  continue;
498
608
  }
499
609
 
500
610
  // Allocate |field_size| bytes for this field in the layout.
501
- field_size = 0;
502
- if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
503
- field_size = sizeof(VALUE);
504
- } else {
505
- field_size = native_slot_size(upb_fielddef_type(field));
506
- }
611
+ field_size = native_slot_size(upb_fielddef_type(field));
612
+
507
613
  // Align current offset up to |size| granularity.
508
614
  off = align_up_to(off, field_size);
509
615
  layout->fields[upb_fielddef_index(field)].offset = off;
510
- layout->fields[upb_fielddef_index(field)].case_offset =
511
- MESSAGE_FIELD_NO_CASE;
512
616
  off += field_size;
513
617
  }
514
618
 
@@ -534,6 +638,10 @@ MessageLayout* create_layout(const upb_msgdef* msgdef) {
534
638
  // Always allocate NATIVE_SLOT_MAX_SIZE bytes, but share the slot between
535
639
  // all fields.
536
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
+
537
645
  // Align the offset.
538
646
  off = align_up_to(off, field_size);
539
647
  // Assign all fields in the oneof this same offset.
@@ -542,6 +650,7 @@ MessageLayout* create_layout(const upb_msgdef* msgdef) {
542
650
  upb_oneof_next(&fit)) {
543
651
  const upb_fielddef* field = upb_oneof_iter_field(&fit);
544
652
  layout->fields[upb_fielddef_index(field)].offset = off;
653
+ layout->oneofs[upb_oneofdef_index(oneof)].offset = off;
545
654
  }
546
655
  off += field_size;
547
656
  }
@@ -551,44 +660,55 @@ MessageLayout* create_layout(const upb_msgdef* msgdef) {
551
660
  !upb_msg_oneof_done(&oit);
552
661
  upb_msg_oneof_next(&oit)) {
553
662
  const upb_oneofdef* oneof = upb_msg_iter_oneof(&oit);
554
- upb_oneof_iter fit;
555
-
556
663
  size_t field_size = sizeof(uint32_t);
664
+ if (upb_oneofdef_issynthetic(oneof)) continue;
665
+ assert(upb_oneofdef_index(oneof) < noneofs);
557
666
  // Align the offset.
558
667
  off = (off + field_size - 1) & ~(field_size - 1);
559
- // Assign all fields in the oneof this same offset.
560
- for (upb_oneof_begin(&fit, oneof);
561
- !upb_oneof_done(&fit);
562
- upb_oneof_next(&fit)) {
563
- const upb_fielddef* field = upb_oneof_iter_field(&fit);
564
- layout->fields[upb_fielddef_index(field)].case_offset = off;
565
- }
668
+ layout->oneofs[upb_oneofdef_index(oneof)].case_offset = off;
566
669
  off += field_size;
567
670
  }
568
671
 
569
672
  layout->size = off;
570
-
571
673
  layout->msgdef = msgdef;
572
- upb_msgdef_ref(layout->msgdef, &layout->msgdef);
573
674
 
574
- 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
+ }
575
694
  }
576
695
 
577
696
  void free_layout(MessageLayout* layout) {
697
+ xfree(layout->empty_template);
578
698
  xfree(layout->fields);
579
- upb_msgdef_unref(layout->msgdef, &layout->msgdef);
699
+ xfree(layout->oneofs);
580
700
  xfree(layout);
581
701
  }
582
702
 
583
- VALUE field_type_class(const upb_fielddef* field) {
703
+ VALUE field_type_class(const MessageLayout* layout, const upb_fielddef* field) {
584
704
  VALUE type_class = Qnil;
585
705
  if (upb_fielddef_type(field) == UPB_TYPE_MESSAGE) {
586
- VALUE submsgdesc =
587
- get_def_obj(upb_fielddef_subdef(field));
706
+ VALUE submsgdesc = get_msgdef_obj(layout->desc->descriptor_pool,
707
+ upb_fielddef_msgsubdef(field));
588
708
  type_class = Descriptor_msgclass(submsgdesc);
589
709
  } else if (upb_fielddef_type(field) == UPB_TYPE_ENUM) {
590
- VALUE subenumdesc =
591
- get_def_obj(upb_fielddef_subdef(field));
710
+ VALUE subenumdesc = get_enumdef_obj(layout->desc->descriptor_pool,
711
+ upb_fielddef_enumsubdef(field));
592
712
  type_class = EnumDescriptor_enummodule(subenumdesc);
593
713
  }
594
714
  return type_class;
@@ -603,9 +723,15 @@ static void* slot_memory(MessageLayout* layout,
603
723
 
604
724
  static uint32_t* slot_oneof_case(MessageLayout* layout,
605
725
  const void* storage,
606
- const upb_fielddef* field) {
607
- return (uint32_t *)(((uint8_t *)storage) +
608
- 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;
609
735
  }
610
736
 
611
737
  static void slot_set_hasbit(MessageLayout* layout,
@@ -629,10 +755,7 @@ static bool slot_is_hasbit_set(MessageLayout* layout,
629
755
  const void* storage,
630
756
  const upb_fielddef* field) {
631
757
  size_t hasbit = layout->fields[upb_fielddef_index(field)].hasbit;
632
- if (hasbit == MESSAGE_FIELD_NO_HASBIT) {
633
- return false;
634
- }
635
-
758
+ assert(field_contains_hasbit(layout, field));
636
759
  return DEREF_OFFSET(
637
760
  (uint8_t*)storage, hasbit / 8, char) & (1 << (hasbit % 8));
638
761
  }
@@ -640,21 +763,28 @@ static bool slot_is_hasbit_set(MessageLayout* layout,
640
763
  VALUE layout_has(MessageLayout* layout,
641
764
  const void* storage,
642
765
  const upb_fielddef* field) {
643
- assert(field_contains_hasbit(layout, field));
644
- 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
+ }
645
774
  }
646
775
 
647
776
  void layout_clear(MessageLayout* layout,
648
777
  const void* storage,
649
778
  const upb_fielddef* field) {
650
779
  void* memory = slot_memory(layout, storage, field);
651
- uint32_t* oneof_case = slot_oneof_case(layout, storage, field);
780
+ const upb_oneofdef* oneof = upb_fielddef_realcontainingoneof(field);
652
781
 
653
782
  if (field_contains_hasbit(layout, field)) {
654
783
  slot_clear_hasbit(layout, storage, field);
655
784
  }
656
785
 
657
- if (upb_fielddef_containingoneof(field)) {
786
+ if (oneof) {
787
+ uint32_t* oneof_case = slot_oneof_case(layout, storage, oneof);
658
788
  memset(memory, 0, NATIVE_SLOT_MAX_SIZE);
659
789
  *oneof_case = ONEOF_CASE_NONE;
660
790
  } else if (is_map_field(field)) {
@@ -662,7 +792,7 @@ void layout_clear(MessageLayout* layout,
662
792
 
663
793
  const upb_fielddef* key_field = map_field_key(field);
664
794
  const upb_fielddef* value_field = map_field_value(field);
665
- VALUE type_class = field_type_class(value_field);
795
+ VALUE type_class = field_type_class(layout, value_field);
666
796
 
667
797
  if (type_class != Qnil) {
668
798
  VALUE args[3] = {
@@ -683,7 +813,7 @@ void layout_clear(MessageLayout* layout,
683
813
  } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
684
814
  VALUE ary = Qnil;
685
815
 
686
- VALUE type_class = field_type_class(field);
816
+ VALUE type_class = field_type_class(layout, field);
687
817
 
688
818
  if (type_class != Qnil) {
689
819
  VALUE args[2] = {
@@ -698,9 +828,9 @@ void layout_clear(MessageLayout* layout,
698
828
 
699
829
  DEREF(memory, VALUE) = ary;
700
830
  } else {
701
- native_slot_set(upb_fielddef_name(field),
702
- upb_fielddef_type(field), field_type_class(field),
703
- 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));
704
834
  }
705
835
  }
706
836
 
@@ -729,12 +859,8 @@ VALUE layout_get_default(const upb_fielddef *field) {
729
859
  case UPB_TYPE_BYTES: {
730
860
  size_t size;
731
861
  const char *str = upb_fielddef_defaultstr(field, &size);
732
- VALUE str_rb = rb_str_new(str, size);
733
-
734
- rb_enc_associate(str_rb, (upb_fielddef_type(field) == UPB_TYPE_BYTES) ?
735
- kRubyString8bitEncoding : kRubyStringUtf8Encoding);
736
- rb_obj_freeze(str_rb);
737
- return str_rb;
862
+ return get_frozen_string(str, size,
863
+ upb_fielddef_type(field) == UPB_TYPE_BYTES);
738
864
  }
739
865
  default: return Qnil;
740
866
  }
@@ -744,8 +870,7 @@ VALUE layout_get(MessageLayout* layout,
744
870
  const void* storage,
745
871
  const upb_fielddef* field) {
746
872
  void* memory = slot_memory(layout, storage, field);
747
- uint32_t* oneof_case = slot_oneof_case(layout, storage, field);
748
-
873
+ const upb_oneofdef* oneof = upb_fielddef_realcontainingoneof(field);
749
874
  bool field_set;
750
875
  if (field_contains_hasbit(layout, field)) {
751
876
  field_set = slot_is_hasbit_set(layout, storage, field);
@@ -753,25 +878,25 @@ VALUE layout_get(MessageLayout* layout,
753
878
  field_set = true;
754
879
  }
755
880
 
756
- if (upb_fielddef_containingoneof(field)) {
757
- 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)) {
758
884
  return layout_get_default(field);
759
885
  }
760
886
  return native_slot_get(upb_fielddef_type(field),
761
- field_type_class(field),
762
- memory);
887
+ field_type_class(layout, field), memory);
763
888
  } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
764
889
  return *((VALUE *)memory);
765
890
  } else if (!field_set) {
766
891
  return layout_get_default(field);
767
892
  } else {
768
893
  return native_slot_get(upb_fielddef_type(field),
769
- field_type_class(field),
770
- memory);
894
+ field_type_class(layout, field), memory);
771
895
  }
772
896
  }
773
897
 
774
- 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) {
775
900
  RepeatedField* self;
776
901
  assert(upb_fielddef_label(field) == UPB_LABEL_REPEATED);
777
902
 
@@ -785,25 +910,13 @@ static void check_repeated_field_type(VALUE val, const upb_fielddef* field) {
785
910
  rb_raise(cTypeError, "Repeated field array has wrong element type");
786
911
  }
787
912
 
788
- if (self->field_type == UPB_TYPE_MESSAGE) {
789
- if (self->field_type_class !=
790
- Descriptor_msgclass(get_def_obj(upb_fielddef_subdef(field)))) {
791
- rb_raise(cTypeError,
792
- "Repeated field array has wrong message class");
793
- }
794
- }
795
-
796
-
797
- if (self->field_type == UPB_TYPE_ENUM) {
798
- if (self->field_type_class !=
799
- EnumDescriptor_enummodule(get_def_obj(upb_fielddef_subdef(field)))) {
800
- rb_raise(cTypeError,
801
- "Repeated field array has wrong enum class");
802
- }
913
+ if (self->field_type_class != field_type_class(layout, field)) {
914
+ rb_raise(cTypeError, "Repeated field array has wrong message/enum class");
803
915
  }
804
916
  }
805
917
 
806
- 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) {
807
920
  const upb_fielddef* key_field = map_field_key(field);
808
921
  const upb_fielddef* value_field = map_field_value(field);
809
922
  Map* self;
@@ -820,25 +933,20 @@ static void check_map_field_type(VALUE val, const upb_fielddef* field) {
820
933
  if (self->value_type != upb_fielddef_type(value_field)) {
821
934
  rb_raise(cTypeError, "Map value type does not match field's value type");
822
935
  }
823
- if (upb_fielddef_type(value_field) == UPB_TYPE_MESSAGE ||
824
- upb_fielddef_type(value_field) == UPB_TYPE_ENUM) {
825
- if (self->value_type_class !=
826
- get_def_obj(upb_fielddef_subdef(value_field))) {
827
- rb_raise(cTypeError,
828
- "Map value type has wrong message/enum class");
829
- }
936
+ if (self->value_type_class != field_type_class(layout, value_field)) {
937
+ rb_raise(cTypeError, "Map value type has wrong message/enum class");
830
938
  }
831
939
  }
832
940
 
833
-
834
941
  void layout_set(MessageLayout* layout,
835
942
  void* storage,
836
943
  const upb_fielddef* field,
837
944
  VALUE val) {
838
945
  void* memory = slot_memory(layout, storage, field);
839
- uint32_t* oneof_case = slot_oneof_case(layout, storage, field);
946
+ const upb_oneofdef* oneof = upb_fielddef_realcontainingoneof(field);
840
947
 
841
- if (upb_fielddef_containingoneof(field)) {
948
+ if (oneof) {
949
+ uint32_t* oneof_case = slot_oneof_case(layout, storage, oneof);
842
950
  if (val == Qnil) {
843
951
  // Assigning nil to a oneof field clears the oneof completely.
844
952
  *oneof_case = ONEOF_CASE_NONE;
@@ -856,58 +964,68 @@ void layout_set(MessageLayout* layout,
856
964
  // sync with the value slot whenever the Ruby VM has been called. Thus, we
857
965
  // use native_slot_set_value_and_case(), which ensures that both the value
858
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
+
859
972
  native_slot_set_value_and_case(
860
- upb_fielddef_name(field),
861
- upb_fielddef_type(field), field_type_class(field),
862
- memory, val,
863
- 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);
864
975
  }
865
976
  } else if (is_map_field(field)) {
866
- check_map_field_type(val, field);
977
+ check_map_field_type(layout, val, field);
867
978
  DEREF(memory, VALUE) = val;
868
979
  } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
869
- check_repeated_field_type(val, field);
980
+ check_repeated_field_type(layout, val, field);
870
981
  DEREF(memory, VALUE) = val;
871
982
  } else {
872
- native_slot_set(upb_fielddef_name(field),
873
- upb_fielddef_type(field), field_type_class(field),
874
- memory, val);
983
+ native_slot_set(upb_fielddef_name(field), upb_fielddef_type(field),
984
+ field_type_class(layout, field), memory, val);
875
985
  }
876
986
 
877
987
  if (layout->fields[upb_fielddef_index(field)].hasbit !=
878
988
  MESSAGE_FIELD_NO_HASBIT) {
879
- 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
+ }
880
999
  }
881
1000
  }
882
1001
 
883
- void layout_init(MessageLayout* layout,
884
- void* storage) {
1002
+ void layout_init(MessageLayout* layout, void* storage) {
1003
+ VALUE* value = (VALUE*)CHARPTR_AT(storage, layout->value_offset);
1004
+ int i;
885
1005
 
886
- upb_msg_field_iter it;
887
- for (upb_msg_field_begin(&it, layout->msgdef);
888
- !upb_msg_field_done(&it);
889
- upb_msg_field_next(&it)) {
890
- 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);
891
1012
  }
892
1013
  }
893
1014
 
894
1015
  void layout_mark(MessageLayout* layout, void* storage) {
895
- upb_msg_field_iter it;
896
- for (upb_msg_field_begin(&it, layout->msgdef);
897
- !upb_msg_field_done(&it);
898
- upb_msg_field_next(&it)) {
899
- const upb_fielddef* field = upb_msg_iter_field(&it);
900
- void* memory = slot_memory(layout, storage, field);
901
- 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;
902
1019
 
903
- if (upb_fielddef_containingoneof(field)) {
904
- if (*oneof_case == upb_fielddef_number(field)) {
905
- native_slot_mark(upb_fielddef_type(field), memory);
906
- }
907
- } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
908
- rb_gc_mark(DEREF(memory, VALUE));
909
- } else {
910
- 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));
911
1029
  }
912
1030
  }
913
1031
  }
@@ -918,14 +1036,16 @@ void layout_dup(MessageLayout* layout, void* to, void* from) {
918
1036
  !upb_msg_field_done(&it);
919
1037
  upb_msg_field_next(&it)) {
920
1038
  const upb_fielddef* field = upb_msg_iter_field(&it);
1039
+ const upb_oneofdef* oneof = upb_fielddef_realcontainingoneof(field);
921
1040
 
922
1041
  void* to_memory = slot_memory(layout, to, field);
923
- uint32_t* to_oneof_case = slot_oneof_case(layout, to, field);
924
1042
  void* from_memory = slot_memory(layout, from, field);
925
- uint32_t* from_oneof_case = slot_oneof_case(layout, from, field);
926
1043
 
927
- if (upb_fielddef_containingoneof(field)) {
928
- 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)) {
929
1049
  *to_oneof_case = *from_oneof_case;
930
1050
  native_slot_dup(upb_fielddef_type(field), to_memory, from_memory);
931
1051
  }
@@ -950,16 +1070,20 @@ void layout_deep_copy(MessageLayout* layout, void* to, void* from) {
950
1070
  !upb_msg_field_done(&it);
951
1071
  upb_msg_field_next(&it)) {
952
1072
  const upb_fielddef* field = upb_msg_iter_field(&it);
1073
+ const upb_oneofdef* oneof = upb_fielddef_realcontainingoneof(field);
953
1074
 
954
1075
  void* to_memory = slot_memory(layout, to, field);
955
- uint32_t* to_oneof_case = slot_oneof_case(layout, to, field);
956
1076
  void* from_memory = slot_memory(layout, from, field);
957
- uint32_t* from_oneof_case = slot_oneof_case(layout, from, field);
958
1077
 
959
- if (upb_fielddef_containingoneof(field)) {
960
- 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)) {
961
1083
  *to_oneof_case = *from_oneof_case;
962
- 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);
963
1087
  }
964
1088
  } else if (is_map_field(field)) {
965
1089
  DEREF(to_memory, VALUE) =
@@ -973,7 +1097,9 @@ void layout_deep_copy(MessageLayout* layout, void* to, void* from) {
973
1097
  slot_set_hasbit(layout, to, field);
974
1098
  }
975
1099
 
976
- 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);
977
1103
  }
978
1104
  }
979
1105
  }
@@ -984,17 +1110,19 @@ VALUE layout_eq(MessageLayout* layout, void* msg1, void* msg2) {
984
1110
  !upb_msg_field_done(&it);
985
1111
  upb_msg_field_next(&it)) {
986
1112
  const upb_fielddef* field = upb_msg_iter_field(&it);
1113
+ const upb_oneofdef* oneof = upb_fielddef_realcontainingoneof(field);
987
1114
 
988
1115
  void* msg1_memory = slot_memory(layout, msg1, field);
989
- uint32_t* msg1_oneof_case = slot_oneof_case(layout, msg1, field);
990
1116
  void* msg2_memory = slot_memory(layout, msg2, field);
991
- uint32_t* msg2_oneof_case = slot_oneof_case(layout, msg2, field);
992
1117
 
993
- 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);
994
1121
  if (*msg1_oneof_case != *msg2_oneof_case ||
995
- (*msg1_oneof_case == upb_fielddef_number(field) &&
1122
+ (slot_read_oneof_case(layout, msg1, oneof) ==
1123
+ upb_fielddef_number(field) &&
996
1124
  !native_slot_eq(upb_fielddef_type(field),
997
- msg1_memory,
1125
+ field_type_class(layout, field), msg1_memory,
998
1126
  msg2_memory))) {
999
1127
  return Qfalse;
1000
1128
  }
@@ -1009,10 +1137,18 @@ VALUE layout_eq(MessageLayout* layout, void* msg1, void* msg2) {
1009
1137
  return Qfalse;
1010
1138
  }
1011
1139
  } else {
1012
- if (slot_is_hasbit_set(layout, msg1, field) !=
1013
- slot_is_hasbit_set(layout, msg2, field) ||
1014
- !native_slot_eq(upb_fielddef_type(field),
1015
- 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)) {
1016
1152
  return Qfalse;
1017
1153
  }
1018
1154
  }