google-protobuf 3.9.2 → 3.10.0.rc.1

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.

@@ -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);
@@ -460,16 +473,32 @@ static size_t align_up_to(size_t offset, size_t granularity) {
460
473
  return (offset + granularity - 1) & ~(granularity - 1);
461
474
  }
462
475
 
463
- MessageLayout* create_layout(const upb_msgdef* msgdef) {
476
+ bool is_value_field(const upb_fielddef* f) {
477
+ return upb_fielddef_isseq(f) || upb_fielddef_issubmsg(f) ||
478
+ upb_fielddef_isstring(f);
479
+ }
480
+
481
+ void create_layout(Descriptor* desc) {
482
+ const upb_msgdef *msgdef = desc->msgdef;
464
483
  MessageLayout* layout = ALLOC(MessageLayout);
465
484
  int nfields = upb_msgdef_numfields(msgdef);
485
+ int noneofs = upb_msgdef_numoneofs(msgdef);
466
486
  upb_msg_field_iter it;
467
487
  upb_msg_oneof_iter oit;
468
488
  size_t off = 0;
489
+ size_t hasbit = 0;
490
+
491
+ layout->empty_template = NULL;
492
+ layout->desc = desc;
493
+ desc->layout = layout;
469
494
 
470
495
  layout->fields = ALLOC_N(MessageField, nfields);
496
+ layout->oneofs = NULL;
497
+
498
+ if (noneofs > 0) {
499
+ layout->oneofs = ALLOC_N(MessageOneof, noneofs);
500
+ }
471
501
 
472
- size_t hasbit = 0;
473
502
  for (upb_msg_field_begin(&it, msgdef);
474
503
  !upb_msg_field_done(&it);
475
504
  upb_msg_field_next(&it)) {
@@ -478,7 +507,7 @@ MessageLayout* create_layout(const upb_msgdef* msgdef) {
478
507
  layout->fields[upb_fielddef_index(field)].hasbit = hasbit++;
479
508
  } else {
480
509
  layout->fields[upb_fielddef_index(field)].hasbit =
481
- MESSAGE_FIELD_NO_HASBIT;
510
+ MESSAGE_FIELD_NO_HASBIT;
482
511
  }
483
512
  }
484
513
 
@@ -486,29 +515,76 @@ MessageLayout* create_layout(const upb_msgdef* msgdef) {
486
515
  off += (hasbit + 8 - 1) / 8;
487
516
  }
488
517
 
518
+ off = align_up_to(off, sizeof(VALUE));
519
+ layout->value_offset = off;
520
+ layout->repeated_count = 0;
521
+ layout->map_count = 0;
522
+ layout->value_count = 0;
523
+
524
+ // Place all VALUE fields for repeated fields.
525
+ for (upb_msg_field_begin(&it, msgdef);
526
+ !upb_msg_field_done(&it);
527
+ upb_msg_field_next(&it)) {
528
+ const upb_fielddef* field = upb_msg_iter_field(&it);
529
+ if (upb_fielddef_containingoneof(field) || !upb_fielddef_isseq(field) ||
530
+ upb_fielddef_ismap(field)) {
531
+ continue;
532
+ }
533
+
534
+ layout->fields[upb_fielddef_index(field)].offset = off;
535
+ off += sizeof(VALUE);
536
+ layout->repeated_count++;
537
+ }
538
+
539
+ // Place all VALUE fields for map fields.
540
+ for (upb_msg_field_begin(&it, msgdef);
541
+ !upb_msg_field_done(&it);
542
+ upb_msg_field_next(&it)) {
543
+ const upb_fielddef* field = upb_msg_iter_field(&it);
544
+ if (upb_fielddef_containingoneof(field) || !upb_fielddef_isseq(field) ||
545
+ !upb_fielddef_ismap(field)) {
546
+ continue;
547
+ }
548
+
549
+ layout->fields[upb_fielddef_index(field)].offset = off;
550
+ off += sizeof(VALUE);
551
+ layout->map_count++;
552
+ }
553
+
554
+ layout->value_count = layout->repeated_count + layout->map_count;
555
+
556
+ // Next place all other (non-oneof) VALUE fields.
557
+ for (upb_msg_field_begin(&it, msgdef);
558
+ !upb_msg_field_done(&it);
559
+ upb_msg_field_next(&it)) {
560
+ const upb_fielddef* field = upb_msg_iter_field(&it);
561
+ if (upb_fielddef_containingoneof(field) || !is_value_field(field) ||
562
+ upb_fielddef_isseq(field)) {
563
+ continue;
564
+ }
565
+
566
+ layout->fields[upb_fielddef_index(field)].offset = off;
567
+ off += sizeof(VALUE);
568
+ layout->value_count++;
569
+ }
570
+
571
+ // Now place all other (non-oneof) fields.
489
572
  for (upb_msg_field_begin(&it, msgdef);
490
573
  !upb_msg_field_done(&it);
491
574
  upb_msg_field_next(&it)) {
492
575
  const upb_fielddef* field = upb_msg_iter_field(&it);
493
576
  size_t field_size;
494
577
 
495
- if (upb_fielddef_containingoneof(field)) {
496
- // Oneofs are handled separately below.
578
+ if (upb_fielddef_containingoneof(field) || is_value_field(field)) {
497
579
  continue;
498
580
  }
499
581
 
500
582
  // 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
- }
583
+ field_size = native_slot_size(upb_fielddef_type(field));
584
+
507
585
  // Align current offset up to |size| granularity.
508
586
  off = align_up_to(off, field_size);
509
587
  layout->fields[upb_fielddef_index(field)].offset = off;
510
- layout->fields[upb_fielddef_index(field)].case_offset =
511
- MESSAGE_FIELD_NO_CASE;
512
588
  off += field_size;
513
589
  }
514
590
 
@@ -542,6 +618,7 @@ MessageLayout* create_layout(const upb_msgdef* msgdef) {
542
618
  upb_oneof_next(&fit)) {
543
619
  const upb_fielddef* field = upb_oneof_iter_field(&fit);
544
620
  layout->fields[upb_fielddef_index(field)].offset = off;
621
+ layout->oneofs[upb_oneofdef_index(oneof)].offset = off;
545
622
  }
546
623
  off += field_size;
547
624
  }
@@ -551,44 +628,43 @@ MessageLayout* create_layout(const upb_msgdef* msgdef) {
551
628
  !upb_msg_oneof_done(&oit);
552
629
  upb_msg_oneof_next(&oit)) {
553
630
  const upb_oneofdef* oneof = upb_msg_iter_oneof(&oit);
554
- upb_oneof_iter fit;
555
-
556
631
  size_t field_size = sizeof(uint32_t);
557
632
  // Align the offset.
558
633
  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
- }
634
+ layout->oneofs[upb_oneofdef_index(oneof)].case_offset = off;
566
635
  off += field_size;
567
636
  }
