google-protobuf 3.7.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 +521 -300
- data/ext/google/protobuf_c/extconf.rb +2 -4
- data/ext/google/protobuf_c/map.c +41 -54
- data/ext/google/protobuf_c/message.c +212 -86
- data/ext/google/protobuf_c/protobuf.c +30 -15
- data/ext/google/protobuf_c/protobuf.h +114 -60
- data/ext/google/protobuf_c/repeated_field.c +55 -23
- data/ext/google/protobuf_c/storage.c +350 -171
- data/ext/google/protobuf_c/upb.c +5630 -9131
- data/ext/google/protobuf_c/upb.h +4590 -7568
- 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/lib/google/protobuf.rb +70 -0
- data/tests/basic.rb +250 -68
- data/tests/generated_code_test.rb +0 -0
- data/tests/stress.rb +0 -0
- metadata +18 -12
@@ -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
|
-
|
97
|
-
|
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
|
-
|
100
|
-
|
101
|
-
|
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
|
-
|
105
|
-
|
106
|
-
|
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(
|
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(
|
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
|
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
|
-
|
172
|
-
|
173
|
-
|
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,
|
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 =
|
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,
|
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 =
|
348
|
-
VALUE val2 =
|
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,25 +487,55 @@ 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
|
-
|
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_numrealoneofs(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
|
+
int i;
|
505
|
+
|
506
|
+
(void)i;
|
507
|
+
|
508
|
+
layout->empty_template = NULL;
|
509
|
+
layout->desc = desc;
|
510
|
+
desc->layout = layout;
|
429
511
|
|
430
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
|
431
528
|
|
432
|
-
size_t hasbit = 0;
|
433
529
|
for (upb_msg_field_begin(&it, msgdef);
|
434
530
|
!upb_msg_field_done(&it);
|
435
531
|
upb_msg_field_next(&it)) {
|
436
532
|
const upb_fielddef* field = upb_msg_iter_field(&it);
|
437
|
-
if (upb_fielddef_haspresence(field)
|
533
|
+
if (upb_fielddef_haspresence(field) &&
|
534
|
+
!upb_fielddef_realcontainingoneof(field)) {
|
438
535
|
layout->fields[upb_fielddef_index(field)].hasbit = hasbit++;
|
439
536
|
} else {
|
440
537
|
layout->fields[upb_fielddef_index(field)].hasbit =
|
441
|
-
|
538
|
+
MESSAGE_FIELD_NO_HASBIT;
|
442
539
|
}
|
443
540
|
}
|
444
541
|
|
@@ -446,29 +543,76 @@ MessageLayout* create_layout(const upb_msgdef* msgdef) {
|
|
446
543
|
off += (hasbit + 8 - 1) / 8;
|
447
544
|
}
|
448
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.
|
449
600
|
for (upb_msg_field_begin(&it, msgdef);
|
450
601
|
!upb_msg_field_done(&it);
|
451
602
|
upb_msg_field_next(&it)) {
|
452
603
|
const upb_fielddef* field = upb_msg_iter_field(&it);
|
453
604
|
size_t field_size;
|
454
605
|
|
455
|
-
if (
|
456
|
-
// Oneofs are handled separately below.
|
606
|
+
if (upb_fielddef_realcontainingoneof(field) || is_value_field(field)) {
|
457
607
|
continue;
|
458
608
|
}
|
459
609
|
|
460
610
|
// Allocate |field_size| bytes for this field in the layout.
|
461
|
-
field_size =
|
462
|
-
|
463
|
-
field_size = sizeof(VALUE);
|
464
|
-
} else {
|
465
|
-
field_size = native_slot_size(upb_fielddef_type(field));
|
466
|
-
}
|
611
|
+
field_size = native_slot_size(upb_fielddef_type(field));
|
612
|
+
|
467
613
|
// Align current offset up to |size| granularity.
|
468
614
|
off = align_up_to(off, field_size);
|
469
615
|
layout->fields[upb_fielddef_index(field)].offset = off;
|
470
|
-
layout->fields[upb_fielddef_index(field)].case_offset =
|
471
|
-
MESSAGE_FIELD_NO_CASE;
|
472
616
|
off += field_size;
|
473
617
|
}
|
474
618
|
|
@@ -494,6 +638,10 @@ MessageLayout* create_layout(const upb_msgdef* msgdef) {
|
|
494
638
|
// Always allocate NATIVE_SLOT_MAX_SIZE bytes, but share the slot between
|
495
639
|
// all fields.
|
496
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
|
+
|
497
645
|
// Align the offset.
|
498
646
|
off = align_up_to(off, field_size);
|
499
647
|
// Assign all fields in the oneof this same offset.
|
@@ -502,6 +650,7 @@ MessageLayout* create_layout(const upb_msgdef* msgdef) {
|
|
502
650
|
upb_oneof_next(&fit)) {
|
503
651
|
const upb_fielddef* field = upb_oneof_iter_field(&fit);
|
504
652
|
layout->fields[upb_fielddef_index(field)].offset = off;
|
653
|
+
layout->oneofs[upb_oneofdef_index(oneof)].offset = off;
|
505
654
|
}
|
506
655
|
off += field_size;
|
507
656
|
}
|
@@ -511,44 +660,55 @@ MessageLayout* create_layout(const upb_msgdef* msgdef) {
|
|
511
660
|
!upb_msg_oneof_done(&oit);
|
512
661
|
upb_msg_oneof_next(&oit)) {
|
513
662
|
const upb_oneofdef* oneof = upb_msg_iter_oneof(&oit);
|
514
|
-
upb_oneof_iter fit;
|
515
|
-
|
516
663
|
size_t field_size = sizeof(uint32_t);
|
664
|
+
if (upb_oneofdef_issynthetic(oneof)) continue;
|
665
|
+
assert(upb_oneofdef_index(oneof) < noneofs);
|
517
666
|
// Align the offset.
|
518
667
|
off = (off + field_size - 1) & ~(field_size - 1);
|
519
|
-
|
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
|
-
}
|
668
|
+
layout->oneofs[upb_oneofdef_index(oneof)].case_offset = off;
|
526
669
|
off += field_size;
|
527
670
|
}
|
528
671
|
|
529
672
|
layout->size = off;
|
530
|
-
|
531
673
|
layout->msgdef = msgdef;
|
532
|
-
upb_msgdef_ref(layout->msgdef, &layout->msgdef);
|
533
674
|
|
534
|
-
|
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
|
+
}
|
535
694
|
}
|
536
695
|
|
537
696
|
void free_layout(MessageLayout* layout) {
|
697
|
+
xfree(layout->empty_template);
|
538
698
|
xfree(layout->fields);
|
539
|
-
|
699
|
+
xfree(layout->oneofs);
|
540
700
|
xfree(layout);
|
541
701
|
}
|
542
702
|
|
543
|
-
VALUE field_type_class(const upb_fielddef* field) {
|
703
|
+
VALUE field_type_class(const MessageLayout* layout, const upb_fielddef* field) {
|
544
704
|
VALUE type_class = Qnil;
|
545
705
|
if (upb_fielddef_type(field) == UPB_TYPE_MESSAGE) {
|
546
|
-
VALUE submsgdesc =
|
547
|
-
|
706
|
+
VALUE submsgdesc = get_msgdef_obj(layout->desc->descriptor_pool,
|
707
|
+
upb_fielddef_msgsubdef(field));
|
548
708
|
type_class = Descriptor_msgclass(submsgdesc);
|
549
709
|
} else if (upb_fielddef_type(field) == UPB_TYPE_ENUM) {
|
550
|
-
VALUE subenumdesc =
|
551
|
-
|
710
|
+
VALUE subenumdesc = get_enumdef_obj(layout->desc->descriptor_pool,
|
711
|
+
upb_fielddef_enumsubdef(field));
|
552
712
|
type_class = EnumDescriptor_enummodule(subenumdesc);
|
553
713
|
}
|
554
714
|
return type_class;
|
@@ -563,9 +723,15 @@ static void* slot_memory(MessageLayout* layout,
|
|
563
723
|
|
564
724
|
static uint32_t* slot_oneof_case(MessageLayout* layout,
|
565
725
|
const void* storage,
|
566
|
-
const
|
567
|
-
return (uint32_t
|
568
|
-
|
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;
|
569
735
|
}
|
570
736
|
|
571
737
|
static void slot_set_hasbit(MessageLayout* layout,
|
@@ -589,10 +755,7 @@ static bool slot_is_hasbit_set(MessageLayout* layout,
|
|
589
755
|
const void* storage,
|
590
756
|
const upb_fielddef* field) {
|
591
757
|
size_t hasbit = layout->fields[upb_fielddef_index(field)].hasbit;
|
592
|
-
|
593
|
-
return false;
|
594
|
-
}
|
595
|
-
|
758
|
+
assert(field_contains_hasbit(layout, field));
|
596
759
|
return DEREF_OFFSET(
|
597
760
|
(uint8_t*)storage, hasbit / 8, char) & (1 << (hasbit % 8));
|
598
761
|
}
|
@@ -600,21 +763,28 @@ static bool slot_is_hasbit_set(MessageLayout* layout,
|
|
600
763
|
VALUE layout_has(MessageLayout* layout,
|
601
764
|
const void* storage,
|
602
765
|
const upb_fielddef* field) {
|
603
|
-
|
604
|
-
|
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
|
+
}
|
605
774
|
}
|
606
775
|
|
607
776
|
void layout_clear(MessageLayout* layout,
|
608
777
|
const void* storage,
|
609
778
|
const upb_fielddef* field) {
|
610
779
|
void* memory = slot_memory(layout, storage, field);
|
611
|
-
|
780
|
+
const upb_oneofdef* oneof = upb_fielddef_realcontainingoneof(field);
|
612
781
|
|
613
782
|
if (field_contains_hasbit(layout, field)) {
|
614
783
|
slot_clear_hasbit(layout, storage, field);
|
615
784
|
}
|
616
785
|
|
617
|
-
if (
|
786
|
+
if (oneof) {
|
787
|
+
uint32_t* oneof_case = slot_oneof_case(layout, storage, oneof);
|
618
788
|
memset(memory, 0, NATIVE_SLOT_MAX_SIZE);
|
619
789
|
*oneof_case = ONEOF_CASE_NONE;
|
620
790
|
} else if (is_map_field(field)) {
|
@@ -622,7 +792,7 @@ void layout_clear(MessageLayout* layout,
|
|
622
792
|
|
623
793
|
const upb_fielddef* key_field = map_field_key(field);
|
624
794
|
const upb_fielddef* value_field = map_field_value(field);
|
625
|
-
VALUE type_class = field_type_class(value_field);
|
795
|
+
VALUE type_class = field_type_class(layout, value_field);
|
626
796
|
|
627
797
|
if (type_class != Qnil) {
|
628
798
|
VALUE args[3] = {
|
@@ -643,7 +813,7 @@ void layout_clear(MessageLayout* layout,
|
|
643
813
|
} else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
|
644
814
|
VALUE ary = Qnil;
|
645
815
|
|
646
|
-
VALUE type_class = field_type_class(field);
|
816
|
+
VALUE type_class = field_type_class(layout, field);
|
647
817
|
|
648
818
|
if (type_class != Qnil) {
|
649
819
|
VALUE args[2] = {
|
@@ -658,8 +828,9 @@ void layout_clear(MessageLayout* layout,
|
|
658
828
|
|
659
829
|
DEREF(memory, VALUE) = ary;
|
660
830
|
} else {
|
661
|
-
native_slot_set(
|
662
|
-
|
831
|
+
native_slot_set(upb_fielddef_name(field), upb_fielddef_type(field),
|
832
|
+
field_type_class(layout, field), memory,
|
833
|
+
layout_get_default(field));
|
663
834
|
}
|
664
835
|
}
|
665
836
|
|
@@ -688,12 +859,8 @@ VALUE layout_get_default(const upb_fielddef *field) {
|
|
688
859
|
case UPB_TYPE_BYTES: {
|
689
860
|
size_t size;
|
690
861
|
const char *str = upb_fielddef_defaultstr(field, &size);
|
691
|
-
|
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;
|
862
|
+
return get_frozen_string(str, size,
|
863
|
+
upb_fielddef_type(field) == UPB_TYPE_BYTES);
|
697
864
|
}
|
698
865
|
default: return Qnil;
|
699
866
|
}
|
@@ -703,8 +870,7 @@ VALUE layout_get(MessageLayout* layout,
|
|
703
870
|
const void* storage,
|
704
871
|
const upb_fielddef* field) {
|
705
872
|
void* memory = slot_memory(layout, storage, field);
|
706
|
-
|
707
|
-
|
873
|
+
const upb_oneofdef* oneof = upb_fielddef_realcontainingoneof(field);
|
708
874
|
bool field_set;
|
709
875
|
if (field_contains_hasbit(layout, field)) {
|
710
876
|
field_set = slot_is_hasbit_set(layout, storage, field);
|
@@ -712,25 +878,25 @@ VALUE layout_get(MessageLayout* layout,
|
|
712
878
|
field_set = true;
|
713
879
|
}
|
714
880
|
|
715
|
-
if (
|
716
|
-
|
881
|
+
if (oneof) {
|
882
|
+
uint32_t oneof_case = slot_read_oneof_case(layout, storage, oneof);
|
883
|
+
if (oneof_case != upb_fielddef_number(field)) {
|
717
884
|
return layout_get_default(field);
|
718
885
|
}
|
719
886
|
return native_slot_get(upb_fielddef_type(field),
|
720
|
-
field_type_class(field),
|
721
|
-
memory);
|
887
|
+
field_type_class(layout, field), memory);
|
722
888
|
} else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
|
723
889
|
return *((VALUE *)memory);
|
724
890
|
} else if (!field_set) {
|
725
891
|
return layout_get_default(field);
|
726
892
|
} else {
|
727
893
|
return native_slot_get(upb_fielddef_type(field),
|
728
|
-
field_type_class(field),
|
729
|
-
memory);
|
894
|
+
field_type_class(layout, field), memory);
|
730
895
|
}
|
731
896
|
}
|
732
897
|
|
733
|
-
static void check_repeated_field_type(
|
898
|
+
static void check_repeated_field_type(const MessageLayout* layout, VALUE val,
|
899
|
+
const upb_fielddef* field) {
|
734
900
|
RepeatedField* self;
|
735
901
|
assert(upb_fielddef_label(field) == UPB_LABEL_REPEATED);
|
736
902
|
|
@@ -744,25 +910,13 @@ static void check_repeated_field_type(VALUE val, const upb_fielddef* field) {
|
|
744
910
|
rb_raise(cTypeError, "Repeated field array has wrong element type");
|
745
911
|
}
|
746
912
|
|
747
|
-
if (self->
|
748
|
-
|
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
|
-
}
|
913
|
+
if (self->field_type_class != field_type_class(layout, field)) {
|
914
|
+
rb_raise(cTypeError, "Repeated field array has wrong message/enum class");
|
762
915
|
}
|
763
916
|
}
|
764
917
|
|
765
|
-
static void check_map_field_type(
|
918
|
+
static void check_map_field_type(const MessageLayout* layout, VALUE val,
|
919
|
+
const upb_fielddef* field) {
|
766
920
|
const upb_fielddef* key_field = map_field_key(field);
|
767
921
|
const upb_fielddef* value_field = map_field_value(field);
|
768
922
|
Map* self;
|
@@ -779,25 +933,20 @@ static void check_map_field_type(VALUE val, const upb_fielddef* field) {
|
|
779
933
|
if (self->value_type != upb_fielddef_type(value_field)) {
|
780
934
|
rb_raise(cTypeError, "Map value type does not match field's value type");
|
781
935
|
}
|
782
|
-
if (
|
783
|
-
|
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
|
-
}
|
936
|
+
if (self->value_type_class != field_type_class(layout, value_field)) {
|
937
|
+
rb_raise(cTypeError, "Map value type has wrong message/enum class");
|
789
938
|
}
|
790
939
|
}
|
791
940
|
|
792
|
-
|
793
941
|
void layout_set(MessageLayout* layout,
|
794
942
|
void* storage,
|
795
943
|
const upb_fielddef* field,
|
796
944
|
VALUE val) {
|
797
945
|
void* memory = slot_memory(layout, storage, field);
|
798
|
-
|
946
|
+
const upb_oneofdef* oneof = upb_fielddef_realcontainingoneof(field);
|
799
947
|
|
800
|
-
if (
|
948
|
+
if (oneof) {
|
949
|
+
uint32_t* oneof_case = slot_oneof_case(layout, storage, oneof);
|
801
950
|
if (val == Qnil) {
|
802
951
|
// Assigning nil to a oneof field clears the oneof completely.
|
803
952
|
*oneof_case = ONEOF_CASE_NONE;
|
@@ -815,56 +964,68 @@ void layout_set(MessageLayout* layout,
|
|
815
964
|
// sync with the value slot whenever the Ruby VM has been called. Thus, we
|
816
965
|
// use native_slot_set_value_and_case(), which ensures that both the value
|
817
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
|
+
|
818
972
|
native_slot_set_value_and_case(
|
819
|
-
|
820
|
-
memory, val,
|
821
|
-
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);
|
822
975
|
}
|
823
976
|
} else if (is_map_field(field)) {
|
824
|
-
check_map_field_type(val, field);
|
977
|
+
check_map_field_type(layout, val, field);
|
825
978
|
DEREF(memory, VALUE) = val;
|
826
979
|
} else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
|
827
|
-
check_repeated_field_type(val, field);
|
980
|
+
check_repeated_field_type(layout, val, field);
|
828
981
|
DEREF(memory, VALUE) = val;
|
829
982
|
} else {
|
830
|
-
native_slot_set(
|
831
|
-
|
983
|
+
native_slot_set(upb_fielddef_name(field), upb_fielddef_type(field),
|
984
|
+
field_type_class(layout, field), memory, val);
|
832
985
|
}
|
833
986
|
|
834
987
|
if (layout->fields[upb_fielddef_index(field)].hasbit !=
|
835
988
|
MESSAGE_FIELD_NO_HASBIT) {
|
836
|
-
|
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
|
+
}
|
837
999
|
}
|
838
1000
|
}
|
839
1001
|
|
840
|
-
void layout_init(MessageLayout* layout,
|
841
|
-
|
1002
|
+
void layout_init(MessageLayout* layout, void* storage) {
|
1003
|
+
VALUE* value = (VALUE*)CHARPTR_AT(storage, layout->value_offset);
|
1004
|
+
int i;
|
842
1005
|
|
843
|
-
|
844
|
-
|
845
|
-
|
846
|
-
|
847
|
-
|
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);
|
848
1012
|
}
|
849
1013
|
}
|
850
1014
|
|
851
1015
|
void layout_mark(MessageLayout* layout, void* storage) {
|
852
|
-
|
853
|
-
|
854
|
-
|
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);
|
1016
|
+
VALUE* values = (VALUE*)CHARPTR_AT(storage, layout->value_offset);
|
1017
|
+
int noneofs = upb_msgdef_numrealoneofs(layout->msgdef);
|
1018
|
+
int i;
|
859
1019
|
|
860
|
-
|
861
|
-
|
862
|
-
|
863
|
-
|
864
|
-
|
865
|
-
|
866
|
-
|
867
|
-
|
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));
|
868
1029
|
}
|
869
1030
|
}
|
870
1031
|
}
|
@@ -875,14 +1036,16 @@ void layout_dup(MessageLayout* layout, void* to, void* from) {
|
|
875
1036
|
!upb_msg_field_done(&it);
|
876
1037
|
upb_msg_field_next(&it)) {
|
877
1038
|
const upb_fielddef* field = upb_msg_iter_field(&it);
|
1039
|
+
const upb_oneofdef* oneof = upb_fielddef_realcontainingoneof(field);
|
878
1040
|
|
879
1041
|
void* to_memory = slot_memory(layout, to, field);
|
880
|
-
uint32_t* to_oneof_case = slot_oneof_case(layout, to, field);
|
881
1042
|
void* from_memory = slot_memory(layout, from, field);
|
882
|
-
uint32_t* from_oneof_case = slot_oneof_case(layout, from, field);
|
883
1043
|
|
884
|
-
if (
|
885
|
-
|
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)) {
|
886
1049
|
*to_oneof_case = *from_oneof_case;
|
887
1050
|
native_slot_dup(upb_fielddef_type(field), to_memory, from_memory);
|
888
1051
|
}
|
@@ -907,16 +1070,20 @@ void layout_deep_copy(MessageLayout* layout, void* to, void* from) {
|
|
907
1070
|
!upb_msg_field_done(&it);
|
908
1071
|
upb_msg_field_next(&it)) {
|
909
1072
|
const upb_fielddef* field = upb_msg_iter_field(&it);
|
1073
|
+
const upb_oneofdef* oneof = upb_fielddef_realcontainingoneof(field);
|
910
1074
|
|
911
1075
|
void* to_memory = slot_memory(layout, to, field);
|
912
|
-
uint32_t* to_oneof_case = slot_oneof_case(layout, to, field);
|
913
1076
|
void* from_memory = slot_memory(layout, from, field);
|
914
|
-
uint32_t* from_oneof_case = slot_oneof_case(layout, from, field);
|
915
1077
|
|
916
|
-
if (
|
917
|
-
|
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)) {
|
918
1083
|
*to_oneof_case = *from_oneof_case;
|
919
|
-
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);
|
920
1087
|
}
|
921
1088
|
} else if (is_map_field(field)) {
|
922
1089
|
DEREF(to_memory, VALUE) =
|
@@ -930,7 +1097,9 @@ void layout_deep_copy(MessageLayout* layout, void* to, void* from) {
|
|
930
1097
|
slot_set_hasbit(layout, to, field);
|
931
1098
|
}
|
932
1099
|
|
933
|
-
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);
|
934
1103
|
}
|
935
1104
|
}
|
936
1105
|
}
|
@@ -941,17 +1110,19 @@ VALUE layout_eq(MessageLayout* layout, void* msg1, void* msg2) {
|
|
941
1110
|
!upb_msg_field_done(&it);
|
942
1111
|
upb_msg_field_next(&it)) {
|
943
1112
|
const upb_fielddef* field = upb_msg_iter_field(&it);
|
1113
|
+
const upb_oneofdef* oneof = upb_fielddef_realcontainingoneof(field);
|
944
1114
|
|
945
1115
|
void* msg1_memory = slot_memory(layout, msg1, field);
|
946
|
-
uint32_t* msg1_oneof_case = slot_oneof_case(layout, msg1, field);
|
947
1116
|
void* msg2_memory = slot_memory(layout, msg2, field);
|
948
|
-
uint32_t* msg2_oneof_case = slot_oneof_case(layout, msg2, field);
|
949
1117
|
|
950
|
-
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);
|
951
1121
|
if (*msg1_oneof_case != *msg2_oneof_case ||
|
952
|
-
(
|
1122
|
+
(slot_read_oneof_case(layout, msg1, oneof) ==
|
1123
|
+
upb_fielddef_number(field) &&
|
953
1124
|
!native_slot_eq(upb_fielddef_type(field),
|
954
|
-
msg1_memory,
|
1125
|
+
field_type_class(layout, field), msg1_memory,
|
955
1126
|
msg2_memory))) {
|
956
1127
|
return Qfalse;
|
957
1128
|
}
|
@@ -966,10 +1137,18 @@ VALUE layout_eq(MessageLayout* layout, void* msg1, void* msg2) {
|
|
966
1137
|
return Qfalse;
|
967
1138
|
}
|
968
1139
|
} else {
|
969
|
-
if (
|
970
|
-
|
971
|
-
|
972
|
-
|
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)) {
|
973
1152
|
return Qfalse;
|
974
1153
|
}
|
975
1154
|
}
|