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
@@ -117,18 +117,18 @@ static const void* newhandlerdata(upb_handlers* h, uint32_t ofs, int32_t hasbit)
|
|
117
117
|
typedef struct {
|
118
118
|
size_t ofs;
|
119
119
|
int32_t hasbit;
|
120
|
-
|
120
|
+
VALUE subklass;
|
121
121
|
} submsg_handlerdata_t;
|
122
122
|
|
123
123
|
// Creates a handlerdata that contains offset and submessage type information.
|
124
124
|
static const void *newsubmsghandlerdata(upb_handlers* h,
|
125
125
|
uint32_t ofs,
|
126
126
|
int32_t hasbit,
|
127
|
-
|
127
|
+
VALUE subklass) {
|
128
128
|
submsg_handlerdata_t *hd = ALLOC(submsg_handlerdata_t);
|
129
129
|
hd->ofs = ofs;
|
130
130
|
hd->hasbit = hasbit;
|
131
|
-
hd->
|
131
|
+
hd->subklass = subklass;
|
132
132
|
upb_handlers_addcleanup(h, hd, xfree);
|
133
133
|
return hd;
|
134
134
|
}
|
@@ -137,13 +137,14 @@ typedef struct {
|
|
137
137
|
size_t ofs; // union data slot
|
138
138
|
size_t case_ofs; // oneof_case field
|
139
139
|
uint32_t oneof_case_num; // oneof-case number to place in oneof_case field
|
140
|
-
|
140
|
+
VALUE subklass;
|
141
141
|
} oneof_handlerdata_t;
|
142
142
|
|
143
143
|
static const void *newoneofhandlerdata(upb_handlers *h,
|
144
144
|
uint32_t ofs,
|
145
145
|
uint32_t case_ofs,
|
146
|
-
const upb_fielddef *f
|
146
|
+
const upb_fielddef *f,
|
147
|
+
const Descriptor* desc) {
|
147
148
|
oneof_handlerdata_t *hd = ALLOC(oneof_handlerdata_t);
|
148
149
|
hd->ofs = ofs;
|
149
150
|
hd->case_ofs = case_ofs;
|
@@ -154,11 +155,10 @@ static const void *newoneofhandlerdata(upb_handlers *h,
|
|
154
155
|
// create a separate ID space. In addition, using the field tag number here
|
155
156
|
// lets us easily look up the field in the oneof accessor.
|
156
157
|
hd->oneof_case_num = upb_fielddef_number(f);
|
157
|
-
if (
|
158
|
-
hd->
|
159
|
-
} else {
|
160
|
-
hd->md = NULL;
|
158
|
+
if (is_value_field(f)) {
|
159
|
+
hd->oneof_case_num |= ONEOF_CASE_MASK;
|
161
160
|
}
|
161
|
+
hd->subklass = field_type_class(desc->layout, f);
|
162
162
|
upb_handlers_addcleanup(h, hd, xfree);
|
163
163
|
return hd;
|
164
164
|
}
|
@@ -254,13 +254,13 @@ static size_t stringdata_handler(void* closure, const void* hd,
|
|
254
254
|
}
|
255
255
|
|
256
256
|
static bool stringdata_end_handler(void* closure, const void* hd) {
|
257
|
-
VALUE rb_str = closure;
|
257
|
+
VALUE rb_str = (VALUE)closure;
|
258
258
|
rb_obj_freeze(rb_str);
|
259
259
|
return true;
|
260
260
|
}
|
261
261
|
|
262
262
|
static bool appendstring_end_handler(void* closure, const void* hd) {
|
263
|
-
VALUE rb_str = closure;
|
263
|
+
VALUE rb_str = (VALUE)closure;
|
264
264
|
rb_obj_freeze(rb_str);
|
265
265
|
return true;
|
266
266
|
}
|
@@ -269,31 +269,36 @@ static bool appendstring_end_handler(void* closure, const void* hd) {
|
|
269
269
|
static void *appendsubmsg_handler(void *closure, const void *hd) {
|
270
270
|
VALUE ary = (VALUE)closure;
|
271
271
|
const submsg_handlerdata_t *submsgdata = hd;
|
272
|
-
VALUE subdesc =
|
273
|
-
get_def_obj((void*)submsgdata->md);
|
274
|
-
VALUE subklass = Descriptor_msgclass(subdesc);
|
275
272
|
MessageHeader* submsg;
|
276
273
|
|
277
|
-
VALUE submsg_rb = rb_class_new_instance(0, NULL, subklass);
|
274
|
+
VALUE submsg_rb = rb_class_new_instance(0, NULL, submsgdata->subklass);
|
278
275
|
RepeatedField_push(ary, submsg_rb);
|
279
276
|
|
280
277
|
TypedData_Get_Struct(submsg_rb, MessageHeader, &Message_type, submsg);
|
281
278
|
return submsg;
|
282
279
|
}
|
283
280
|
|
281
|
+
// Appends a wrapper to a repeated field (a regular Ruby array for now).
|
282
|
+
static void *appendwrapper_handler(void *closure, const void *hd) {
|
283
|
+
VALUE ary = (VALUE)closure;
|
284
|
+
int size = RepeatedField_size(ary);
|
285
|
+
(void)hd;
|
286
|
+
|
287
|
+
RepeatedField_push(ary, Qnil);
|
288
|
+
|
289
|
+
return RepeatedField_index_native(ary, size);
|
290
|
+
}
|
291
|
+
|
284
292
|
// Sets a non-repeated submessage field in a message.
|
285
293
|
static void *submsg_handler(void *closure, const void *hd) {
|
286
294
|
MessageHeader* msg = closure;
|
287
295
|
const submsg_handlerdata_t* submsgdata = hd;
|
288
|
-
VALUE subdesc =
|
289
|
-
get_def_obj((void*)submsgdata->md);
|
290
|
-
VALUE subklass = Descriptor_msgclass(subdesc);
|
291
296
|
VALUE submsg_rb;
|
292
297
|
MessageHeader* submsg;
|
293
298
|
|
294
299
|
if (DEREF(msg, submsgdata->ofs, VALUE) == Qnil) {
|
295
300
|
DEREF(msg, submsgdata->ofs, VALUE) =
|
296
|
-
rb_class_new_instance(0, NULL, subklass);
|
301
|
+
rb_class_new_instance(0, NULL, submsgdata->subklass);
|
297
302
|
}
|
298
303
|
|
299
304
|
set_hasbit(closure, submsgdata->hasbit);
|
@@ -304,16 +309,21 @@ static void *submsg_handler(void *closure, const void *hd) {
|
|
304
309
|
return submsg;
|
305
310
|
}
|
306
311
|
|
312
|
+
static void* startwrapper(void* closure, const void* hd) {
|
313
|
+
char* msg = closure;
|
314
|
+
const submsg_handlerdata_t* submsgdata = hd;
|
315
|
+
|
316
|
+
set_hasbit(closure, submsgdata->hasbit);
|
317
|
+
|
318
|
+
return msg + submsgdata->ofs;
|
319
|
+
}
|
320
|
+
|
307
321
|
// Handler data for startmap/endmap handlers.
|
308
322
|
typedef struct {
|
309
323
|
size_t ofs;
|
310
324
|
upb_fieldtype_t key_field_type;
|
311
325
|
upb_fieldtype_t value_field_type;
|
312
|
-
|
313
|
-
// We know that we can hold this reference because the handlerdata has the
|
314
|
-
// same lifetime as the upb_handlers struct, and the upb_handlers struct holds
|
315
|
-
// a reference to the upb_msgdef, which in turn has references to its subdefs.
|
316
|
-
const upb_def* value_field_subdef;
|
326
|
+
VALUE subklass;
|
317
327
|
} map_handlerdata_t;
|
318
328
|
|
319
329
|
// Temporary frame for map parsing: at the beginning of a map entry message, a
|
@@ -349,33 +359,36 @@ rb_data_type_t MapParseFrame_type = {
|
|
349
359
|
{ MapParseFrame_mark, MapParseFrame_free, NULL },
|
350
360
|
};
|
351
361
|
|
352
|
-
|
353
|
-
|
362
|
+
// Handler to begin a map entry: allocates a temporary frame. This is the
|
363
|
+
// 'startsubmsg' handler on the msgdef that contains the map field.
|
364
|
+
static void *startmap_handler(void *closure, const void *hd) {
|
365
|
+
MessageHeader* msg = closure;
|
366
|
+
const map_handlerdata_t* mapdata = hd;
|
354
367
|
map_parse_frame_t* frame = ALLOC(map_parse_frame_t);
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
368
|
+
VALUE map_rb = DEREF(msg, mapdata->ofs, VALUE);
|
369
|
+
|
370
|
+
frame->handlerdata = mapdata;
|
371
|
+
frame->map = map_rb;
|
372
|
+
native_slot_init(mapdata->key_field_type, &frame->key_storage);
|
373
|
+
native_slot_init(mapdata->value_field_type, &frame->value_storage);
|
359
374
|
|
360
|
-
Map_set_frame(
|
361
|
-
|
375
|
+
Map_set_frame(map_rb,
|
376
|
+
TypedData_Wrap_Struct(rb_cObject, &MapParseFrame_type, frame));
|
362
377
|
|
363
378
|
return frame;
|
364
379
|
}
|
365
380
|
|
366
|
-
|
367
|
-
// 'startsubmsg' handler on the msgdef that contains the map field.
|
368
|
-
static void *startmapentry_handler(void *closure, const void *hd) {
|
381
|
+
static bool endmap_handler(void *closure, const void *hd) {
|
369
382
|
MessageHeader* msg = closure;
|
370
383
|
const map_handlerdata_t* mapdata = hd;
|
371
384
|
VALUE map_rb = DEREF(msg, mapdata->ofs, VALUE);
|
372
|
-
|
373
|
-
return
|
385
|
+
Map_set_frame(map_rb, Qnil);
|
386
|
+
return true;
|
374
387
|
}
|
375
388
|
|
376
389
|
// Handler to end a map entry: inserts the value defined during the message into
|
377
390
|
// the map. This is the 'endmsg' handler on the map entry msgdef.
|
378
|
-
static bool
|
391
|
+
static bool endmapentry_handler(void* closure, const void* hd, upb_status* s) {
|
379
392
|
map_parse_frame_t* frame = closure;
|
380
393
|
const map_handlerdata_t* mapdata = hd;
|
381
394
|
|
@@ -383,20 +396,11 @@ static bool endmap_handler(void *closure, const void *hd, upb_status* s) {
|
|
383
396
|
mapdata->key_field_type, Qnil,
|
384
397
|
&frame->key_storage);
|
385
398
|
|
386
|
-
VALUE
|
387
|
-
|
388
|
-
|
389
|
-
if (mapdata->value_field_type == UPB_TYPE_MESSAGE ||
|
390
|
-
mapdata->value_field_type == UPB_TYPE_ENUM) {
|
391
|
-
value_field_typeclass = get_def_obj(mapdata->value_field_subdef);
|
392
|
-
}
|
393
|
-
|
394
|
-
value = native_slot_get(
|
395
|
-
mapdata->value_field_type, value_field_typeclass,
|
399
|
+
VALUE value = native_slot_get(
|
400
|
+
mapdata->value_field_type, mapdata->subklass,
|
396
401
|
&frame->value_storage);
|
397
402
|
|
398
403
|
Map_index_set(frame->map, key, value);
|
399
|
-
Map_set_frame(frame->map, Qnil);
|
400
404
|
|
401
405
|
return true;
|
402
406
|
}
|
@@ -411,7 +415,7 @@ static bool endmap_handler(void *closure, const void *hd, upb_status* s) {
|
|
411
415
|
static map_handlerdata_t* new_map_handlerdata(
|
412
416
|
size_t ofs,
|
413
417
|
const upb_msgdef* mapentry_def,
|
414
|
-
Descriptor* desc) {
|
418
|
+
const Descriptor* desc) {
|
415
419
|
const upb_fielddef* key_field;
|
416
420
|
const upb_fielddef* value_field;
|
417
421
|
map_handlerdata_t* hd = ALLOC(map_handlerdata_t);
|
@@ -422,7 +426,7 @@ static map_handlerdata_t* new_map_handlerdata(
|
|
422
426
|
value_field = upb_msgdef_itof(mapentry_def, MAP_VALUE_FIELD);
|
423
427
|
assert(value_field != NULL);
|
424
428
|
hd->value_field_type = upb_fielddef_type(value_field);
|
425
|
-
hd->
|
429
|
+
hd->subklass = field_type_class(desc->layout, value_field);
|
426
430
|
|
427
431
|
return hd;
|
428
432
|
}
|
@@ -488,16 +492,13 @@ static void *oneofsubmsg_handler(void *closure,
|
|
488
492
|
const oneof_handlerdata_t *oneofdata = hd;
|
489
493
|
uint32_t oldcase = DEREF(msg, oneofdata->case_ofs, uint32_t);
|
490
494
|
|
491
|
-
VALUE subdesc =
|
492
|
-
get_def_obj((void*)oneofdata->md);
|
493
|
-
VALUE subklass = Descriptor_msgclass(subdesc);
|
494
495
|
VALUE submsg_rb;
|
495
496
|
MessageHeader* submsg;
|
496
497
|
|
497
498
|
if (oldcase != oneofdata->oneof_case_num ||
|
498
499
|
DEREF(msg, oneofdata->ofs, VALUE) == Qnil) {
|
499
500
|
DEREF(msg, oneofdata->ofs, VALUE) =
|
500
|
-
rb_class_new_instance(0, NULL, subklass);
|
501
|
+
rb_class_new_instance(0, NULL, oneofdata->subklass);
|
501
502
|
}
|
502
503
|
// Set the oneof case *after* allocating the new class instance -- otherwise,
|
503
504
|
// if the Ruby GC is invoked as part of a call into the VM, it might invoke
|
@@ -505,22 +506,47 @@ static void *oneofsubmsg_handler(void *closure,
|
|
505
506
|
// indicating a VALUE is present and expect a valid VALUE. See comment in
|
506
507
|
// layout_set() for more detail: basically, the change to the value and the
|
507
508
|
// case must be atomic w.r.t. the Ruby VM.
|
508
|
-
DEREF(msg, oneofdata->case_ofs, uint32_t) =
|
509
|
-
oneofdata->oneof_case_num;
|
509
|
+
DEREF(msg, oneofdata->case_ofs, uint32_t) = oneofdata->oneof_case_num;
|
510
510
|
|
511
511
|
submsg_rb = DEREF(msg, oneofdata->ofs, VALUE);
|
512
512
|
TypedData_Get_Struct(submsg_rb, MessageHeader, &Message_type, submsg);
|
513
513
|
return submsg;
|
514
514
|
}
|
515
515
|
|
516
|
+
static void* oneof_startwrapper(void* closure, const void* hd) {
|
517
|
+
char* msg = closure;
|
518
|
+
const oneof_handlerdata_t *oneofdata = hd;
|
519
|
+
|
520
|
+
DEREF(msg, oneofdata->case_ofs, uint32_t) = oneofdata->oneof_case_num;
|
521
|
+
|
522
|
+
return msg + oneofdata->ofs;
|
523
|
+
}
|
524
|
+
|
525
|
+
bool is_wrapper(const upb_msgdef* m) {
|
526
|
+
switch (upb_msgdef_wellknowntype(m)) {
|
527
|
+
case UPB_WELLKNOWN_DOUBLEVALUE:
|
528
|
+
case UPB_WELLKNOWN_FLOATVALUE:
|
529
|
+
case UPB_WELLKNOWN_INT64VALUE:
|
530
|
+
case UPB_WELLKNOWN_UINT64VALUE:
|
531
|
+
case UPB_WELLKNOWN_INT32VALUE:
|
532
|
+
case UPB_WELLKNOWN_UINT32VALUE:
|
533
|
+
case UPB_WELLKNOWN_STRINGVALUE:
|
534
|
+
case UPB_WELLKNOWN_BYTESVALUE:
|
535
|
+
case UPB_WELLKNOWN_BOOLVALUE:
|
536
|
+
return true;
|
537
|
+
default:
|
538
|
+
return false;
|
539
|
+
}
|
540
|
+
}
|
541
|
+
|
516
542
|
// Set up handlers for a repeated field.
|
517
543
|
static void add_handlers_for_repeated_field(upb_handlers *h,
|
544
|
+
const Descriptor* desc,
|
518
545
|
const upb_fielddef *f,
|
519
546
|
size_t offset) {
|
520
|
-
upb_handlerattr attr =
|
521
|
-
|
547
|
+
upb_handlerattr attr = UPB_HANDLERATTR_INIT;
|
548
|
+
attr.handler_data = newhandlerdata(h, offset, -1);
|
522
549
|
upb_handlers_setstartseq(h, f, startseq_handler, &attr);
|
523
|
-
upb_handlerattr_uninit(&attr);
|
524
550
|
|
525
551
|
switch (upb_fielddef_type(f)) {
|
526
552
|
|
@@ -551,20 +577,104 @@ static void add_handlers_for_repeated_field(upb_handlers *h,
|
|
551
577
|
break;
|
552
578
|
}
|
553
579
|
case UPB_TYPE_MESSAGE: {
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
580
|
+
VALUE subklass = field_type_class(desc->layout, f);
|
581
|
+
upb_handlerattr attr = UPB_HANDLERATTR_INIT;
|
582
|
+
attr.handler_data = newsubmsghandlerdata(h, 0, -1, subklass);
|
583
|
+
if (is_wrapper(upb_fielddef_msgsubdef(f))) {
|
584
|
+
upb_handlers_setstartsubmsg(h, f, appendwrapper_handler, &attr);
|
585
|
+
} else {
|
586
|
+
upb_handlers_setstartsubmsg(h, f, appendsubmsg_handler, &attr);
|
587
|
+
}
|
558
588
|
break;
|
559
589
|
}
|
560
590
|
}
|
561
591
|
}
|
562
592
|
|
593
|
+
static bool doublewrapper_handler(void* closure, const void* hd, double val) {
|
594
|
+
VALUE* rbval = closure;
|
595
|
+
*rbval = DBL2NUM(val);
|
596
|
+
return true;
|
597
|
+
}
|
598
|
+
|
599
|
+
static bool floatwrapper_handler(void* closure, const void* hd, float val) {
|
600
|
+
VALUE* rbval = closure;
|
601
|
+
*rbval = DBL2NUM(val);
|
602
|
+
return true;
|
603
|
+
}
|
604
|
+
|
605
|
+
static bool int64wrapper_handler(void* closure, const void* hd, int64_t val) {
|
606
|
+
VALUE* rbval = closure;
|
607
|
+
*rbval = LL2NUM(val);
|
608
|
+
return true;
|
609
|
+
}
|
610
|
+
|
611
|
+
static bool uint64wrapper_handler(void* closure, const void* hd, uint64_t val) {
|
612
|
+
VALUE* rbval = closure;
|
613
|
+
*rbval = ULL2NUM(val);
|
614
|
+
return true;
|
615
|
+
}
|
616
|
+
|
617
|
+
static bool int32wrapper_handler(void* closure, const void* hd, int32_t val) {
|
618
|
+
VALUE* rbval = closure;
|
619
|
+
*rbval = INT2NUM(val);
|
620
|
+
return true;
|
621
|
+
}
|
622
|
+
|
623
|
+
static bool uint32wrapper_handler(void* closure, const void* hd, uint32_t val) {
|
624
|
+
VALUE* rbval = closure;
|
625
|
+
*rbval = UINT2NUM(val);
|
626
|
+
return true;
|
627
|
+
}
|
628
|
+
|
629
|
+
static void* startstringwrapper_handler(void* closure, const void* hd,
|
630
|
+
size_t size_hint) {
|
631
|
+
VALUE* rbval = closure;
|
632
|
+
(void)size_hint;
|
633
|
+
*rbval = rb_str_new(NULL, 0);
|
634
|
+
rb_enc_associate(*rbval, kRubyStringUtf8Encoding);
|
635
|
+
return closure;
|
636
|
+
}
|
637
|
+
|
638
|
+
static size_t stringwrapper_handler(void* closure, const void* hd,
|
639
|
+
const char* ptr, size_t len,
|
640
|
+
const upb_bufhandle* handle) {
|
641
|
+
VALUE* rbval = closure;
|
642
|
+
*rbval = noleak_rb_str_cat(*rbval, ptr, len);
|
643
|
+
return len;
|
644
|
+
}
|
645
|
+
|
646
|
+
static void* startbyteswrapper_handler(void* closure, const void* hd,
|
647
|
+
size_t size_hint) {
|
648
|
+
VALUE* rbval = closure;
|
649
|
+
(void)size_hint;
|
650
|
+
*rbval = rb_str_new(NULL, 0);
|
651
|
+
rb_enc_associate(*rbval, kRubyString8bitEncoding);
|
652
|
+
return closure;
|
653
|
+
}
|
654
|
+
|
655
|
+
static size_t byteswrapper_handler(void* closure, const void* hd,
|
656
|
+
const char* ptr, size_t len,
|
657
|
+
const upb_bufhandle* handle) {
|
658
|
+
VALUE* rbval = closure;
|
659
|
+
*rbval = noleak_rb_str_cat(*rbval, ptr, len);
|
660
|
+
return len;
|
661
|
+
}
|
662
|
+
|
663
|
+
static bool boolwrapper_handler(void* closure, const void* hd, bool val) {
|
664
|
+
VALUE* rbval = closure;
|
665
|
+
if (val) {
|
666
|
+
*rbval = Qtrue;
|
667
|
+
} else {
|
668
|
+
*rbval = Qfalse;
|
669
|
+
}
|
670
|
+
return true;
|
671
|
+
}
|
672
|
+
|
563
673
|
// Set up handlers for a singular field.
|
564
|
-
static void add_handlers_for_singular_field(
|
565
|
-
|
566
|
-
|
567
|
-
size_t hasbit_off) {
|
674
|
+
static void add_handlers_for_singular_field(const Descriptor* desc,
|
675
|
+
upb_handlers* h,
|
676
|
+
const upb_fielddef* f,
|
677
|
+
size_t offset, size_t hasbit_off) {
|
568
678
|
// The offset we pass to UPB points to the start of the Message,
|
569
679
|
// rather than the start of where our data is stored.
|
570
680
|
int32_t hasbit = -1;
|
@@ -586,24 +696,24 @@ static void add_handlers_for_singular_field(upb_handlers *h,
|
|
586
696
|
case UPB_TYPE_STRING:
|
587
697
|
case UPB_TYPE_BYTES: {
|
588
698
|
bool is_bytes = upb_fielddef_type(f) == UPB_TYPE_BYTES;
|
589
|
-
upb_handlerattr attr =
|
590
|
-
|
699
|
+
upb_handlerattr attr = UPB_HANDLERATTR_INIT;
|
700
|
+
attr.handler_data = newhandlerdata(h, offset, hasbit);
|
591
701
|
upb_handlers_setstartstr(h, f,
|
592
702
|
is_bytes ? bytes_handler : str_handler,
|
593
703
|
&attr);
|
594
704
|
upb_handlers_setstring(h, f, stringdata_handler, &attr);
|
595
705
|
upb_handlers_setendstr(h, f, stringdata_end_handler, &attr);
|
596
|
-
upb_handlerattr_uninit(&attr);
|
597
706
|
break;
|
598
707
|
}
|
599
708
|
case UPB_TYPE_MESSAGE: {
|
600
|
-
upb_handlerattr attr =
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
709
|
+
upb_handlerattr attr = UPB_HANDLERATTR_INIT;
|
710
|
+
attr.handler_data = newsubmsghandlerdata(
|
711
|
+
h, offset, hasbit, field_type_class(desc->layout, f));
|
712
|
+
if (is_wrapper(upb_fielddef_msgsubdef(f))) {
|
713
|
+
upb_handlers_setstartsubmsg(h, f, startwrapper, &attr);
|
714
|
+
} else {
|
715
|
+
upb_handlers_setstartsubmsg(h, f, submsg_handler, &attr);
|
716
|
+
}
|
607
717
|
}
|
608
718
|
}
|
609
719
|
}
|
@@ -612,49 +722,87 @@ static void add_handlers_for_singular_field(upb_handlers *h,
|
|
612
722
|
static void add_handlers_for_mapfield(upb_handlers* h,
|
613
723
|
const upb_fielddef* fielddef,
|
614
724
|
size_t offset,
|
615
|
-
Descriptor* desc) {
|
725
|
+
const Descriptor* desc) {
|
616
726
|
const upb_msgdef* map_msgdef = upb_fielddef_msgsubdef(fielddef);
|
617
727
|
map_handlerdata_t* hd = new_map_handlerdata(offset, map_msgdef, desc);
|
618
|
-
upb_handlerattr attr =
|
728
|
+
upb_handlerattr attr = UPB_HANDLERATTR_INIT;
|
619
729
|
|
620
730
|
upb_handlers_addcleanup(h, hd, xfree);
|
621
|
-
|
622
|
-
upb_handlers_setstartsubmsg(h, fielddef,
|
623
|
-
|
731
|
+
attr.handler_data = hd;
|
732
|
+
upb_handlers_setstartsubmsg(h, fielddef, startmap_handler, &attr);
|
733
|
+
upb_handlers_setendsubmsg(h, fielddef, endmap_handler, &attr);
|
624
734
|
}
|
625
735
|
|
626
736
|
// Adds handlers to a map-entry msgdef.
|
627
|
-
static void add_handlers_for_mapentry(const upb_msgdef* msgdef,
|
628
|
-
|
629
|
-
Descriptor* desc) {
|
737
|
+
static void add_handlers_for_mapentry(const upb_msgdef* msgdef, upb_handlers* h,
|
738
|
+
const Descriptor* desc) {
|
630
739
|
const upb_fielddef* key_field = map_entry_key(msgdef);
|
631
740
|
const upb_fielddef* value_field = map_entry_value(msgdef);
|
632
741
|
map_handlerdata_t* hd = new_map_handlerdata(0, msgdef, desc);
|
633
|
-
upb_handlerattr attr =
|
742
|
+
upb_handlerattr attr = UPB_HANDLERATTR_INIT;
|
634
743
|
|
635
744
|
upb_handlers_addcleanup(h, hd, xfree);
|
636
|
-
|
637
|
-
upb_handlers_setendmsg(h,
|
745
|
+
attr.handler_data = hd;
|
746
|
+
upb_handlers_setendmsg(h, endmapentry_handler, &attr);
|
638
747
|
|
639
748
|
add_handlers_for_singular_field(
|
640
|
-
h, key_field,
|
749
|
+
desc, h, key_field,
|
641
750
|
offsetof(map_parse_frame_t, key_storage),
|
642
751
|
MESSAGE_FIELD_NO_HASBIT);
|
643
752
|
add_handlers_for_singular_field(
|
644
|
-
h, value_field,
|
753
|
+
desc, h, value_field,
|
645
754
|
offsetof(map_parse_frame_t, value_storage),
|
646
755
|
MESSAGE_FIELD_NO_HASBIT);
|
647
756
|
}
|
648
757
|
|
758
|
+
static void add_handlers_for_wrapper(const upb_msgdef* msgdef,
|
759
|
+
upb_handlers* h) {
|
760
|
+
const upb_fielddef* f = upb_msgdef_itof(msgdef, 1);
|
761
|
+
switch (upb_msgdef_wellknowntype(msgdef)) {
|
762
|
+
case UPB_WELLKNOWN_DOUBLEVALUE:
|
763
|
+
upb_handlers_setdouble(h, f, doublewrapper_handler, NULL);
|
764
|
+
break;
|
765
|
+
case UPB_WELLKNOWN_FLOATVALUE:
|
766
|
+
upb_handlers_setfloat(h, f, floatwrapper_handler, NULL);
|
767
|
+
break;
|
768
|
+
case UPB_WELLKNOWN_INT64VALUE:
|
769
|
+
upb_handlers_setint64(h, f, int64wrapper_handler, NULL);
|
770
|
+
break;
|
771
|
+
case UPB_WELLKNOWN_UINT64VALUE:
|
772
|
+
upb_handlers_setuint64(h, f, uint64wrapper_handler, NULL);
|
773
|
+
break;
|
774
|
+
case UPB_WELLKNOWN_INT32VALUE:
|
775
|
+
upb_handlers_setint32(h, f, int32wrapper_handler, NULL);
|
776
|
+
break;
|
777
|
+
case UPB_WELLKNOWN_UINT32VALUE:
|
778
|
+
upb_handlers_setuint32(h, f, uint32wrapper_handler, NULL);
|
779
|
+
break;
|
780
|
+
case UPB_WELLKNOWN_STRINGVALUE:
|
781
|
+
upb_handlers_setstartstr(h, f, startstringwrapper_handler, NULL);
|
782
|
+
upb_handlers_setstring(h, f, stringwrapper_handler, NULL);
|
783
|
+
break;
|
784
|
+
case UPB_WELLKNOWN_BYTESVALUE:
|
785
|
+
upb_handlers_setstartstr(h, f, startbyteswrapper_handler, NULL);
|
786
|
+
upb_handlers_setstring(h, f, byteswrapper_handler, NULL);
|
787
|
+
break;
|
788
|
+
case UPB_WELLKNOWN_BOOLVALUE:
|
789
|
+
upb_handlers_setbool(h, f, boolwrapper_handler, NULL);
|
790
|
+
return;
|
791
|
+
default:
|
792
|
+
rb_raise(rb_eRuntimeError,
|
793
|
+
"Internal logic error with well-known types.");
|
794
|
+
}
|
795
|
+
}
|
796
|
+
|
649
797
|
// Set up handlers for a oneof field.
|
650
798
|
static void add_handlers_for_oneof_field(upb_handlers *h,
|
651
799
|
const upb_fielddef *f,
|
652
800
|
size_t offset,
|
653
|
-
size_t oneof_case_offset
|
654
|
-
|
655
|
-
upb_handlerattr attr =
|
656
|
-
|
657
|
-
|
801
|
+
size_t oneof_case_offset,
|
802
|
+
const Descriptor* desc) {
|
803
|
+
upb_handlerattr attr = UPB_HANDLERATTR_INIT;
|
804
|
+
attr.handler_data =
|
805
|
+
newoneofhandlerdata(h, offset, oneof_case_offset, f, desc);
|
658
806
|
|
659
807
|
switch (upb_fielddef_type(f)) {
|
660
808
|
|
@@ -685,19 +833,21 @@ static void add_handlers_for_oneof_field(upb_handlers *h,
|
|
685
833
|
break;
|
686
834
|
}
|
687
835
|
case UPB_TYPE_MESSAGE: {
|
688
|
-
|
836
|
+
if (is_wrapper(upb_fielddef_msgsubdef(f))) {
|
837
|
+
upb_handlers_setstartsubmsg(h, f, oneof_startwrapper, &attr);
|
838
|
+
} else {
|
839
|
+
upb_handlers_setstartsubmsg(h, f, oneofsubmsg_handler, &attr);
|
840
|
+
}
|
689
841
|
break;
|
690
842
|
}
|
691
843
|
}
|
692
|
-
|
693
|
-
upb_handlerattr_uninit(&attr);
|
694
844
|
}
|
695
845
|
|
696
846
|
static bool unknown_field_handler(void* closure, const void* hd,
|
697
847
|
const char* buf, size_t size) {
|
848
|
+
MessageHeader* msg = (MessageHeader*)closure;
|
698
849
|
UPB_UNUSED(hd);
|
699
850
|
|
700
|
-
MessageHeader* msg = (MessageHeader*)closure;
|
701
851
|
if (msg->unknown_fields == NULL) {
|
702
852
|
msg->unknown_fields = malloc(sizeof(stringsink));
|
703
853
|
stringsink_init(msg->unknown_fields);
|
@@ -708,10 +858,25 @@ static bool unknown_field_handler(void* closure, const void* hd,
|
|
708
858
|
return true;
|
709
859
|
}
|
710
860
|
|
711
|
-
|
861
|
+
size_t get_field_offset(MessageLayout* layout, const upb_fielddef* f) {
|
862
|
+
return layout->fields[upb_fielddef_index(f)].offset + sizeof(MessageHeader);
|
863
|
+
}
|
864
|
+
|
865
|
+
void add_handlers_for_message(const void *closure, upb_handlers *h) {
|
866
|
+
const VALUE descriptor_pool = (VALUE)closure;
|
712
867
|
const upb_msgdef* msgdef = upb_handlers_msgdef(h);
|
713
|
-
Descriptor* desc =
|
868
|
+
Descriptor* desc =
|
869
|
+
ruby_to_Descriptor(get_msgdef_obj(descriptor_pool, msgdef));
|
714
870
|
upb_msg_field_iter i;
|
871
|
+
upb_handlerattr attr = UPB_HANDLERATTR_INIT;
|
872
|
+
|
873
|
+
// Ensure layout exists. We may be invoked to create handlers for a given
|
874
|
+
// message if we are included as a submsg of another message type before our
|
875
|
+
// class is actually built, so to work around this, we just create the layout
|
876
|
+
// (and handlers, in the class-building function) on-demand.
|
877
|
+
if (desc->layout == NULL) {
|
878
|
+
create_layout(desc);
|
879
|
+
}
|
715
880
|
|
716
881
|
// If this is a mapentry message type, set up a special set of handlers and
|
717
882
|
// bail out of the normal (user-defined) message type handling.
|
@@ -720,86 +885,70 @@ static void add_handlers_for_message(const void *closure, upb_handlers *h) {
|
|
720
885
|
return;
|
721
886
|
}
|
722
887
|
|
723
|
-
//
|
724
|
-
|
725
|
-
|
726
|
-
|
727
|
-
if (desc->layout == NULL) {
|
728
|
-
desc->layout = create_layout(desc->msgdef);
|
888
|
+
// If this is a wrapper type, use special handlers and bail.
|
889
|
+
if (is_wrapper(msgdef)) {
|
890
|
+
add_handlers_for_wrapper(msgdef, h);
|
891
|
+
return;
|
729
892
|
}
|
730
893
|
|
731
|
-
upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER;
|
732
894
|
upb_handlers_setunknown(h, unknown_field_handler, &attr);
|
733
895
|
|
734
896
|
for (upb_msg_field_begin(&i, desc->msgdef);
|
735
897
|
!upb_msg_field_done(&i);
|
736
898
|
upb_msg_field_next(&i)) {
|
737
899
|
const upb_fielddef *f = upb_msg_iter_field(&i);
|
738
|
-
|
739
|
-
|
900
|
+
const upb_oneofdef *oneof = upb_fielddef_containingoneof(f);
|
901
|
+
size_t offset = get_field_offset(desc->layout, f);
|
740
902
|
|
741
|
-
if (
|
903
|
+
if (oneof) {
|
742
904
|
size_t oneof_case_offset =
|
743
|
-
desc->layout->
|
905
|
+
desc->layout->oneofs[upb_oneofdef_index(oneof)].case_offset +
|
744
906
|
sizeof(MessageHeader);
|
745
|
-
add_handlers_for_oneof_field(h, f, offset, oneof_case_offset);
|
907
|
+
add_handlers_for_oneof_field(h, f, offset, oneof_case_offset, desc);
|
746
908
|
} else if (is_map_field(f)) {
|
747
909
|
add_handlers_for_mapfield(h, f, offset, desc);
|
748
910
|
} else if (upb_fielddef_isseq(f)) {
|
749
|
-
add_handlers_for_repeated_field(h, f, offset);
|
911
|
+
add_handlers_for_repeated_field(h, desc, f, offset);
|
750
912
|
} else {
|
751
913
|
add_handlers_for_singular_field(
|
752
|
-
h, f, offset,
|
914
|
+
desc, h, f, offset,
|
915
|
+
desc->layout->fields[upb_fielddef_index(f)].hasbit);
|
753
916
|
}
|
754
917
|
}
|
755
918
|
}
|
756
919
|
|
757
|
-
// Creates upb handlers for populating a message.
|
758
|
-
static const upb_handlers *new_fill_handlers(Descriptor* desc,
|
759
|
-
const void* owner) {
|
760
|
-
// TODO(cfallin, haberman): once upb gets a caching/memoization layer for
|
761
|
-
// handlers, reuse subdef handlers so that e.g. if we already parse
|
762
|
-
// B-with-field-of-type-C, we don't have to rebuild the whole hierarchy to
|
763
|
-
// parse A-with-field-of-type-B-with-field-of-type-C.
|
764
|
-
return upb_handlers_newfrozen(desc->msgdef, owner,
|
765
|
-
add_handlers_for_message, NULL);
|
766
|
-
}
|
767
|
-
|
768
920
|
// Constructs the handlers for filling a message's data into an in-memory
|
769
921
|
// object.
|
770
922
|
const upb_handlers* get_fill_handlers(Descriptor* desc) {
|
771
|
-
|
772
|
-
|
773
|
-
new_fill_handlers(desc, &desc->fill_handlers);
|
774
|
-
}
|
775
|
-
return desc->fill_handlers;
|
923
|
+
DescriptorPool* pool = ruby_to_DescriptorPool(desc->descriptor_pool);
|
924
|
+
return upb_handlercache_get(pool->fill_handler_cache, desc->msgdef);
|
776
925
|
}
|
777
926
|
|
778
|
-
|
779
|
-
|
780
|
-
|
781
|
-
|
782
|
-
const upb_handlers* handlers = get_fill_handlers(desc);
|
783
|
-
upb_pbdecodermethodopts opts;
|
784
|
-
upb_pbdecodermethodopts_init(&opts, handlers);
|
927
|
+
static const upb_pbdecodermethod *msgdef_decodermethod(Descriptor* desc) {
|
928
|
+
DescriptorPool* pool = ruby_to_DescriptorPool(desc->descriptor_pool);
|
929
|
+
return upb_pbcodecache_get(pool->fill_method_cache, desc->msgdef);
|
930
|
+
}
|
785
931
|
|
786
|
-
|
932
|
+
static const upb_json_parsermethod *msgdef_jsonparsermethod(Descriptor* desc) {
|
933
|
+
DescriptorPool* pool = ruby_to_DescriptorPool(desc->descriptor_pool);
|
934
|
+
return upb_json_codecache_get(pool->json_fill_method_cache, desc->msgdef);
|
787
935
|
}
|
788
936
|
|
789
|
-
static const
|
790
|
-
|
791
|
-
|
792
|
-
desc, &desc->fill_method);
|
793
|
-
}
|
794
|
-
return desc->fill_method;
|
937
|
+
static const upb_handlers* msgdef_pb_serialize_handlers(Descriptor* desc) {
|
938
|
+
DescriptorPool* pool = ruby_to_DescriptorPool(desc->descriptor_pool);
|
939
|
+
return upb_handlercache_get(pool->pb_serialize_handler_cache, desc->msgdef);
|
795
940
|
}
|
796
941
|
|
797
|
-
static const
|
798
|
-
|
799
|
-
|
800
|
-
|
942
|
+
static const upb_handlers* msgdef_json_serialize_handlers(
|
943
|
+
Descriptor* desc, bool preserve_proto_fieldnames) {
|
944
|
+
DescriptorPool* pool = ruby_to_DescriptorPool(desc->descriptor_pool);
|
945
|
+
if (preserve_proto_fieldnames) {
|
946
|
+
return upb_handlercache_get(pool->json_serialize_handler_preserve_cache,
|
947
|
+
desc->msgdef);
|
948
|
+
} else {
|
949
|
+
return upb_handlercache_get(pool->json_serialize_handler_cache,
|
950
|
+
desc->msgdef);
|
801
951
|
}
|
802
|
-
return desc->json_fill_method;
|
803
952
|
}
|
804
953
|
|
805
954
|
|
@@ -809,7 +958,8 @@ static const upb_json_parsermethod *msgdef_jsonparsermethod(Descriptor* desc) {
|
|
809
958
|
// if any error occurs.
|
810
959
|
#define STACK_ENV_STACKBYTES 4096
|
811
960
|
typedef struct {
|
812
|
-
|
961
|
+
upb_arena *arena;
|
962
|
+
upb_status status;
|
813
963
|
const char* ruby_error_template;
|
814
964
|
char allocbuf[STACK_ENV_STACKBYTES];
|
815
965
|
} stackenv;
|
@@ -817,29 +967,22 @@ typedef struct {
|
|
817
967
|
static void stackenv_init(stackenv* se, const char* errmsg);
|
818
968
|
static void stackenv_uninit(stackenv* se);
|
819
969
|
|
820
|
-
// Callback invoked by upb if any error occurs during parsing or serialization.
|
821
|
-
static bool env_error_func(void* ud, const upb_status* status) {
|
822
|
-
stackenv* se = ud;
|
823
|
-
// Free the env -- rb_raise will longjmp up the stack past the encode/decode
|
824
|
-
// function so it would not otherwise have been freed.
|
825
|
-
stackenv_uninit(se);
|
826
|
-
|
827
|
-
// TODO(haberman): have a way to verify that this is actually a parse error,
|
828
|
-
// instead of just throwing "parse error" unconditionally.
|
829
|
-
rb_raise(cParseError, se->ruby_error_template, upb_status_errmsg(status));
|
830
|
-
// Never reached: rb_raise() always longjmp()s up the stack, past all of our
|
831
|
-
// code, back to Ruby.
|
832
|
-
return false;
|
833
|
-
}
|
834
|
-
|
835
970
|
static void stackenv_init(stackenv* se, const char* errmsg) {
|
836
971
|
se->ruby_error_template = errmsg;
|
837
|
-
|
838
|
-
|
972
|
+
se->arena =
|
973
|
+
upb_arena_init(se->allocbuf, sizeof(se->allocbuf), &upb_alloc_global);
|
974
|
+
upb_status_clear(&se->status);
|
839
975
|
}
|
840
976
|
|
841
977
|
static void stackenv_uninit(stackenv* se) {
|
842
|
-
|
978
|
+
upb_arena_free(se->arena);
|
979
|
+
|
980
|
+
if (!upb_ok(&se->status)) {
|
981
|
+
// TODO(haberman): have a way to verify that this is actually a parse error,
|
982
|
+
// instead of just throwing "parse error" unconditionally.
|
983
|
+
VALUE errmsg = rb_str_new2(upb_status_errmsg(&se->status));
|
984
|
+
rb_raise(cParseError, se->ruby_error_template, errmsg);
|
985
|
+
}
|
843
986
|
}
|
844
987
|
|
845
988
|
/*
|
@@ -867,17 +1010,28 @@ VALUE Message_decode(VALUE klass, VALUE data) {
|
|
867
1010
|
{
|
868
1011
|
const upb_pbdecodermethod* method = msgdef_decodermethod(desc);
|
869
1012
|
const upb_handlers* h = upb_pbdecodermethod_desthandlers(method);
|
1013
|
+
const upb_msgdef* m = upb_handlers_msgdef(h);
|
1014
|
+
VALUE wrapper = Qnil;
|
1015
|
+
void* ptr = msg;
|
870
1016
|
stackenv se;
|
871
1017
|
upb_sink sink;
|
872
1018
|
upb_pbdecoder* decoder;
|
873
|
-
stackenv_init(&se, "Error occurred during parsing: %
|
1019
|
+
stackenv_init(&se, "Error occurred during parsing: %" PRIsVALUE);
|
874
1020
|
|
875
|
-
|
876
|
-
|
1021
|
+
if (is_wrapper(m)) {
|
1022
|
+
ptr = &wrapper;
|
1023
|
+
}
|
1024
|
+
|
1025
|
+
upb_sink_reset(&sink, h, ptr);
|
1026
|
+
decoder = upb_pbdecoder_create(se.arena, method, sink, &se.status);
|
877
1027
|
upb_bufsrc_putbuf(RSTRING_PTR(data), RSTRING_LEN(data),
|
878
1028
|
upb_pbdecoder_input(decoder));
|
879
1029
|
|
880
1030
|
stackenv_uninit(&se);
|
1031
|
+
|
1032
|
+
if (is_wrapper(m)) {
|
1033
|
+
msg_rb = ruby_wrapper_type(msgklass, wrapper);
|
1034
|
+
}
|
881
1035
|
}
|
882
1036
|
|
883
1037
|
return msg_rb;
|
@@ -891,8 +1045,9 @@ VALUE Message_decode(VALUE klass, VALUE data) {
|
|
891
1045
|
* format) under the interpretration given by this message class's definition
|
892
1046
|
* and returns a message object with the corresponding field values.
|
893
1047
|
*
|
894
|
-
*
|
895
|
-
* ignore_unknown_fields: set true to ignore unknown fields (default is to
|
1048
|
+
* @param options [Hash] options for the decoder
|
1049
|
+
* ignore_unknown_fields: set true to ignore unknown fields (default is to
|
1050
|
+
* raise an error)
|
896
1051
|
*/
|
897
1052
|
VALUE Message_decode_json(int argc, VALUE* argv, VALUE klass) {
|
898
1053
|
VALUE descriptor = rb_ivar_get(klass, descriptor_instancevar_interned);
|
@@ -920,6 +1075,7 @@ VALUE Message_decode_json(int argc, VALUE* argv, VALUE klass) {
|
|
920
1075
|
if (TYPE(data) != T_STRING) {
|
921
1076
|
rb_raise(rb_eArgError, "Expected string for JSON data.");
|
922
1077
|
}
|
1078
|
+
|
923
1079
|
// TODO(cfallin): Check and respect string encoding. If not UTF-8, we need to
|
924
1080
|
// convert, because string handlers pass data directly to message string
|
925
1081
|
// fields.
|
@@ -929,15 +1085,23 @@ VALUE Message_decode_json(int argc, VALUE* argv, VALUE klass) {
|
|
929
1085
|
|
930
1086
|
{
|
931
1087
|
const upb_json_parsermethod* method = msgdef_jsonparsermethod(desc);
|
1088
|
+
const upb_handlers* h = get_fill_handlers(desc);
|
1089
|
+
const upb_msgdef* m = upb_handlers_msgdef(h);
|
932
1090
|
stackenv se;
|
933
1091
|
upb_sink sink;
|
934
1092
|
upb_json_parser* parser;
|
935
1093
|
DescriptorPool* pool = ruby_to_DescriptorPool(generated_pool);
|
936
|
-
stackenv_init(&se, "Error occurred during parsing: %
|
1094
|
+
stackenv_init(&se, "Error occurred during parsing: %" PRIsVALUE);
|
1095
|
+
|
1096
|
+
if (is_wrapper(m)) {
|
1097
|
+
rb_raise(
|
1098
|
+
rb_eRuntimeError,
|
1099
|
+
"Parsing a wrapper type from JSON at the top level does not work.");
|
1100
|
+
}
|
937
1101
|
|
938
|
-
upb_sink_reset(&sink,
|
939
|
-
parser = upb_json_parser_create(
|
940
|
-
&
|
1102
|
+
upb_sink_reset(&sink, h, msg);
|
1103
|
+
parser = upb_json_parser_create(se.arena, method, pool->symtab, sink,
|
1104
|
+
&se.status, RTEST(ignore_unknown_fields));
|
941
1105
|
upb_bufsrc_putbuf(RSTRING_PTR(data), RSTRING_LEN(data),
|
942
1106
|
upb_json_parser_input(parser));
|
943
1107
|
|
@@ -953,9 +1117,8 @@ VALUE Message_decode_json(int argc, VALUE* argv, VALUE klass) {
|
|
953
1117
|
|
954
1118
|
/* msgvisitor *****************************************************************/
|
955
1119
|
|
956
|
-
static void putmsg(VALUE msg, const Descriptor* desc,
|
957
|
-
|
958
|
-
bool is_json, bool open_msg);
|
1120
|
+
static void putmsg(VALUE msg, const Descriptor* desc, upb_sink sink, int depth,
|
1121
|
+
bool emit_defaults, bool is_json, bool open_msg);
|
959
1122
|
|
960
1123
|
static upb_selector_t getsel(const upb_fielddef *f, upb_handlertype_t type) {
|
961
1124
|
upb_selector_t ret;
|
@@ -964,7 +1127,7 @@ static upb_selector_t getsel(const upb_fielddef *f, upb_handlertype_t type) {
|
|
964
1127
|
return ret;
|
965
1128
|
}
|
966
1129
|
|
967
|
-
static void putstr(VALUE str, const upb_fielddef *f, upb_sink
|
1130
|
+
static void putstr(VALUE str, const upb_fielddef *f, upb_sink sink) {
|
968
1131
|
upb_sink subsink;
|
969
1132
|
|
970
1133
|
if (str == Qnil) return;
|
@@ -981,12 +1144,12 @@ static void putstr(VALUE str, const upb_fielddef *f, upb_sink *sink) {
|
|
981
1144
|
|
982
1145
|
upb_sink_startstr(sink, getsel(f, UPB_HANDLER_STARTSTR), RSTRING_LEN(str),
|
983
1146
|
&subsink);
|
984
|
-
upb_sink_putstring(
|
1147
|
+
upb_sink_putstring(subsink, getsel(f, UPB_HANDLER_STRING), RSTRING_PTR(str),
|
985
1148
|
RSTRING_LEN(str), NULL);
|
986
1149
|
upb_sink_endstr(sink, getsel(f, UPB_HANDLER_ENDSTR));
|
987
1150
|
}
|
988
1151
|
|
989
|
-
static void putsubmsg(VALUE submsg, const upb_fielddef *f, upb_sink
|
1152
|
+
static void putsubmsg(VALUE submsg, const upb_fielddef *f, upb_sink sink,
|
990
1153
|
int depth, bool emit_defaults, bool is_json) {
|
991
1154
|
upb_sink subsink;
|
992
1155
|
VALUE descriptor;
|
@@ -998,16 +1161,18 @@ static void putsubmsg(VALUE submsg, const upb_fielddef *f, upb_sink *sink,
|
|
998
1161
|
subdesc = ruby_to_Descriptor(descriptor);
|
999
1162
|
|
1000
1163
|
upb_sink_startsubmsg(sink, getsel(f, UPB_HANDLER_STARTSUBMSG), &subsink);
|
1001
|
-
putmsg(submsg, subdesc,
|
1164
|
+
putmsg(submsg, subdesc, subsink, depth + 1, emit_defaults, is_json, true);
|
1002
1165
|
upb_sink_endsubmsg(sink, getsel(f, UPB_HANDLER_ENDSUBMSG));
|
1003
1166
|
}
|
1004
1167
|
|
1005
|
-
static void putary(VALUE ary, const upb_fielddef
|
1006
|
-
|
1168
|
+
static void putary(VALUE ary, const upb_fielddef* f, upb_sink sink, int depth,
|
1169
|
+
bool emit_defaults, bool is_json) {
|
1007
1170
|
upb_sink subsink;
|
1008
1171
|
upb_fieldtype_t type = upb_fielddef_type(f);
|
1009
1172
|
upb_selector_t sel = 0;
|
1010
1173
|
int size;
|
1174
|
+
int i;
|
1175
|
+
VALUE type_class = ruby_to_RepeatedField(ary)->field_type_class;
|
1011
1176
|
|
1012
1177
|
if (ary == Qnil) return;
|
1013
1178
|
if (!emit_defaults && NUM2INT(RepeatedField_length(ary)) == 0) return;
|
@@ -1021,12 +1186,12 @@ static void putary(VALUE ary, const upb_fielddef *f, upb_sink *sink,
|
|
1021
1186
|
sel = getsel(f, upb_handlers_getprimitivehandlertype(f));
|
1022
1187
|
}
|
1023
1188
|
|
1024
|
-
for (
|
1189
|
+
for (i = 0; i < size; i++) {
|
1025
1190
|
void* memory = RepeatedField_index_native(ary, i);
|
1026
1191
|
switch (type) {
|
1027
|
-
#define T(upbtypeconst, upbtype, ctype)
|
1028
|
-
case upbtypeconst:
|
1029
|
-
upb_sink_put##upbtype(
|
1192
|
+
#define T(upbtypeconst, upbtype, ctype) \
|
1193
|
+
case upbtypeconst: \
|
1194
|
+
upb_sink_put##upbtype(subsink, sel, *((ctype*)memory)); \
|
1030
1195
|
break;
|
1031
1196
|
|
1032
1197
|
T(UPB_TYPE_FLOAT, float, float)
|
@@ -1040,12 +1205,13 @@ static void putary(VALUE ary, const upb_fielddef *f, upb_sink *sink,
|
|
1040
1205
|
|
1041
1206
|
case UPB_TYPE_STRING:
|
1042
1207
|
case UPB_TYPE_BYTES:
|
1043
|
-
putstr(*((VALUE *)memory), f,
|
1208
|
+
putstr(*((VALUE *)memory), f, subsink);
|
1044
1209
|
break;
|
1045
|
-
case UPB_TYPE_MESSAGE:
|
1046
|
-
|
1047
|
-
|
1210
|
+
case UPB_TYPE_MESSAGE: {
|
1211
|
+
VALUE val = native_slot_get(UPB_TYPE_MESSAGE, type_class, memory);
|
1212
|
+
putsubmsg(val, f, subsink, depth, emit_defaults, is_json);
|
1048
1213
|
break;
|
1214
|
+
}
|
1049
1215
|
|
1050
1216
|
#undef T
|
1051
1217
|
|
@@ -1054,14 +1220,16 @@ static void putary(VALUE ary, const upb_fielddef *f, upb_sink *sink,
|
|
1054
1220
|
upb_sink_endseq(sink, getsel(f, UPB_HANDLER_ENDSEQ));
|
1055
1221
|
}
|
1056
1222
|
|
1057
|
-
static void put_ruby_value(VALUE value,
|
1058
|
-
|
1059
|
-
VALUE type_class,
|
1060
|
-
int depth,
|
1061
|
-
upb_sink *sink,
|
1062
|
-
bool emit_defaults,
|
1223
|
+
static void put_ruby_value(VALUE value, const upb_fielddef* f, VALUE type_class,
|
1224
|
+
int depth, upb_sink sink, bool emit_defaults,
|
1063
1225
|
bool is_json) {
|
1064
1226
|
upb_selector_t sel = 0;
|
1227
|
+
|
1228
|
+
if (depth > ENCODE_MAX_NESTING) {
|
1229
|
+
rb_raise(rb_eRuntimeError,
|
1230
|
+
"Maximum recursion depth exceeded during encoding.");
|
1231
|
+
}
|
1232
|
+
|
1065
1233
|
if (upb_fielddef_isprimitive(f)) {
|
1066
1234
|
sel = getsel(f, upb_handlers_getprimitivehandlertype(f));
|
1067
1235
|
}
|
@@ -1104,8 +1272,8 @@ static void put_ruby_value(VALUE value,
|
|
1104
1272
|
}
|
1105
1273
|
}
|
1106
1274
|
|
1107
|
-
static void putmap(VALUE map, const upb_fielddef
|
1108
|
-
|
1275
|
+
static void putmap(VALUE map, const upb_fielddef* f, upb_sink sink, int depth,
|
1276
|
+
bool emit_defaults, bool is_json) {
|
1109
1277
|
Map* self;
|
1110
1278
|
upb_sink subsink;
|
1111
1279
|
const upb_fielddef* key_field;
|
@@ -1129,17 +1297,17 @@ static void putmap(VALUE map, const upb_fielddef *f, upb_sink *sink,
|
|
1129
1297
|
upb_status status;
|
1130
1298
|
|
1131
1299
|
upb_sink entry_sink;
|
1132
|
-
upb_sink_startsubmsg(
|
1300
|
+
upb_sink_startsubmsg(subsink, getsel(f, UPB_HANDLER_STARTSUBMSG),
|
1133
1301
|
&entry_sink);
|
1134
|
-
upb_sink_startmsg(
|
1302
|
+
upb_sink_startmsg(entry_sink);
|
1135
1303
|
|
1136
|
-
put_ruby_value(key, key_field, Qnil, depth + 1,
|
1137
|
-
|
1304
|
+
put_ruby_value(key, key_field, Qnil, depth + 1, entry_sink, emit_defaults,
|
1305
|
+
is_json);
|
1138
1306
|
put_ruby_value(value, value_field, self->value_type_class, depth + 1,
|
1139
|
-
|
1307
|
+
entry_sink, emit_defaults, is_json);
|
1140
1308
|
|
1141
|
-
upb_sink_endmsg(
|
1142
|
-
upb_sink_endsubmsg(
|
1309
|
+
upb_sink_endmsg(entry_sink, &status);
|
1310
|
+
upb_sink_endsubmsg(subsink, getsel(f, UPB_HANDLER_ENDSUBMSG));
|
1143
1311
|
}
|
1144
1312
|
|
1145
1313
|
upb_sink_endseq(sink, getsel(f, UPB_HANDLER_ENDSEQ));
|
@@ -1148,8 +1316,8 @@ static void putmap(VALUE map, const upb_fielddef *f, upb_sink *sink,
|
|
1148
1316
|
static const upb_handlers* msgdef_json_serialize_handlers(
|
1149
1317
|
Descriptor* desc, bool preserve_proto_fieldnames);
|
1150
1318
|
|
1151
|
-
static void putjsonany(VALUE msg_rb, const Descriptor* desc,
|
1152
|
-
|
1319
|
+
static void putjsonany(VALUE msg_rb, const Descriptor* desc, upb_sink sink,
|
1320
|
+
int depth, bool emit_defaults) {
|
1153
1321
|
upb_status status;
|
1154
1322
|
MessageHeader* msg = NULL;
|
1155
1323
|
const upb_fielddef* type_field = upb_msgdef_itof(desc->msgdef, UPB_ANY_TYPE);
|
@@ -1196,16 +1364,14 @@ static void putjsonany(VALUE msg_rb, const Descriptor* desc,
|
|
1196
1364
|
{
|
1197
1365
|
uint32_t value_offset;
|
1198
1366
|
VALUE value_str_rb;
|
1199
|
-
const char* value_str;
|
1200
1367
|
size_t value_len;
|
1201
1368
|
|
1202
1369
|
value_offset = desc->layout->fields[upb_fielddef_index(value_field)].offset;
|
1203
1370
|
value_str_rb = DEREF(Message_data(msg), value_offset, VALUE);
|
1204
|
-
value_str = RSTRING_PTR(value_str_rb);
|
1205
1371
|
value_len = RSTRING_LEN(value_str_rb);
|
1206
1372
|
|
1207
1373
|
if (value_len > 0) {
|
1208
|
-
VALUE payload_desc_rb =
|
1374
|
+
VALUE payload_desc_rb = get_msgdef_obj(generated_pool, payload_type);
|
1209
1375
|
Descriptor* payload_desc = ruby_to_Descriptor(payload_desc_rb);
|
1210
1376
|
VALUE payload_class = Descriptor_msgclass(payload_desc_rb);
|
1211
1377
|
upb_sink subsink;
|
@@ -1223,8 +1389,8 @@ static void putjsonany(VALUE msg_rb, const Descriptor* desc,
|
|
1223
1389
|
|
1224
1390
|
subsink.handlers =
|
1225
1391
|
msgdef_json_serialize_handlers(payload_desc, true);
|
1226
|
-
subsink.closure = sink
|
1227
|
-
putmsg(payload_msg_rb, payload_desc,
|
1392
|
+
subsink.closure = sink.closure;
|
1393
|
+
putmsg(payload_msg_rb, payload_desc, subsink, depth, emit_defaults, true,
|
1228
1394
|
is_wellknown);
|
1229
1395
|
}
|
1230
1396
|
}
|
@@ -1232,18 +1398,53 @@ static void putjsonany(VALUE msg_rb, const Descriptor* desc,
|
|
1232
1398
|
upb_sink_endmsg(sink, &status);
|
1233
1399
|
}
|
1234
1400
|
|
1401
|
+
static void putjsonlistvalue(
|
1402
|
+
VALUE msg_rb, const Descriptor* desc,
|
1403
|
+
upb_sink sink, int depth, bool emit_defaults) {
|
1404
|
+
upb_status status;
|
1405
|
+
upb_sink subsink;
|
1406
|
+
MessageHeader* msg = NULL;
|
1407
|
+
const upb_fielddef* f = upb_msgdef_itof(desc->msgdef, 1);
|
1408
|
+
uint32_t offset =
|
1409
|
+
desc->layout->fields[upb_fielddef_index(f)].offset +
|
1410
|
+
sizeof(MessageHeader);
|
1411
|
+
VALUE ary;
|
1412
|
+
|
1413
|
+
TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg);
|
1414
|
+
|
1415
|
+
upb_sink_startmsg(sink);
|
1416
|
+
|
1417
|
+
ary = DEREF(msg, offset, VALUE);
|
1418
|
+
|
1419
|
+
if (ary == Qnil || RepeatedField_size(ary) == 0) {
|
1420
|
+
upb_sink_startseq(sink, getsel(f, UPB_HANDLER_STARTSEQ), &subsink);
|
1421
|
+
upb_sink_endseq(sink, getsel(f, UPB_HANDLER_ENDSEQ));
|
1422
|
+
} else {
|
1423
|
+
putary(ary, f, sink, depth, emit_defaults, true);
|
1424
|
+
}
|
1425
|
+
|
1426
|
+
upb_sink_endmsg(sink, &status);
|
1427
|
+
}
|
1428
|
+
|
1235
1429
|
static void putmsg(VALUE msg_rb, const Descriptor* desc,
|
1236
|
-
upb_sink
|
1430
|
+
upb_sink sink, int depth, bool emit_defaults,
|
1237
1431
|
bool is_json, bool open_msg) {
|
1238
1432
|
MessageHeader* msg;
|
1239
1433
|
upb_msg_field_iter i;
|
1240
1434
|
upb_status status;
|
1241
1435
|
|
1242
|
-
if (is_json &&
|
1436
|
+
if (is_json &&
|
1437
|
+
upb_msgdef_wellknowntype(desc->msgdef) == UPB_WELLKNOWN_ANY) {
|
1243
1438
|
putjsonany(msg_rb, desc, sink, depth, emit_defaults);
|
1244
1439
|
return;
|
1245
1440
|
}
|
1246
1441
|
|
1442
|
+
if (is_json &&
|
1443
|
+
upb_msgdef_wellknowntype(desc->msgdef) == UPB_WELLKNOWN_LISTVALUE) {
|
1444
|
+
putjsonlistvalue(msg_rb, desc, sink, depth, emit_defaults);
|
1445
|
+
return;
|
1446
|
+
}
|
1447
|
+
|
1247
1448
|
if (open_msg) {
|
1248
1449
|
upb_sink_startmsg(sink);
|
1249
1450
|
}
|
@@ -1268,19 +1469,18 @@ static void putmsg(VALUE msg_rb, const Descriptor* desc,
|
|
1268
1469
|
!upb_msg_field_done(&i);
|
1269
1470
|
upb_msg_field_next(&i)) {
|
1270
1471
|
upb_fielddef *f = upb_msg_iter_field(&i);
|
1472
|
+
const upb_oneofdef *oneof = upb_fielddef_containingoneof(f);
|
1271
1473
|
bool is_matching_oneof = false;
|
1272
1474
|
uint32_t offset =
|
1273
1475
|
desc->layout->fields[upb_fielddef_index(f)].offset +
|
1274
1476
|
sizeof(MessageHeader);
|
1275
1477
|
|
1276
|
-
if (
|
1277
|
-
uint32_t
|
1278
|
-
desc->layout
|
1279
|
-
sizeof(MessageHeader);
|
1478
|
+
if (oneof) {
|
1479
|
+
uint32_t oneof_case =
|
1480
|
+
slot_read_oneof_case(desc->layout, Message_data(msg), oneof);
|
1280
1481
|
// For a oneof, check that this field is actually present -- skip all the
|
1281
1482
|
// below if not.
|
1282
|
-
if (
|
1283
|
-
upb_fielddef_number(f)) {
|
1483
|
+
if (oneof_case != upb_fielddef_number(f)) {
|
1284
1484
|
continue;
|
1285
1485
|
}
|
1286
1486
|
// Otherwise, fall through to the appropriate singular-field handler
|
@@ -1312,25 +1512,26 @@ static void putmsg(VALUE msg_rb, const Descriptor* desc,
|
|
1312
1512
|
putstr(str, f, sink);
|
1313
1513
|
}
|
1314
1514
|
} else if (upb_fielddef_issubmsg(f)) {
|
1315
|
-
|
1316
|
-
|
1515
|
+
// OPT: could try to avoid the layout_get() (which will expand lazy
|
1516
|
+
// wrappers).
|
1517
|
+
VALUE val = layout_get(desc->layout, Message_data(msg), f);
|
1518
|
+
putsubmsg(val, f, sink, depth, emit_defaults, is_json);
|
1317
1519
|
} else {
|
1318
1520
|
upb_selector_t sel = getsel(f, upb_handlers_getprimitivehandlertype(f));
|
1319
1521
|
|
1320
|
-
#define T(upbtypeconst, upbtype, ctype, default_value)
|
1321
|
-
case upbtypeconst: {
|
1322
|
-
|
1323
|
-
|
1324
|
-
|
1325
|
-
|
1326
|
-
|
1327
|
-
|
1328
|
-
|
1329
|
-
|
1330
|
-
|
1331
|
-
|
1332
|
-
|
1333
|
-
break;
|
1522
|
+
#define T(upbtypeconst, upbtype, ctype, default_value) \
|
1523
|
+
case upbtypeconst: { \
|
1524
|
+
ctype value = DEREF(msg, offset, ctype); \
|
1525
|
+
bool is_default = false; \
|
1526
|
+
if (upb_fielddef_haspresence(f)) { \
|
1527
|
+
is_default = layout_has(desc->layout, Message_data(msg), f) == Qfalse; \
|
1528
|
+
} else if (upb_msgdef_syntax(desc->msgdef) == UPB_SYNTAX_PROTO3) { \
|
1529
|
+
is_default = default_value == value; \
|
1530
|
+
} \
|
1531
|
+
if (is_matching_oneof || emit_defaults || !is_default) { \
|
1532
|
+
upb_sink_put##upbtype(sink, sel, value); \
|
1533
|
+
} \
|
1534
|
+
} break;
|
1334
1535
|
|
1335
1536
|
switch (upb_fielddef_type(f)) {
|
1336
1537
|
T(UPB_TYPE_FLOAT, float, float, 0.0)
|
@@ -1348,13 +1549,14 @@ static void putmsg(VALUE msg_rb, const Descriptor* desc,
|
|
1348
1549
|
}
|
1349
1550
|
|
1350
1551
|
#undef T
|
1351
|
-
|
1352
1552
|
}
|
1353
1553
|
}
|
1354
1554
|
|
1355
|
-
|
1356
|
-
|
1357
|
-
|
1555
|
+
{
|
1556
|
+
stringsink* unknown = msg->unknown_fields;
|
1557
|
+
if (unknown != NULL) {
|
1558
|
+
upb_sink_putunknown(sink, unknown->ptr, unknown->len);
|
1559
|
+
}
|
1358
1560
|
}
|
1359
1561
|
|
1360
1562
|
if (open_msg) {
|
@@ -1362,33 +1564,6 @@ static void putmsg(VALUE msg_rb, const Descriptor* desc,
|
|
1362
1564
|
}
|
1363
1565
|
}
|
1364
1566
|
|
1365
|
-
static const upb_handlers* msgdef_pb_serialize_handlers(Descriptor* desc) {
|
1366
|
-
if (desc->pb_serialize_handlers == NULL) {
|
1367
|
-
desc->pb_serialize_handlers =
|
1368
|
-
upb_pb_encoder_newhandlers(desc->msgdef, &desc->pb_serialize_handlers);
|
1369
|
-
}
|
1370
|
-
return desc->pb_serialize_handlers;
|
1371
|
-
}
|
1372
|
-
|
1373
|
-
static const upb_handlers* msgdef_json_serialize_handlers(
|
1374
|
-
Descriptor* desc, bool preserve_proto_fieldnames) {
|
1375
|
-
if (preserve_proto_fieldnames) {
|
1376
|
-
if (desc->json_serialize_handlers == NULL) {
|
1377
|
-
desc->json_serialize_handlers =
|
1378
|
-
upb_json_printer_newhandlers(
|
1379
|
-
desc->msgdef, true, &desc->json_serialize_handlers);
|
1380
|
-
}
|
1381
|
-
return desc->json_serialize_handlers;
|
1382
|
-
} else {
|
1383
|
-
if (desc->json_serialize_handlers_preserve == NULL) {
|
1384
|
-
desc->json_serialize_handlers_preserve =
|
1385
|
-
upb_json_printer_newhandlers(
|
1386
|
-
desc->msgdef, false, &desc->json_serialize_handlers_preserve);
|
1387
|
-
}
|
1388
|
-
return desc->json_serialize_handlers_preserve;
|
1389
|
-
}
|
1390
|
-
}
|
1391
|
-
|
1392
1567
|
/*
|
1393
1568
|
* call-seq:
|
1394
1569
|
* MessageClass.encode(msg) => bytes
|
@@ -1411,8 +1586,8 @@ VALUE Message_encode(VALUE klass, VALUE msg_rb) {
|
|
1411
1586
|
upb_pb_encoder* encoder;
|
1412
1587
|
VALUE ret;
|
1413
1588
|
|
1414
|
-
stackenv_init(&se, "Error occurred during encoding: %
|
1415
|
-
encoder = upb_pb_encoder_create(
|
1589
|
+
stackenv_init(&se, "Error occurred during encoding: %" PRIsVALUE);
|
1590
|
+
encoder = upb_pb_encoder_create(se.arena, serialize_handlers, sink.sink);
|
1416
1591
|
|
1417
1592
|
putmsg(msg_rb, desc, upb_pb_encoder_input(encoder), 0, false, false, true);
|
1418
1593
|
|
@@ -1469,8 +1644,8 @@ VALUE Message_encode_json(int argc, VALUE* argv, VALUE klass) {
|
|
1469
1644
|
stackenv se;
|
1470
1645
|
VALUE ret;
|
1471
1646
|
|
1472
|
-
stackenv_init(&se, "Error occurred during encoding: %
|
1473
|
-
printer = upb_json_printer_create(
|
1647
|
+
stackenv_init(&se, "Error occurred during encoding: %" PRIsVALUE);
|
1648
|
+
printer = upb_json_printer_create(se.arena, serialize_handlers, sink.sink);
|
1474
1649
|
|
1475
1650
|
putmsg(msg_rb, desc, upb_json_printer_input(printer), 0,
|
1476
1651
|
RTEST(emit_defaults), true, true);
|
@@ -1490,28 +1665,29 @@ static void discard_unknown(VALUE msg_rb, const Descriptor* desc) {
|
|
1490
1665
|
|
1491
1666
|
TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg);
|
1492
1667
|
|
1493
|
-
|
1494
|
-
|
1495
|
-
|
1496
|
-
|
1668
|
+
{
|
1669
|
+
stringsink* unknown = msg->unknown_fields;
|
1670
|
+
if (unknown != NULL) {
|
1671
|
+
stringsink_uninit(unknown);
|
1672
|
+
msg->unknown_fields = NULL;
|
1673
|
+
}
|
1497
1674
|
}
|
1498
1675
|
|
1499
1676
|
for (upb_msg_field_begin(&it, desc->msgdef);
|
1500
1677
|
!upb_msg_field_done(&it);
|
1501
1678
|
upb_msg_field_next(&it)) {
|
1502
1679
|
upb_fielddef *f = upb_msg_iter_field(&it);
|
1680
|
+
const upb_oneofdef *oneof = upb_fielddef_containingoneof(f);
|
1503
1681
|
uint32_t offset =
|
1504
1682
|
desc->layout->fields[upb_fielddef_index(f)].offset +
|
1505
1683
|
sizeof(MessageHeader);
|
1506
1684
|
|
1507
|
-
if (
|
1508
|
-
uint32_t
|
1509
|
-
desc->layout
|
1510
|
-
sizeof(MessageHeader);
|
1685
|
+
if (oneof) {
|
1686
|
+
uint32_t oneof_case =
|
1687
|
+
slot_read_oneof_case(desc->layout, Message_data(msg), oneof);
|
1511
1688
|
// For a oneof, check that this field is actually present -- skip all the
|
1512
1689
|
// below if not.
|
1513
|
-
if (
|
1514
|
-
upb_fielddef_number(f)) {
|
1690
|
+
if (oneof_case != upb_fielddef_number(f)) {
|
1515
1691
|
continue;
|
1516
1692
|
}
|
1517
1693
|
// Otherwise, fall through to the appropriate singular-field handler
|
@@ -1523,10 +1699,12 @@ static void discard_unknown(VALUE msg_rb, const Descriptor* desc) {
|
|
1523
1699
|
}
|
1524
1700
|
|
1525
1701
|
if (is_map_field(f)) {
|
1702
|
+
VALUE map;
|
1703
|
+
Map_iter map_it;
|
1704
|
+
|
1526
1705
|
if (!upb_fielddef_issubmsg(map_field_value(f))) continue;
|
1527
|
-
|
1706
|
+
map = DEREF(msg, offset, VALUE);
|
1528
1707
|
if (map == Qnil) continue;
|
1529
|
-
Map_iter map_it;
|
1530
1708
|
for (Map_begin(map, &map_it); !Map_done(&map_it); Map_next(&map_it)) {
|
1531
1709
|
VALUE submsg = Map_iter_value(&map_it);
|
1532
1710
|
VALUE descriptor = rb_ivar_get(submsg, descriptor_instancevar_interned);
|
@@ -1535,9 +1713,12 @@ static void discard_unknown(VALUE msg_rb, const Descriptor* desc) {
|
|
1535
1713
|
}
|
1536
1714
|
} else if (upb_fielddef_isseq(f)) {
|
1537
1715
|
VALUE ary = DEREF(msg, offset, VALUE);
|
1716
|
+
int size;
|
1717
|
+
int i;
|
1718
|
+
|
1538
1719
|
if (ary == Qnil) continue;
|
1539
|
-
|
1540
|
-
for (
|
1720
|
+
size = NUM2INT(RepeatedField_length(ary));
|
1721
|
+
for (i = 0; i < size; i++) {
|
1541
1722
|
void* memory = RepeatedField_index_native(ary, i);
|
1542
1723
|
VALUE submsg = *((VALUE *)memory);
|
1543
1724
|
VALUE descriptor = rb_ivar_get(submsg, descriptor_instancevar_interned);
|
@@ -1546,9 +1727,12 @@ static void discard_unknown(VALUE msg_rb, const Descriptor* desc) {
|
|
1546
1727
|
}
|
1547
1728
|
} else {
|
1548
1729
|
VALUE submsg = DEREF(msg, offset, VALUE);
|
1730
|
+
VALUE descriptor;
|
1731
|
+
const Descriptor* subdesc;
|
1732
|
+
|
1549
1733
|
if (submsg == Qnil) continue;
|
1550
|
-
|
1551
|
-
|
1734
|
+
descriptor = rb_ivar_get(submsg, descriptor_instancevar_interned);
|
1735
|
+
subdesc = ruby_to_Descriptor(descriptor);
|
1552
1736
|
discard_unknown(submsg, subdesc);
|
1553
1737
|
}
|
1554
1738
|
}
|