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.
- checksums.yaml +4 -4
- data/ext/google/protobuf_c/defs.c +851 -830
- data/ext/google/protobuf_c/encode_decode.c +477 -293
- data/ext/google/protobuf_c/extconf.rb +2 -4
- data/ext/google/protobuf_c/map.c +21 -8
- data/ext/google/protobuf_c/message.c +194 -77
- data/ext/google/protobuf_c/protobuf.c +30 -15
- data/ext/google/protobuf_c/protobuf.h +113 -60
- data/ext/google/protobuf_c/repeated_field.c +55 -23
- data/ext/google/protobuf_c/storage.c +291 -161
- data/ext/google/protobuf_c/upb.c +4824 -8853
- data/ext/google/protobuf_c/upb.h +4699 -7369
- 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 +104 -20
- metadata +6 -6
@@ -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,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
|
-
|
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
|
-
|
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 =
|
462
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
567
|
-
return (uint32_t
|
568
|
-
|
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
|
-
|
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 (
|
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(
|
662
|
-
|
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
|
-
|
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
|
-
|
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 (
|
716
|
-
|
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(
|
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->
|
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
|
-
}
|
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(
|
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 (
|
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
|
-
}
|
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
|
-
|
913
|
+
const upb_oneofdef* oneof = upb_fielddef_containingoneof(field);
|
799
914
|
|
800
|
-
if (
|
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
|
-
|
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(
|
831
|
-
|
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
|
-
|
960
|
+
void layout_init(MessageLayout* layout, void* storage) {
|
961
|
+
VALUE* value = (VALUE*)CHARPTR_AT(storage, layout->value_offset);
|
962
|
+
int i;
|
842
963
|
|
843
|
-
|
844
|
-
|
845
|
-
|
846
|
-
|
847
|
-
|
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
|
-
|
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);
|
974
|
+
VALUE* values = (VALUE*)CHARPTR_AT(storage, layout->value_offset);
|
975
|
+
int noneofs = upb_msgdef_numoneofs(layout->msgdef);
|
976
|
+
int i;
|
859
977
|
|
860
|
-
|
861
|
-
|
862
|
-
|
863
|
-
|
864
|
-
|
865
|
-
|
866
|
-
|
867
|
-
|
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 (
|
885
|
-
|
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 (
|
917
|
-
|
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),
|
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),
|
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 (
|
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
|
-
(
|
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
|
-
|
1099
|
+
slot_is_hasbit_set(layout, msg2, field) ||
|
971
1100
|
!native_slot_eq(upb_fielddef_type(field),
|
972
|
-
|
1101
|
+
field_type_class(layout, field), msg1_memory,
|
1102
|
+
msg2_memory)) {
|
973
1103
|
return Qfalse;
|
974
1104
|
}
|
975
1105
|
}
|