google-protobuf 3.8.0 → 3.13.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


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

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