google-protobuf 3.7.0 → 3.11.0

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

Potentially problematic release.


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

@@ -65,9 +65,10 @@ static bool is_ruby_num(VALUE value) {
65
65
  TYPE(value) == T_BIGNUM);
66
66
  }
67
67
 
68
- void native_slot_check_int_range_precision(upb_fieldtype_t type, VALUE val) {
68
+ void native_slot_check_int_range_precision(const char* name, upb_fieldtype_t type, VALUE val) {
69
69
  if (!is_ruby_num(val)) {
70
- rb_raise(cTypeError, "Expected number type for integral field.");
70
+ rb_raise(cTypeError, "Expected number type for integral field '%s' (given %s).",
71
+ name, rb_class2name(CLASS_OF(val)));
71
72
  }
72
73
 
73
74
  // NUM2{INT,UINT,LL,ULL} macros do the appropriate range checks on upper
@@ -77,13 +78,15 @@ void native_slot_check_int_range_precision(upb_fieldtype_t type, VALUE val) {
77
78
  double dbl_val = NUM2DBL(val);
78
79
  if (floor(dbl_val) != dbl_val) {
79
80
  rb_raise(rb_eRangeError,
80
- "Non-integral floating point value assigned to integer field.");
81
+ "Non-integral floating point value assigned to integer field '%s' (given %s).",
82
+ name, rb_class2name(CLASS_OF(val)));
81
83
  }
82
84
  }
83
85
  if (type == UPB_TYPE_UINT32 || type == UPB_TYPE_UINT64) {
84
86
  if (NUM2DBL(val) < 0) {
85
87
  rb_raise(rb_eRangeError,
86
- "Assigning negative value to unsigned integer field.");
88
+ "Assigning negative value to unsigned integer field '%s' (given %s).",
89
+ name, rb_class2name(CLASS_OF(val)));
87
90
  }
88
91
  }
89
92
  }
@@ -93,27 +96,31 @@ VALUE native_slot_encode_and_freeze_string(upb_fieldtype_t type, VALUE value) {
93
96
  kRubyStringUtf8Encoding : kRubyString8bitEncoding;
94
97
  VALUE desired_encoding_value = rb_enc_from_encoding(desired_encoding);
95
98
 
96
- // Note: this will not duplicate underlying string data unless necessary.
97
- value = rb_str_encode(value, desired_encoding_value, 0, Qnil);
99
+ if (rb_obj_encoding(value) != desired_encoding_value || !OBJ_FROZEN(value)) {
100
+ // Note: this will not duplicate underlying string data unless necessary.
101
+ value = rb_str_encode(value, desired_encoding_value, 0, Qnil);
98
102
 
99
- if (type == UPB_TYPE_STRING &&
100
- rb_enc_str_coderange(value) == ENC_CODERANGE_BROKEN) {
101
- rb_raise(rb_eEncodingError, "String is invalid UTF-8");
102
- }
103
+ if (type == UPB_TYPE_STRING &&
104
+ rb_enc_str_coderange(value) == ENC_CODERANGE_BROKEN) {
105
+ rb_raise(rb_eEncodingError, "String is invalid UTF-8");
106
+ }
103
107
 
104
- // Ensure the data remains valid. Since we called #encode a moment ago,
105
- // this does not freeze the string the user assigned.
106
- rb_obj_freeze(value);
108
+ // Ensure the data remains valid. Since we called #encode a moment ago,
109
+ // this does not freeze the string the user assigned.
110
+ rb_obj_freeze(value);
111
+ }
107
112
 
108
113
  return value;
109
114
  }
110
115
 