568
637
 
569
638
  layout->size = off;
570
-
571
639
  layout->msgdef = msgdef;
572
- upb_msgdef_ref(layout->msgdef, &layout->msgdef);
573
640
 
574
- return layout;
641
+ // Create the empty message template.
642
+ layout->empty_template = ALLOC_N(char, layout->size);
643
+ memset(layout->empty_template, 0, layout->size);
644
+
645
+ for (upb_msg_field_begin(&it, layout->msgdef);
646
+ !upb_msg_field_done(&it);
647
+ upb_msg_field_next(&it)) {
648
+ layout_clear(layout, layout->empty_template, upb_msg_iter_field(&it));
649
+ }
575
650
  }
576
651
 
577
652
  void free_layout(MessageLayout* layout) {
653
+ xfree(layout->empty_template);
578
654
  xfree(layout->fields);
579
- upb_msgdef_unref(layout->msgdef, &layout->msgdef);
655
+ xfree(layout->oneofs);
580
656
  xfree(layout);
581
657
  }
582
658
 
583
- VALUE field_type_class(const upb_fielddef* field) {
659
+ VALUE field_type_class(const MessageLayout* layout, const upb_fielddef* field) {
584
660
  VALUE type_class = Qnil;
585
661
  if (upb_fielddef_type(field) == UPB_TYPE_MESSAGE) {
586
- VALUE submsgdesc =
587
- get_def_obj(upb_fielddef_subdef(field));
662
+ VALUE submsgdesc = get_msgdef_obj(layout->desc->descriptor_pool,
663
+ upb_fielddef_msgsubdef(field));
588
664
  type_class = Descriptor_msgclass(submsgdesc);
589
665
  } else if (upb_fielddef_type(field) == UPB_TYPE_ENUM) {
590
- VALUE subenumdesc =
591
- get_def_obj(upb_fielddef_subdef(field));
666
+ VALUE subenumdesc = get_enumdef_obj(layout->desc->descriptor_pool,
667
+ upb_fielddef_enumsubdef(field));
592
668
  type_class = EnumDescriptor_enummodule(subenumdesc);
593
669
  }
594
670
  return type_class;
@@ -603,9 +679,15 @@ static void* slot_memory(MessageLayout* layout,
603
679
 
604
680
  static uint32_t* slot_oneof_case(MessageLayout* layout,
605
681
  const void* storage,
606
- const upb_fielddef* field) {
607
- return (uint32_t *)(((uint8_t *)storage) +
608
- layout->fields[upb_fielddef_index(field)].case_offset);
682
+ const upb_oneofdef* oneof) {
683
+ return (uint32_t*)(((uint8_t*)storage) +
684
+ layout->oneofs[upb_oneofdef_index(oneof)].case_offset);
685
+ }
686
+
687
+ uint32_t slot_read_oneof_case(MessageLayout* layout, const void* storage,
688
+ const upb_oneofdef* oneof) {
689
+ uint32_t* ptr = slot_oneof_case(layout, storage, oneof);
690
+ return *ptr & ~ONEOF_CASE_MASK;
609
691
  }
610
692
 
611
693
  static void slot_set_hasbit(MessageLayout* layout,
@@ -648,13 +730,14 @@ void layout_clear(MessageLayout* layout,
648
730
  const void* storage,
649
731
  const upb_fielddef* field) {
650
732
  void* memory = slot_memory(layout, storage, field);
651
- uint32_t* oneof_case = slot_oneof_case(layout, storage, field);
733
+ const upb_oneofdef* oneof = upb_fielddef_containingoneof(field);
652
734
 
653
735
  if (field_contains_hasbit(layout, field)) {
654
736
  slot_clear_hasbit(layout, storage, field);
655
737
  }
656
738
 
657
- if (upb_fielddef_containingoneof(field)) {
739
+ if (oneof) {
740
+ uint32_t* oneof_case = slot_oneof_case(layout, storage, oneof);
658
741
  memset(memory, 0, NATIVE_SLOT_MAX_SIZE);
659
742
  *oneof_case = ONEOF_CASE_NONE;
660
743
  } else if (is_map_field(field)) {
@@ -662,7 +745,7 @@ void layout_clear(MessageLayout* layout,
662
745
 
663
746
  const upb_fielddef* key_field = map_field_key(field);
664
747
  const upb_fielddef* value_field = map_field_value(field);
665
- VALUE type_class = field_type_class(value_field);
748
+ VALUE type_class = field_type_class(layout, value_field);
666
749
 
667
750
  if (type_class != Qnil) {
668
751
  VALUE args[3] = {
@@ -683,7 +766,7 @@ void layout_clear(MessageLayout* layout,
683
766
  } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
684
767
  VALUE ary = Qnil;
685
768
 
686
- VALUE type_class = field_type_class(field);
769
+ VALUE type_class = field_type_class(layout, field);
687
770
 
688
771
  if (type_class != Qnil) {
689
772
  VALUE args[2] = {
@@ -698,9 +781,9 @@ void layout_clear(MessageLayout* layout,
698
781
 
699
782
  DEREF(memory, VALUE) = ary;
700
783
  } else {
701
- native_slot_set(upb_fielddef_name(field),
702
- upb_fielddef_type(field), field_type_class(field),
703
- memory, layout_get_default(field));
784
+ native_slot_set(upb_fielddef_name(field), upb_fielddef_type(field),
785
+ field_type_class(layout, field), memory,
786
+ layout_get_default(field));
704
787
  }
705
788
  }
706
789
 
@@ -729,12 +812,8 @@ VALUE layout_get_default(const upb_fielddef *field) {
729
812
  case UPB_TYPE_BYTES: {
730
813
  size_t size;
731
814
  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;
815
+ return get_frozen_string(str, size,
816
+ upb_fielddef_type(field) == UPB_TYPE_BYTES);
738
817
  }
739
818
  default: return Qnil;
740
819
  }
@@ -744,8 +823,7 @@ VALUE layout_get(MessageLayout* layout,
744
823
  const void* storage,
745
824
  const upb_fielddef* field) {
746
825
  void* memory = slot_memory(layout, storage, field);
747
- uint32_t* oneof_case = slot_oneof_case(layout, storage, field);
748
-
826
+ const upb_oneofdef* oneof = upb_fielddef_containingoneof(field);
749
827
  bool field_set;
750
828
  if (field_contains_hasbit(layout, field)) {
751
829
  field_set = slot_is_hasbit_set(layout, storage, field);
@@ -753,25 +831,25 @@ VALUE layout_get(MessageLayout* layout,
753
831
  field_set = true;
754
832
  }
755
833
 
756
- if (upb_fielddef_containingoneof(field)) {
757
- if (*oneof_case != upb_fielddef_number(field)) {
834
+ if (oneof) {
835
+ uint32_t oneof_case = slot_read_oneof_case(layout, storage, oneof);
836
+ if (oneof_case != upb_fielddef_number(field)) {
758
837
  return layout_get_default(field);
759
838
  }
760
839
  return native_slot_get(upb_fielddef_type(field),
761
- field_type_class(field),
762
- memory);
840
+ field_type_class(layout, field), memory);
763
841
  } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
764
842
  return *((VALUE *)memory);
765
843
  } else if (!field_set) {
766
844
  return layout_get_default(field);
767
845
  } else {
768
846
  return native_slot_get(upb_fielddef_type(field),
769
- field_type_class(field),
770
- memory);
847
+ field_type_class(layout, field), memory);
771
848
  }
772
849
  }
773
850
 
774
- static void check_repeated_field_type(VALUE val, const upb_fielddef* field) {
851
+ static void check_repeated_field_type(const MessageLayout* layout, VALUE val,
852
+ const upb_fielddef* field) {
775
853
  RepeatedField* self;
776
854
  assert(upb_fielddef_label(field) == UPB_LABEL_REPEATED);
777
855
 
@@ -785,25 +863,13 @@ static void check_repeated_field_type(VALUE val, const upb_fielddef* field) {
785
863
  rb_raise(cTypeError, "Repeated field array has wrong element type");
786
864
  }
787
865
 
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
- }
866
+ if (self->field_type_class != field_type_class(layout, field)) {
867
+ rb_raise(cTypeError, "Repeated field array has wrong message/enum class");
803
868
  }
804
869
  }
805
870
 
806
- static void check_map_field_type(VALUE val, const upb_fielddef* field) {
871
+ static void check_map_field_type(const MessageLayout* layout, VALUE val,
872
+ const upb_fielddef* field) {
807
873
  const upb_fielddef* key_field = map_field_key(field);
808
874
  const upb_fielddef* value_field = map_field_value(field);
809
875
  Map* self;
@@ -820,25 +886,20 @@ static void check_map_field_type(VALUE val, const upb_fielddef* field) {
820
886
  if (self->value_type != upb_fielddef_type(value_field)) {
821
887
  rb_raise(cTypeError, "Map value type does not match field's value type");
822
888
  }
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
- }
889
+ if (self->value_type_class != field_type_class(layout, value_field)) {
890
+ rb_raise(cTypeError, "Map value type has wrong message/enum class");
830
891
  }
831
892
  }
832
893
 
833
-
834
894
  void layout_set(MessageLayout* layout,
835
895
  void* storage,
836
896
  const upb_fielddef* field,
837
897
  VALUE val) {
838
898
  void* memory = slot_memory(layout, storage, field);
839
- uint32_t* oneof_case = slot_oneof_case(layout, storage, field);
899
+ const upb_oneofdef* oneof = upb_fielddef_containingoneof(field);
840
900
 
841
- if (upb_fielddef_containingoneof(field)) {
901
+ if (oneof) {
902
+ uint32_t* oneof_case = slot_oneof_case(layout, storage, oneof);
842
903
  if (val == Qnil) {
843
904
  // Assigning nil to a oneof field clears the oneof completely.
844
905
  *oneof_case = ONEOF_CASE_NONE;
@@ -856,22 +917,24 @@ void layout_set(MessageLayout* layout,
856
917
  // sync with the value slot whenever the Ruby VM has been called. Thus, we
857
918
  // use native_slot_set_value_and_case(), which ensures that both the value
858
919
  // and case number are altered atomically (w.r.t. the Ruby VM).
920
+ uint32_t case_value = upb_fielddef_number(field);
921
+ if (upb_fielddef_issubmsg(field) || upb_fielddef_isstring(field)) {
922
+ case_value |= ONEOF_CASE_MASK;
923
+ }
924
+
859
925
  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));
926
+ upb_fielddef_name(field), upb_fielddef_type(field),
927
+ field_type_class(layout, field), memory, val, oneof_case, case_value);
864
928
  }
865
929
  } else if (is_map_field(field)) {
866
- check_map_field_type(val, field);
930
+ check_map_field_type(layout, val, field);
867
931
  DEREF(memory, VALUE) = val;
868
932
  } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
869
- check_repeated_field_type(val, field);
933
+ check_repeated_field_type(layout, val, field);
870
934
  DEREF(memory, VALUE) = val;
871
935
  } else {
872
- native_slot_set(upb_fielddef_name(field),
873
- upb_fielddef_type(field), field_type_class(field),
874
- memory, val);
936
+ native_slot_set(upb_fielddef_name(field), upb_fielddef_type(field),
937
+ field_type_class(layout, field), memory, val);
875
938
  }
876
939
 
877
940
  if (layout->fields[upb_fielddef_index(field)].hasbit !=
@@ -880,34 +943,33 @@ void layout_set(MessageLayout* layout,
880
943
  }
881
944
  }
882
945
 
883
- void layout_init(MessageLayout* layout,
884
- void* storage) {
946
+ void layout_init(MessageLayout* layout, void* storage) {
947
+ VALUE* value = (VALUE*)CHARPTR_AT(storage, layout->value_offset);
948
+ int i;
885
949
 
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));
950
+ for (i = 0; i < layout->repeated_count; i++, value++) {
951
+ *value = RepeatedField_new_this_type(*value);
952
+ }
953
+
954
+ for (i = 0; i < layout->map_count; i++, value++) {
955
+ *value = Map_new_this_type(*value);
891
956
  }
892
957
  }
893
958
 
894
959
  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);
960
+ VALUE* values = (VALUE*)CHARPTR_AT(storage, layout->value_offset);
961
+ int noneofs = upb_msgdef_numoneofs(layout->msgdef);
962
+ int i;
902
963
 
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);
964
+ for (i = 0; i < layout->value_count; i++) {
965
+ rb_gc_mark(values[i]);
966
+ }
967
+
968
+ for (i = 0; i < noneofs; i++) {
969
+ MessageOneof* oneof = &layout->oneofs[i];
970
+ uint32_t* case_ptr = (uint32_t*)CHARPTR_AT(storage, oneof->case_offset);
971
+ if (*case_ptr & ONEOF_CASE_MASK) {
972
+ rb_gc_mark(DEREF_OFFSET(storage, oneof->offset, VALUE));
911
973
  }
912
974
  }
913
975
  }
@@ -918,14 +980,16 @@ void layout_dup(MessageLayout* layout, void* to, void* from) {
918
980
  !upb_msg_field_done(&it);
919
981
  upb_msg_field_next(&it)) {
920
982
  const upb_fielddef* field = upb_msg_iter_field(&it);
983
+ const upb_oneofdef* oneof = upb_fielddef_containingoneof(field);
921
984
 
922
985
  void* to_memory = slot_memory(layout, to, field);
923
- uint32_t* to_oneof_case = slot_oneof_case(layout, to, field);
924
986
  void* from_memory = slot_memory(layout, from, field);
925
- uint32_t* from_oneof_case = slot_oneof_case(layout, from, field);
926
987
 
927
- if (upb_fielddef_containingoneof(field)) {
928
- if (*from_oneof_case == upb_fielddef_number(field)) {
988
+ if (oneof) {
989
+ uint32_t* to_oneof_case = slot_oneof_case(layout, to, oneof);
990
+ uint32_t* from_oneof_case = slot_oneof_case(layout, from, oneof);
991
+ if (slot_read_oneof_case(layout, from, oneof) ==
992
+ upb_fielddef_number(field)) {
929
993
  *to_oneof_case = *from_oneof_case;
930
994
  native_slot_dup(upb_fielddef_type(field), to_memory, from_memory);
931
995
  }
@@ -950,14 +1014,16 @@ void layout_deep_copy(MessageLayout* layout, void* to, void* from) {
950
1014
  !upb_msg_field_done(&it);
951
1015
  upb_msg_field_next(&it)) {
952
1016
  const upb_fielddef* field = upb_msg_iter_field(&it);
1017
+ const upb_oneofdef* oneof = upb_fielddef_containingoneof(field);
953
1018
 
954
1019
  void* to_memory = slot_memory(layout, to, field);
955
- uint32_t* to_oneof_case = slot_oneof_case(layout, to, field);
956
1020
  void* from_memory = slot_memory(layout, from, field);
957
- uint32_t* from_oneof_case = slot_oneof_case(layout, from, field);
958
1021
 
959
- if (upb_fielddef_containingoneof(field)) {
960
- if (*from_oneof_case == upb_fielddef_number(field)) {
1022
+ if (oneof) {
1023
+ uint32_t* to_oneof_case = slot_oneof_case(layout, to, oneof);
1024
+ uint32_t* from_oneof_case = slot_oneof_case(layout, from, oneof);
1025
+ if (slot_read_oneof_case(layout, from, oneof) ==
1026
+ upb_fielddef_number(field)) {
961
1027
  *to_oneof_case = *from_oneof_case;
962
1028
  native_slot_deep_copy(upb_fielddef_type(field), to_memory, from_memory);
963
1029
  }
@@ -984,17 +1050,18 @@ VALUE layout_eq(MessageLayout* layout, void* msg1, void* msg2) {
984
1050
  !upb_msg_field_done(&it);
985
1051
  upb_msg_field_next(&it)) {
986
1052
  const upb_fielddef* field = upb_msg_iter_field(&it);
1053
+ const upb_oneofdef* oneof = upb_fielddef_containingoneof(field);
987
1054
 
988
1055
  void* msg1_memory = slot_memory(layout, msg1, field);
989
- uint32_t* msg1_oneof_case = slot_oneof_case(layout, msg1, field);
990
1056
  void* msg2_memory = slot_memory(layout, msg2, field);
991
- uint32_t* msg2_oneof_case = slot_oneof_case(layout, msg2, field);
992
1057
 
993
- if (upb_fielddef_containingoneof(field)) {
1058
+ if (oneof) {
1059
+ uint32_t* msg1_oneof_case = slot_oneof_case(layout, msg1, oneof);
1060
+ uint32_t* msg2_oneof_case = slot_oneof_case(layout, msg2, oneof);
994
1061
  if (*msg1_oneof_case != *msg2_oneof_case ||
995
- (*msg1_oneof_case == upb_fielddef_number(field) &&
996
- !native_slot_eq(upb_fielddef_type(field),
997
- msg1_memory,
1062
+ (slot_read_oneof_case(layout, msg1, oneof) ==
1063
+ upb_fielddef_number(field) &&
1064
+ !native_slot_eq(upb_fielddef_type(field), msg1_memory,
998
1065
  msg2_memory))) {
999
1066
  return Qfalse;
1000
1067
  }
@@ -1010,9 +1077,8 @@ VALUE layout_eq(MessageLayout* layout, void* msg1, void* msg2) {
1010
1077
  }
1011
1078
  } else {
1012
1079
  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)) {
1080
+ slot_is_hasbit_set(layout, msg2, field) ||
1081
+ !native_slot_eq(upb_fielddef_type(field), msg1_memory, msg2_memory)) {
1016
1082
  return Qfalse;
1017
1083
  }
1018
1084
  }