google-protobuf 3.8.0 → 3.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of google-protobuf might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/ext/google/protobuf_c/defs.c +942 -833
- data/ext/google/protobuf_c/encode_decode.c +482 -301
- data/ext/google/protobuf_c/extconf.rb +2 -4
- data/ext/google/protobuf_c/map.c +39 -58
- data/ext/google/protobuf_c/message.c +124 -114
- data/ext/google/protobuf_c/protobuf.c +30 -15
- data/ext/google/protobuf_c/protobuf.h +109 -57
- data/ext/google/protobuf_c/repeated_field.c +47 -21
- data/ext/google/protobuf_c/storage.c +305 -169
- data/ext/google/protobuf_c/upb.c +5335 -8998
- data/ext/google/protobuf_c/upb.h +4634 -8498
- data/lib/google/protobuf.rb +70 -0
- data/lib/google/protobuf/any_pb.rb +1 -1
- data/lib/google/protobuf/api_pb.rb +3 -3
- data/lib/google/protobuf/duration_pb.rb +1 -1
- data/lib/google/protobuf/empty_pb.rb +1 -1
- data/lib/google/protobuf/field_mask_pb.rb +1 -1
- data/lib/google/protobuf/source_context_pb.rb +1 -1
- data/lib/google/protobuf/struct_pb.rb +4 -4
- data/lib/google/protobuf/timestamp_pb.rb +1 -1
- data/lib/google/protobuf/type_pb.rb +8 -8
- data/lib/google/protobuf/well_known_types.rb +8 -2
- data/lib/google/protobuf/wrappers_pb.rb +9 -9
- data/tests/basic.rb +229 -67
- data/tests/generated_code_test.rb +0 -0
- data/tests/stress.rb +0 -0
- metadata +17 -10
@@ -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
|
-
|
100
|
-
|
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
|
-
|
103
|
-
|
104
|
-
|
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
|
-
|
108
|
-
|
109
|
-
|
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 =
|
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"),
|
190
|
-
|
191
|
-
|
192
|
-
|
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"),
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
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 ==
|
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,
|
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 =
|
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,
|
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 =
|
388
|
-
VALUE val2 =
|
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
|
-
|
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
|
-
|
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 (
|
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 =
|
502
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
607
|
-
return (uint32_t
|
608
|
-
|
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
|
-
|
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
|
-
|
644
|
-
|
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
|
-
|
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 (
|
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
|
-
|
703
|
-
|
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
|
-
|
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
|
-
|
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 (
|
757
|
-
|
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(
|
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->
|
789
|
-
|
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(
|
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 (
|
824
|
-
|
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
|
-
|
946
|
+
const upb_oneofdef* oneof = upb_fielddef_realcontainingoneof(field);
|
840
947
|
|
841
|
-
if (
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
1002
|
+
void layout_init(MessageLayout* layout, void* storage) {
|
1003
|
+
VALUE* value = (VALUE*)CHARPTR_AT(storage, layout->value_offset);
|
1004
|
+
int i;
|
885
1005
|
|
886
|
-
|
887
|
-
|
888
|
-
|
889
|
-
|
890
|
-
|
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
|
-
|
896
|
-
|
897
|
-
|
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
|
-
|
904
|
-
|
905
|
-
|
906
|
-
|
907
|
-
|
908
|
-
|
909
|
-
|
910
|
-
|
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 (
|
928
|
-
|
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 (
|
960
|
-
|
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),
|
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),
|
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 (
|
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
|
-
(
|
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 (
|
1013
|
-
|
1014
|
-
|
1015
|
-
|
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
|
}
|