111
- void native_slot_set(upb_fieldtype_t type, VALUE type_class,
116
+ void native_slot_set(const char* name,
117
+ upb_fieldtype_t type, VALUE type_class,
112
118
  void* memory, VALUE value) {
113
- native_slot_set_value_and_case(type, type_class, memory, value, NULL, 0);
119
+ native_slot_set_value_and_case(name, type, type_class, memory, value, NULL, 0);
114
120
  }
115
121
 
116
- void native_slot_set_value_and_case(upb_fieldtype_t type, VALUE type_class,
122
+ void native_slot_set_value_and_case(const char* name,
123
+ upb_fieldtype_t type, VALUE type_class,
117
124
  void* memory, VALUE value,
118
125
  uint32_t* case_memory,
119
126
  uint32_t case_number) {
@@ -124,13 +131,15 @@ void native_slot_set_value_and_case(upb_fieldtype_t type, VALUE type_class,
124
131
  switch (type) {
125
132
  case UPB_TYPE_FLOAT:
126
133
  if (!is_ruby_num(value)) {
127
- rb_raise(cTypeError, "Expected number type for float field.");
134
+ rb_raise(cTypeError, "Expected number type for float field '%s' (given %s).",
135
+ name, rb_class2name(CLASS_OF(value)));
128
136
  }
129
137
  DEREF(memory, float) = NUM2DBL(value);
130
138
  break;
131
139
  case UPB_TYPE_DOUBLE:
132
140
  if (!is_ruby_num(value)) {
133
- rb_raise(cTypeError, "Expected number type for double field.");
141
+ rb_raise(cTypeError, "Expected number type for double field '%s' (given %s).",
142
+ name, rb_class2name(CLASS_OF(value)));
134
143
  }
135
144
  DEREF(memory, double) = NUM2DBL(value);
136
145
  break;
@@ -141,7 +150,8 @@ void native_slot_set_value_and_case(upb_fieldtype_t type, VALUE type_class,
141
150
  } else if (value == Qfalse) {
142
151
  val = 0;
143
152
  } else {
144
- rb_raise(cTypeError, "Invalid argument for boolean field.");
153
+ rb_raise(cTypeError, "Invalid argument for boolean field '%s' (given %s).",
154
+ name, rb_class2name(CLASS_OF(value)));
145
155
  }
146
156
  DEREF(memory, int8_t) = val;
147
157
  break;
@@ -150,7 +160,8 @@ void native_slot_set_value_and_case(upb_fieldtype_t type, VALUE type_class,
150
160
  if (CLASS_OF(value) == rb_cSymbol) {
151
161
  value = rb_funcall(value, rb_intern("to_s"), 0);
152
162
  } else if (CLASS_OF(value) != rb_cString) {
153
- rb_raise(cTypeError, "Invalid argument for string field.");
163
+ rb_raise(cTypeError, "Invalid argument for string field '%s' (given %s).",
164
+ name, rb_class2name(CLASS_OF(value)));
154
165
  }
155
166
 
156
167
  DEREF(memory, VALUE) = native_slot_encode_and_freeze_string(type, value);
@@ -158,7 +169,8 @@ void native_slot_set_value_and_case(upb_fieldtype_t type, VALUE type_class,
158
169
 
159
170
  case UPB_TYPE_BYTES: {
160
171
  if (CLASS_OF(value) != rb_cString) {
161
- rb_raise(cTypeError, "Invalid argument for string field.");
172
+ rb_raise(cTypeError, "Invalid argument for bytes field '%s' (given %s).",
173
+ name, rb_class2name(CLASS_OF(value)));
162
174
  }
163
175
 
164
176
  DEREF(memory, VALUE) = native_slot_encode_and_freeze_string(type, value);
@@ -168,9 +180,50 @@ void native_slot_set_value_and_case(upb_fieldtype_t type, VALUE type_class,
168
180
  if (CLASS_OF(value) == CLASS_OF(Qnil)) {
169
181
  value = Qnil;
170
182
  } else if (CLASS_OF(value) != type_class) {
171
- rb_raise(cTypeError,
172
- "Invalid type %s to assign to submessage field.",
173
- rb_class2name(CLASS_OF(value)));
183
+ // check for possible implicit conversions
184
+ VALUE converted_value = Qnil;
185
+ const char* field_type_name = rb_class2name(type_class);
186
+
187
+ if (strcmp(field_type_name, "Google::Protobuf::Timestamp") == 0 &&
188
+ rb_obj_is_kind_of(value, rb_cTime)) {
189
+ // Time -> Google::Protobuf::Timestamp
190
+ VALUE hash = rb_hash_new();
191
+ rb_hash_aset(hash, rb_str_new2("seconds"),
192
+ rb_funcall(value, rb_intern("to_i"), 0));
193
+ rb_hash_aset(hash, rb_str_new2("nanos"),
194
+ rb_funcall(value, rb_intern("nsec"), 0));
195
+ {
196
+ VALUE args[1] = {hash};
197
+ converted_value = rb_class_new_instance(1, args, type_class);
198
+ }
199
+ } else if (strcmp(field_type_name, "Google::Protobuf::Duration") == 0 &&
200
+ rb_obj_is_kind_of(value, rb_cNumeric)) {
201
+ // Numeric -> Google::Protobuf::Duration
202
+ VALUE hash = rb_hash_new();
203
+ rb_hash_aset(hash, rb_str_new2("seconds"),
204
+ rb_funcall(value, rb_intern("to_i"), 0));
205
+ {
206
+ VALUE n_value =
207
+ rb_funcall(value, rb_intern("remainder"), 1, INT2NUM(1));
208
+ n_value =
209
+ rb_funcall(n_value, rb_intern("*"), 1, INT2NUM(1000000000));
210
+ n_value = rb_funcall(n_value, rb_intern("round"), 0);
211
+ rb_hash_aset(hash, rb_str_new2("nanos"), n_value);
212
+ }
213
+ {
214
+ VALUE args[1] = { hash };
215
+ converted_value = rb_class_new_instance(1, args, type_class);
216
+ }
217
+ }
218
+
219
+ // raise if no suitable conversaion could be found
220
+ if (converted_value == Qnil) {
221
+ rb_raise(cTypeError,
222
+ "Invalid type %s to assign to submessage field '%s'.",
223
+ rb_class2name(CLASS_OF(value)), name);
224
+ } else {
225
+ value = converted_value;
226
+ }
174
227
  }
175
228
  DEREF(memory, VALUE) = value;
176
229
  break;
@@ -181,18 +234,18 @@ void native_slot_set_value_and_case(upb_fieldtype_t type, VALUE type_class,
181
234
  value = rb_funcall(value, rb_intern("to_sym"), 0);
182
235
  } else if (!is_ruby_num(value) && TYPE(value) != T_SYMBOL) {
183
236
  rb_raise(cTypeError,
184
- "Expected number or symbol type for enum field.");
237
+ "Expected number or symbol type for enum field '%s'.", name);
185
238
  }
186
239
  if (TYPE(value) == T_SYMBOL) {
187
240
  // Ensure that the given symbol exists in the enum module.
188
241
  VALUE lookup = rb_funcall(type_class, rb_intern("resolve"), 1, value);
189
242
  if (lookup == Qnil) {
190
- rb_raise(rb_eRangeError, "Unknown symbol value for enum field.");
243
+ rb_raise(rb_eRangeError, "Unknown symbol value for enum field '%s'.", name);
191
244
  } else {
192
245
  int_val = NUM2INT(lookup);
193
246
  }
194
247
  } else {
195
- native_slot_check_int_range_precision(UPB_TYPE_INT32, value);
248
+ native_slot_check_int_range_precision(name, UPB_TYPE_INT32, value);
196
249
  int_val = NUM2INT(value);
197
250
  }
198
251
  DEREF(memory, int32_t) = int_val;
@@ -202,7 +255,7 @@ void native_slot_set_value_and_case(upb_fieldtype_t type, VALUE type_class,
202
255
  case UPB_TYPE_INT64:
203
256
  case UPB_TYPE_UINT32:
204
257
  case UPB_TYPE_UINT64:
205
- native_slot_check_int_range_precision(type, value);
258
+ native_slot_check_int_range_precision(name, type, value);
206
259
  switch (type) {
207
260
  case UPB_TYPE_INT32:
208
261
  DEREF(memory, int32_t) = NUM2INT(value);
@@ -241,8 +294,20 @@ VALUE native_slot_get(upb_fieldtype_t type,
241
294
  return DEREF(memory, int8_t) ? Qtrue : Qfalse;
242
295
  case UPB_TYPE_STRING:
243
296
  case UPB_TYPE_BYTES:
244
- case UPB_TYPE_MESSAGE:
245
297
  return DEREF(memory, VALUE);
298
+ case UPB_TYPE_MESSAGE: {
299
+ VALUE val = DEREF(memory, VALUE);
300
+
301
+ // Lazily expand wrapper type if necessary.
302
+ int type = TYPE(val);
303
+ if (type != T_DATA && type != T_NIL) {
304
+ // This must be a wrapper type.
305
+ val = ruby_wrapper_type(type_class, val);
306
+ DEREF(memory, VALUE) = val;
307
+ }
308
+
309
+ return val;
310
+ }
246
311
  case UPB_TYPE_ENUM: {
247
312
  int32_t val = DEREF(memory, int32_t);
248
313
  VALUE symbol = enum_lookup(type_class, INT2NUM(val));
@@ -319,7 +384,8 @@ void native_slot_dup(upb_fieldtype_t type, void* to, void* from) {
319
384
  memcpy(to, from, native_slot_size(type));
320
385
  }
321
386
 
322
- void native_slot_deep_copy(upb_fieldtype_t type, void* to, void* from) {
387
+ void native_slot_deep_copy(upb_fieldtype_t type, VALUE type_class, void* to,
388
+ void* from) {
323
389
  switch (type) {
324
390
  case UPB_TYPE_STRING:
325
391
  case UPB_TYPE_BYTES: {
@@ -329,7 +395,7 @@ void native_slot_deep_copy(upb_fieldtype_t type, void* to, void* from) {
329
395
  break;
330
396
  }
331
397
  case UPB_TYPE_MESSAGE: {
332
- VALUE from_val = DEREF(from, VALUE);
398
+ VALUE from_val = native_slot_get(type, type_class, from);
333
399
  DEREF(to, VALUE) = (from_val != Qnil) ?
334
400
  Message_deep_copy(from_val) : Qnil;
335
401
  break;
@@ -339,13 +405,14 @@ void native_slot_deep_copy(upb_fieldtype_t type, void* to, void* from) {
339
405
  }
340
406
  }
341
407
 
342
- bool native_slot_eq(upb_fieldtype_t type, void* mem1, void* mem2) {
408
+ bool native_slot_eq(upb_fieldtype_t type, VALUE type_class, void* mem1,
409
+ void* mem2) {
343
410
  switch (type) {
344
411
  case UPB_TYPE_STRING:
345
412
  case UPB_TYPE_BYTES:
346
413
  case UPB_TYPE_MESSAGE: {
347
- VALUE val1 = DEREF(mem1, VALUE);
348
- VALUE val2 = DEREF(mem2, VALUE);
414
+ VALUE val1 = native_slot_get(type, type_class, mem1);
415
+ VALUE val2 = native_slot_get(type, type_class, mem2);
349
416
  VALUE ret = rb_funcall(val1, rb_intern("=="), 1, val2);
350
417
  return ret == Qtrue;
351
418
  }
@@ -420,16 +487,32 @@ static size_t align_up_to(size_t offset, size_t granularity) {
420
487
  return (offset + granularity - 1) & ~(granularity - 1);
421
488
  }
422
489
 
423
- MessageLayout* create_layout(const upb_msgdef* msgdef) {
490
+ bool is_value_field(const upb_fielddef* f) {
491
+ return upb_fielddef_isseq(f) || upb_fielddef_issubmsg(f) ||
492
+ upb_fielddef_isstring(f);
493
+ }
494
+
495
+ void create_layout(Descriptor* desc) {
496
+ const upb_msgdef *msgdef = desc->msgdef;
424
497
  MessageLayout* layout = ALLOC(MessageLayout);
425
498
  int nfields = upb_msgdef_numfields(msgdef);
499
+ int noneofs = upb_msgdef_numoneofs(msgdef);
426
500
  upb_msg_field_iter it;
427
501
  upb_msg_oneof_iter oit;
428
502
  size_t off = 0;
503
+ size_t hasbit = 0;
504
+
505
+ layout->empty_template = NULL;
506
+ layout->desc = desc;
507
+ desc->layout = layout;
429
508
 
430
509
  layout->fields = ALLOC_N(MessageField, nfields);
510
+ layout->oneofs = NULL;
511
+
512
+ if (noneofs > 0) {
513
+ layout->oneofs = ALLOC_N(MessageOneof, noneofs);
514
+ }
431
515
 
432
- size_t hasbit = 0;
433
516
  for (upb_msg_field_begin(&it, msgdef);
434
517
  !upb_msg_field_done(&it);
435
518
  upb_msg_field_next(&it)) {
@@ -438,7 +521,7 @@ MessageLayout* create_layout(const upb_msgdef* msgdef) {
438
521
  layout->fields[upb_fielddef_index(field)].hasbit = hasbit++;
439
522
  } else {
440
523
  layout->fields[upb_fielddef_index(field)].hasbit =
441
- MESSAGE_FIELD_NO_HASBIT;
524
+ MESSAGE_FIELD_NO_HASBIT;
442
525
  }
443
526
  }
444
527
 
@@ -446,29 +529,76 @@ MessageLayout* create_layout(const upb_msgdef* msgdef) {
446
529
  off += (hasbit + 8 - 1) / 8;
447
530
  }
448
531
 
532
+ off = align_up_to(off, sizeof(VALUE));
533
+ layout->value_offset = off;
534
+ layout->repeated_count = 0;
535
+ layout->map_count = 0;
536
+ layout->value_count = 0;
537
+
538
+ // Place all VALUE fields for repeated fields.
539
+ for (upb_msg_field_begin(&it, msgdef);
540
+ !upb_msg_field_done(&it);
541
+ upb_msg_field_next(&it)) {
542
+ const upb_fielddef* field = upb_msg_iter_field(&it);
543
+ if (upb_fielddef_containingoneof(field) || !upb_fielddef_isseq(field) ||
544
+ upb_fielddef_ismap(field)) {
545
+ continue;
546
+ }
547
+
548
+ layout->fields[upb_fielddef_index(field)].offset = off;
549
+ off += sizeof(VALUE);
550
+ layout->repeated_count++;
551
+ }
552
+
553
+ // Place all VALUE fields for map fields.
554
+ for (upb_msg_field_begin(&it, msgdef);
555
+ !upb_msg_field_done(&it);
556
+ upb_msg_field_next(&it)) {
557
+ const upb_fielddef* field = upb_msg_iter_field(&it);
558
+ if (upb_fielddef_containingoneof(field) || !upb_fielddef_isseq(field) ||
559
+ !upb_fielddef_ismap(field)) {
560
+ continue;
561
+ }
562
+
563
+ layout->fields[upb_fielddef_index(field)].offset = off;
564
+ off += sizeof(VALUE);
565
+ layout->map_count++;
566
+ }
567
+
568
+ layout->value_count = layout->repeated_count + layout->map_count;
569
+
570
+ // Next place all other (non-oneof) VALUE fields.
571
+ for (upb_msg_field_begin(&it, msgdef);
572
+ !upb_msg_field_done(&it);
573
+ upb_msg_field_next(&it)) {
574
+ const upb_fielddef* field = upb_msg_iter_field(&it);
575
+ if (upb_fielddef_containingoneof(field) || !is_value_field(field) ||
576
+ upb_fielddef_isseq(field)) {
577
+ continue;
578
+ }
579
+
580
+ layout->fields[upb_fielddef_index(field)].offset = off;
581
+ off += sizeof(VALUE);
582
+ layout->value_count++;
583
+ }
584
+
585
+ // Now place all other (non-oneof) fields.
449
586
  for (upb_msg_field_begin(&it, msgdef);
450
587
  !upb_msg_field_done(&it);
451
588
  upb_msg_field_next(&it)) {
452
589
  const upb_fielddef* field = upb_msg_iter_field(&it);
453
590
  size_t field_size;
454
591
 
455
- if (upb_fielddef_containingoneof(field)) {
456
- // Oneofs are handled separately below.
592
+ if (upb_fielddef_containingoneof(field) || is_value_field(field)) {
457
593
  continue;
458
594
  }
459
595
 
460
596
  // Allocate |field_size| bytes for this field in the layout.
461
- field_size = 0;
462
- if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
463
- field_size = sizeof(VALUE);
464
- } else {
465
- field_size = native_slot_size(upb_fielddef_type(field));
466
- }
597
+ field_size = native_slot_size(upb_fielddef_type(field));
598
+
467
599
  // Align current offset up to |size| granularity.
468
600
  off = align_up_to(off, field_size);
469
601
  layout->fields[upb_fielddef_index(field)].offset = off;
470
- layout->fields[upb_fielddef_index(field)].case_offset =
471
- MESSAGE_FIELD_NO_CASE;
472
602
  off += field_size;
473
603
  }
474
604
 
@@ -502,6 +632,7 @@ MessageLayout* create_layout(const upb_msgdef* msgdef) {
502
632
  upb_oneof_next(&fit)) {
503
633
  const upb_fielddef* field = upb_oneof_iter_field(&fit);
504
634
  layout->fields[upb_fielddef_index(field)].offset = off;
635
+ layout->oneofs[upb_oneofdef_index(oneof)].offset = off;
505
636
  }
506
637
  off += field_size;
507
638
  }
@@ -511,44 +642,43 @@ MessageLayout* create_layout(const upb_msgdef* msgdef) {
511
642
  !upb_msg_oneof_done(&oit);
512
643
  upb_msg_oneof_next(&oit)) {
513
644
  const upb_oneofdef* oneof = upb_msg_iter_oneof(&oit);
514
- upb_oneof_iter fit;
515
-
516
645
  size_t field_size = sizeof(uint32_t);
517
646
  // Align the offset.
518
647
  off = (off + field_size - 1) & ~(field_size - 1);
519
- // Assign all fields in the oneof this same offset.
520
- for (upb_oneof_begin(&fit, oneof);
521
- !upb_oneof_done(&fit);
522
- upb_oneof_next(&fit)) {
523
- const upb_fielddef* field = upb_oneof_iter_field(&fit);
524
- layout->fields[upb_fielddef_index(field)].case_offset = off;
525
- }
648
+ layout->oneofs[upb_oneofdef_index(oneof)].case_offset = off;
526
649
  off += field_size;
527
650
  }
528
651
 
529
652
  layout->size = off;
530
-
531
653
  layout->msgdef = msgdef;
532
- upb_msgdef_ref(layout->msgdef, &layout->msgdef);
533
654
 
534
- return layout;
655
+ // Create the empty message template.
656
+ layout->empty_template = ALLOC_N(char, layout->size);
657
+ memset(layout->empty_template, 0, layout->size);
658
+
659
+ for (upb_msg_field_begin(&it, layout->msgdef);
660
+ !upb_msg_field_done(&it);
661
+ upb_msg_field_next(&it)) {
662
+ layout_clear(layout, layout->empty_template, upb_msg_iter_field(&it));
663
+ }
535
664
  }
536
665
 
537
666
  void free_layout(MessageLayout* layout) {
667
+ xfree(layout->empty_template);
538
668
  xfree(layout->fields);
539
- upb_msgdef_unref(layout->msgdef, &layout->msgdef);
669
+ xfree(layout->oneofs);
540
670
  xfree(layout);
541
671
  }
542
672
 
543
- VALUE field_type_class(const upb_fielddef* field) {
673
+ VALUE field_type_class(const MessageLayout* layout, const upb_fielddef* field) {
544
674
  VALUE type_class = Qnil;
545
675
  if (upb_fielddef_type(field) == UPB_TYPE_MESSAGE) {
546
- VALUE submsgdesc =
547
- get_def_obj(upb_fielddef_subdef(field));
676
+ VALUE submsgdesc = get_msgdef_obj(layout->desc->descriptor_pool,
677
+ upb_fielddef_msgsubdef(field));
548
678
  type_class = Descriptor_msgclass(submsgdesc);
549
679
  } else if (upb_fielddef_type(field) == UPB_TYPE_ENUM) {
550
- VALUE subenumdesc =
551
- get_def_obj(upb_fielddef_subdef(field));
680
+ VALUE subenumdesc = get_enumdef_obj(layout->desc->descriptor_pool,
681
+ upb_fielddef_enumsubdef(field));
552
682
  type_class = EnumDescriptor_enummodule(subenumdesc);
553
683
  }
554
684
  return type_class;
@@ -563,9 +693,15 @@ static void* slot_memory(MessageLayout* layout,
563
693
 
564
694
  static uint32_t* slot_oneof_case(MessageLayout* layout,
565
695
  const void* storage,
566
- const upb_fielddef* field) {
567
- return (uint32_t *)(((uint8_t *)storage) +
568
- layout->fields[upb_fielddef_index(field)].case_offset);
696
+ const upb_oneofdef* oneof) {
697
+ return (uint32_t*)(((uint8_t*)storage) +
698
+ layout->oneofs[upb_oneofdef_index(oneof)].case_offset);
699
+ }
700
+
701
+ uint32_t slot_read_oneof_case(MessageLayout* layout, const void* storage,
702
+ const upb_oneofdef* oneof) {
703
+ uint32_t* ptr = slot_oneof_case(layout, storage, oneof);
704
+ return *ptr & ~ONEOF_CASE_MASK;
569
705
  }
570
706
 
571
707
  static void slot_set_hasbit(MessageLayout* layout,
@@ -608,13 +744,14 @@ void layout_clear(MessageLayout* layout,
608
744
  const void* storage,
609
745
  const upb_fielddef* field) {
610
746
  void* memory = slot_memory(layout, storage, field);
611
- uint32_t* oneof_case = slot_oneof_case(layout, storage, field);
747
+ const upb_oneofdef* oneof = upb_fielddef_containingoneof(field);
612
748
 
613
749
  if (field_contains_hasbit(layout, field)) {
614
750
  slot_clear_hasbit(layout, storage, field);
615
751
  }
616
752
 
617
- if (upb_fielddef_containingoneof(field)) {
753
+ if (oneof) {
754
+ uint32_t* oneof_case = slot_oneof_case(layout, storage, oneof);
618
755
  memset(memory, 0, NATIVE_SLOT_MAX_SIZE);
619
756
  *oneof_case = ONEOF_CASE_NONE;
620
757
  } else if (is_map_field(field)) {
@@ -622,7 +759,7 @@ void layout_clear(MessageLayout* layout,
622
759
 
623
760
  const upb_fielddef* key_field = map_field_key(field);
624
761
  const upb_fielddef* value_field = map_field_value(field);
625
- VALUE type_class = field_type_class(value_field);
762
+ VALUE type_class = field_type_class(layout, value_field);
626
763
 
627
764
  if (type_class != Qnil) {
628
765
  VALUE args[3] = {
@@ -643,7 +780,7 @@ void layout_clear(MessageLayout* layout,
643
780
  } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
644
781
  VALUE ary = Qnil;
645
782
 
646
- VALUE type_class = field_type_class(field);
783
+ VALUE type_class = field_type_class(layout, field);
647
784
 
648
785
  if (type_class != Qnil) {
649
786
  VALUE args[2] = {
@@ -658,8 +795,9 @@ void layout_clear(MessageLayout* layout,
658
795
 
659
796
  DEREF(memory, VALUE) = ary;
660
797
  } else {
661
- native_slot_set(upb_fielddef_type(field), field_type_class(field),
662
- memory, layout_get_default(field));
798
+ native_slot_set(upb_fielddef_name(field), upb_fielddef_type(field),
799
+ field_type_class(layout, field), memory,
800
+ layout_get_default(field));
663
801
  }
664
802
  }
665
803
 
@@ -688,12 +826,8 @@ VALUE layout_get_default(const upb_fielddef *field) {
688
826
  case UPB_TYPE_BYTES: {
689
827
  size_t size;
690
828
  const char *str = upb_fielddef_defaultstr(field, &size);
691
- VALUE str_rb = rb_str_new(str, size);
692
-
693
- rb_enc_associate(str_rb, (upb_fielddef_type(field) == UPB_TYPE_BYTES) ?
694
- kRubyString8bitEncoding : kRubyStringUtf8Encoding);
695
- rb_obj_freeze(str_rb);
696
- return str_rb;
829
+ return get_frozen_string(str, size,
830
+ upb_fielddef_type(field) == UPB_TYPE_BYTES);
697
831
  }
698
832
  default: return Qnil;
699
833
  }
@@ -703,8 +837,7 @@ VALUE layout_get(MessageLayout* layout,
703
837
  const void* storage,
704
838
  const upb_fielddef* field) {
705
839
  void* memory = slot_memory(layout, storage, field);
706
- uint32_t* oneof_case = slot_oneof_case(layout, storage, field);
707
-
840
+ const upb_oneofdef* oneof = upb_fielddef_containingoneof(field);
708
841
  bool field_set;
709
842
  if (field_contains_hasbit(layout, field)) {
710
843
  field_set = slot_is_hasbit_set(layout, storage, field);
@@ -712,25 +845,25 @@ VALUE layout_get(MessageLayout* layout,
712
845
  field_set = true;
713
846
  }
714
847
 
715
- if (upb_fielddef_containingoneof(field)) {
716
- if (*oneof_case != upb_fielddef_number(field)) {
848
+ if (oneof) {
849
+ uint32_t oneof_case = slot_read_oneof_case(layout, storage, oneof);
850
+ if (oneof_case != upb_fielddef_number(field)) {
717
851
  return layout_get_default(field);
718
852
  }
719
853
  return native_slot_get(upb_fielddef_type(field),
720
- field_type_class(field),
721
- memory);
854
+ field_type_class(layout, field), memory);
722
855
  } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
723
856
  return *((VALUE *)memory);
724
857
  } else if (!field_set) {
725
858
  return layout_get_default(field);
726
859
  } else {
727
860
  return native_slot_get(upb_fielddef_type(field),
728
- field_type_class(field),
729
- memory);
861
+ field_type_class(layout, field), memory);
730
862
  }
731
863
  }
732
864
 
733
- static void check_repeated_field_type(VALUE val, const upb_fielddef* field) {
865
+ static void check_repeated_field_type(const MessageLayout* layout, VALUE val,
866
+ const upb_fielddef* field) {
734
867
  RepeatedField* self;
735
868
  assert(upb_fielddef_label(field) == UPB_LABEL_REPEATED);
736
869
 
@@ -744,25 +877,13 @@ static void check_repeated_field_type(VALUE val, const upb_fielddef* field) {
744
877
  rb_raise(cTypeError, "Repeated field array has wrong element type");
745
878
  }
746
879
 
747
- if (self->field_type == UPB_TYPE_MESSAGE) {
748
- if (self->field_type_class !=
749
- Descriptor_msgclass(get_def_obj(upb_fielddef_subdef(field)))) {
750
- rb_raise(cTypeError,
751
- "Repeated field array has wrong message class");
752
- }
753
- }
754
-
755
-
756
- if (self->field_type == UPB_TYPE_ENUM) {
757
- if (self->field_type_class !=
758
- EnumDescriptor_enummodule(get_def_obj(upb_fielddef_subdef(field)))) {
759
- rb_raise(cTypeError,
760
- "Repeated field array has wrong enum class");
761
- }
880
+ if (self->field_type_class != field_type_class(layout, field)) {
881
+ rb_raise(cTypeError, "Repeated field array has wrong message/enum class");
762
882
  }
763
883
  }
764
884
 
765
- static void check_map_field_type(VALUE val, const upb_fielddef* field) {
885
+ static void check_map_field_type(const MessageLayout* layout, VALUE val,
886
+ const upb_fielddef* field) {
766
887
  const upb_fielddef* key_field = map_field_key(field);
767
888
  const upb_fielddef* value_field = map_field_value(field);
768
889
  Map* self;
@@ -779,25 +900,20 @@ static void check_map_field_type(VALUE val, const upb_fielddef* field) {
779
900
  if (self->value_type != upb_fielddef_type(value_field)) {
780
901
  rb_raise(cTypeError, "Map value type does not match field's value type");
781
902
  }
782
- if (upb_fielddef_type(value_field) == UPB_TYPE_MESSAGE ||
783
- upb_fielddef_type(value_field) == UPB_TYPE_ENUM) {
784
- if (self->value_type_class !=
785
- get_def_obj(upb_fielddef_subdef(value_field))) {
786
- rb_raise(cTypeError,
787
- "Map value type has wrong message/enum class");
788
- }
903
+ if (self->value_type_class != field_type_class(layout, value_field)) {
904
+ rb_raise(cTypeError, "Map value type has wrong message/enum class");
789
905
  }
790
906
  }
791
907
 
792
-
793
908
  void layout_set(MessageLayout* layout,
794
909
  void* storage,
795
910
  const upb_fielddef* field,
796
911
  VALUE val) {
797
912
  void* memory = slot_memory(layout, storage, field);
798
- uint32_t* oneof_case = slot_oneof_case(layout, storage, field);
913
+ const upb_oneofdef* oneof = upb_fielddef_containingoneof(field);
799
914
 
800
- if (upb_fielddef_containingoneof(field)) {
915
+ if (oneof) {
916
+ uint32_t* oneof_case = slot_oneof_case(layout, storage, oneof);
801
917
  if (val == Qnil) {
802
918
  // Assigning nil to a oneof field clears the oneof completely.
803
919
  *oneof_case = ONEOF_CASE_NONE;
@@ -815,20 +931,24 @@ void layout_set(MessageLayout* layout,
815
931
  // sync with the value slot whenever the Ruby VM has been called. Thus, we
816
932
  // use native_slot_set_value_and_case(), which ensures that both the value
817
933
  // and case number are altered atomically (w.r.t. the Ruby VM).
934
+ uint32_t case_value = upb_fielddef_number(field);
935
+ if (upb_fielddef_issubmsg(field) || upb_fielddef_isstring(field)) {
936
+ case_value |= ONEOF_CASE_MASK;
937
+ }
938
+
818
939
  native_slot_set_value_and_case(
819
- upb_fielddef_type(field), field_type_class(field),
820
- memory, val,
821
- oneof_case, upb_fielddef_number(field));
940
+ upb_fielddef_name(field), upb_fielddef_type(field),
941
+ field_type_class(layout, field), memory, val, oneof_case, case_value);
822
942
  }
823
943
  } else if (is_map_field(field)) {
824
- check_map_field_type(val, field);
944
+ check_map_field_type(layout, val, field);
825
945
  DEREF(memory, VALUE) = val;
826
946
  } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
827
- check_repeated_field_type(val, field);
947
+ check_repeated_field_type(layout, val, field);
828
948
  DEREF(memory, VALUE) = val;
829
949
  } else {
830
- native_slot_set(upb_fielddef_type(field), field_type_class(field), memory,
831
- val);
950
+ native_slot_set(upb_fielddef_name(field), upb_fielddef_type(field),
951
+ field_type_class(layout, field), memory, val);
832
952
  }
833
953
 
834
954
  if (layout->fields[upb_fielddef_index(field)].hasbit !=
@@ -837,34 +957,33 @@ void layout_set(MessageLayout* layout,
837
957
  }
838
958
  }
839
959
 
840
- void layout_init(MessageLayout* layout,
841
- void* storage) {
960
+ void layout_init(MessageLayout* layout, void* storage) {
961
+ VALUE* value = (VALUE*)CHARPTR_AT(storage, layout->value_offset);
962
+ int i;
842
963
 
843
- upb_msg_field_iter it;
844
- for (upb_msg_field_begin(&it, layout->msgdef);
845
- !upb_msg_field_done(&it);
846
- upb_msg_field_next(&it)) {
847
- layout_clear(layout, storage, upb_msg_iter_field(&it));
964
+ for (i = 0; i < layout->repeated_count; i++, value++) {
965
+ *value = RepeatedField_new_this_type(*value);
966
+ }
967
+
968
+ for (i = 0; i < layout->map_count; i++, value++) {
969
+ *value = Map_new_this_type(*value);
848
970
  }
849
971
  }
850
972
 
851
973
  void layout_mark(MessageLayout* layout, void* storage) {
852
- upb_msg_field_iter it;
853
- for (upb_msg_field_begin(&it, layout->msgdef);
854
- !upb_msg_field_done(&it);
855
- upb_msg_field_next(&it)) {
856
- const upb_fielddef* field = upb_msg_iter_field(&it);
857
- void* memory = slot_memory(layout, storage, field);
858
- uint32_t* oneof_case = slot_oneof_case(layout, storage, field);
974
+ VALUE* values = (VALUE*)CHARPTR_AT(storage, layout->value_offset);
975
+ int noneofs = upb_msgdef_numoneofs(layout->msgdef);
976
+ int i;
859
977
 
860
- if (upb_fielddef_containingoneof(field)) {
861
- if (*oneof_case == upb_fielddef_number(field)) {
862
- native_slot_mark(upb_fielddef_type(field), memory);
863
- }
864
- } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
865
- rb_gc_mark(DEREF(memory, VALUE));
866
- } else {
867
- native_slot_mark(upb_fielddef_type(field), memory);
978
+ for (i = 0; i < layout->value_count; i++) {
979
+ rb_gc_mark(values[i]);
980
+ }
981
+
982
+ for (i = 0; i < noneofs; i++) {
983
+ MessageOneof* oneof = &layout->oneofs[i];
984
+ uint32_t* case_ptr = (uint32_t*)CHARPTR_AT(storage, oneof->case_offset);
985
+ if (*case_ptr & ONEOF_CASE_MASK) {
986
+ rb_gc_mark(DEREF_OFFSET(storage, oneof->offset, VALUE));
868
987
  }
869
988
  }
870
989
  }
@@ -875,14 +994,16 @@ void layout_dup(MessageLayout* layout, void* to, void* from) {
875
994
  !upb_msg_field_done(&it);
876
995
  upb_msg_field_next(&it)) {
877
996
  const upb_fielddef* field = upb_msg_iter_field(&it);
997
+ const upb_oneofdef* oneof = upb_fielddef_containingoneof(field);
878
998
 
879
999
  void* to_memory = slot_memory(layout, to, field);
880
- uint32_t* to_oneof_case = slot_oneof_case(layout, to, field);
881
1000
  void* from_memory = slot_memory(layout, from, field);
882
- uint32_t* from_oneof_case = slot_oneof_case(layout, from, field);
883
1001
 
884
- if (upb_fielddef_containingoneof(field)) {
885
- if (*from_oneof_case == upb_fielddef_number(field)) {
1002
+ if (oneof) {
1003
+ uint32_t* to_oneof_case = slot_oneof_case(layout, to, oneof);
1004
+ uint32_t* from_oneof_case = slot_oneof_case(layout, from, oneof);
1005
+ if (slot_read_oneof_case(layout, from, oneof) ==
1006
+ upb_fielddef_number(field)) {
886
1007
  *to_oneof_case = *from_oneof_case;
887
1008
  native_slot_dup(upb_fielddef_type(field), to_memory, from_memory);
888
1009
  }
@@ -907,16 +1028,20 @@ void layout_deep_copy(MessageLayout* layout, void* to, void* from) {
907
1028
  !upb_msg_field_done(&it);
908
1029
  upb_msg_field_next(&it)) {
909
1030
  const upb_fielddef* field = upb_msg_iter_field(&it);
1031
+ const upb_oneofdef* oneof = upb_fielddef_containingoneof(field);
910
1032
 
911
1033
  void* to_memory = slot_memory(layout, to, field);
912
- uint32_t* to_oneof_case = slot_oneof_case(layout, to, field);
913
1034
  void* from_memory = slot_memory(layout, from, field);
914
- uint32_t* from_oneof_case = slot_oneof_case(layout, from, field);
915
1035
 
916
- if (upb_fielddef_containingoneof(field)) {
917
- if (*from_oneof_case == upb_fielddef_number(field)) {
1036
+ if (oneof) {
1037
+ uint32_t* to_oneof_case = slot_oneof_case(layout, to, oneof);
1038
+ uint32_t* from_oneof_case = slot_oneof_case(layout, from, oneof);
1039
+ if (slot_read_oneof_case(layout, from, oneof) ==
1040
+ upb_fielddef_number(field)) {
918
1041
  *to_oneof_case = *from_oneof_case;
919
- native_slot_deep_copy(upb_fielddef_type(field), to_memory, from_memory);
1042
+ native_slot_deep_copy(upb_fielddef_type(field),
1043
+ field_type_class(layout, field), to_memory,
1044
+ from_memory);
920
1045
  }
921
1046
  } else if (is_map_field(field)) {
922
1047
  DEREF(to_memory, VALUE) =
@@ -930,7 +1055,9 @@ void layout_deep_copy(MessageLayout* layout, void* to, void* from) {
930
1055
  slot_set_hasbit(layout, to, field);
931
1056
  }
932
1057
 
933
- native_slot_deep_copy(upb_fielddef_type(field), to_memory, from_memory);
1058
+ native_slot_deep_copy(upb_fielddef_type(field),
1059
+ field_type_class(layout, field), to_memory,
1060
+ from_memory);
934
1061
  }
935
1062
  }
936
1063
  }
@@ -941,17 +1068,19 @@ VALUE layout_eq(MessageLayout* layout, void* msg1, void* msg2) {
941
1068
  !upb_msg_field_done(&it);
942
1069
  upb_msg_field_next(&it)) {
943
1070
  const upb_fielddef* field = upb_msg_iter_field(&it);
1071
+ const upb_oneofdef* oneof = upb_fielddef_containingoneof(field);
944
1072
 
945
1073
  void* msg1_memory = slot_memory(layout, msg1, field);
946
- uint32_t* msg1_oneof_case = slot_oneof_case(layout, msg1, field);
947
1074
  void* msg2_memory = slot_memory(layout, msg2, field);
948
- uint32_t* msg2_oneof_case = slot_oneof_case(layout, msg2, field);
949
1075
 
950
- if (upb_fielddef_containingoneof(field)) {
1076
+ if (oneof) {
1077
+ uint32_t* msg1_oneof_case = slot_oneof_case(layout, msg1, oneof);
1078
+ uint32_t* msg2_oneof_case = slot_oneof_case(layout, msg2, oneof);
951
1079
  if (*msg1_oneof_case != *msg2_oneof_case ||
952
- (*msg1_oneof_case == upb_fielddef_number(field) &&
1080
+ (slot_read_oneof_case(layout, msg1, oneof) ==
1081
+ upb_fielddef_number(field) &&
953
1082
  !native_slot_eq(upb_fielddef_type(field),
954
- msg1_memory,
1083
+ field_type_class(layout, field), msg1_memory,
955
1084
  msg2_memory))) {
956
1085
  return Qfalse;
957
1086
  }
@@ -967,9 +1096,10 @@ VALUE layout_eq(MessageLayout* layout, void* msg1, void* msg2) {
967
1096
  }
968
1097
  } else {
969
1098
  if (slot_is_hasbit_set(layout, msg1, field) !=
970
- slot_is_hasbit_set(layout, msg2, field) ||
1099
+ slot_is_hasbit_set(layout, msg2, field) ||
971
1100
  !native_slot_eq(upb_fielddef_type(field),
972
- msg1_memory, msg2_memory)) {
1101
+ field_type_class(layout, field), msg1_memory,
1102
+ msg2_memory)) {
973
1103
  return Qfalse;
974
1104
  }
975
1105
  }