google-protobuf 3.7.0 → 3.12.0
Sign up to get free protection for your applications and to get access to all the features.
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
@@ -30,6 +30,10 @@
|
|
30
30
|
|
31
31
|
#include "protobuf.h"
|
32
32
|
|
33
|
+
VALUE initialize_rb_class_with_no_args(VALUE klass) {
|
34
|
+
return rb_funcall(klass, rb_intern("new"), 0);
|
35
|
+
}
|
36
|
+
|
33
37
|
// This function is equivalent to rb_str_cat(), but unlike the real
|
34
38
|
// rb_str_cat(), it doesn't leak memory in some versions of Ruby.
|
35
39
|
// For more information, see:
|
@@ -44,6 +48,23 @@ VALUE noleak_rb_str_cat(VALUE rb_str, const char *str, long len) {
|
|
44
48
|
return rb_str;
|
45
49
|
}
|
46
50
|
|
51
|
+
bool is_wrapper(const upb_msgdef* m) {
|
52
|
+
switch (upb_msgdef_wellknowntype(m)) {
|
53
|
+
case UPB_WELLKNOWN_DOUBLEVALUE:
|
54
|
+
case UPB_WELLKNOWN_FLOATVALUE:
|
55
|
+
case UPB_WELLKNOWN_INT64VALUE:
|
56
|
+
case UPB_WELLKNOWN_UINT64VALUE:
|
57
|
+
case UPB_WELLKNOWN_INT32VALUE:
|
58
|
+
case UPB_WELLKNOWN_UINT32VALUE:
|
59
|
+
case UPB_WELLKNOWN_STRINGVALUE:
|
60
|
+
case UPB_WELLKNOWN_BYTESVALUE:
|
61
|
+
case UPB_WELLKNOWN_BOOLVALUE:
|
62
|
+
return true;
|
63
|
+
default:
|
64
|
+
return false;
|
65
|
+
}
|
66
|
+
}
|
67
|
+
|
47
68
|
// The code below also comes from upb's prototype Ruby binding, developed by
|
48
69
|
// haberman@.
|
49
70
|
|
@@ -117,19 +138,26 @@ static const void* newhandlerdata(upb_handlers* h, uint32_t ofs, int32_t hasbit)
|
|
117
138
|
typedef struct {
|
118
139
|
size_t ofs;
|
119
140
|
int32_t hasbit;
|
120
|
-
|
141
|
+
upb_fieldtype_t wrapped_type; // Only for wrappers.
|
142
|
+
VALUE subklass;
|
121
143
|
} submsg_handlerdata_t;
|
122
144
|
|
123
145
|
// Creates a handlerdata that contains offset and submessage type information.
|
124
146
|
static const void *newsubmsghandlerdata(upb_handlers* h,
|
147
|
+
const upb_fielddef *f,
|
125
148
|
uint32_t ofs,
|
126
149
|
int32_t hasbit,
|
127
|
-
|
150
|
+
VALUE subklass) {
|
128
151
|
submsg_handlerdata_t *hd = ALLOC(submsg_handlerdata_t);
|
152
|
+
const upb_msgdef *subm = upb_fielddef_msgsubdef(f);
|
129
153
|
hd->ofs = ofs;
|
130
154
|
hd->hasbit = hasbit;
|
131
|
-
hd->
|
155
|
+
hd->subklass = subklass;
|
132
156
|
upb_handlers_addcleanup(h, hd, xfree);
|
157
|
+
if (is_wrapper(subm)) {
|
158
|
+
const upb_fielddef *value_f = upb_msgdef_itof(subm, 1);
|
159
|
+
hd->wrapped_type = upb_fielddef_type(value_f);
|
160
|
+
}
|
133
161
|
return hd;
|
134
162
|
}
|
135
163
|
|
@@ -137,13 +165,14 @@ typedef struct {
|
|
137
165
|
size_t ofs; // union data slot
|
138
166
|
size_t case_ofs; // oneof_case field
|
139
167
|
uint32_t oneof_case_num; // oneof-case number to place in oneof_case field
|
140
|
-
|
168
|
+
VALUE subklass;
|
141
169
|
} oneof_handlerdata_t;
|
142
170
|
|
143
171
|
static const void *newoneofhandlerdata(upb_handlers *h,
|
144
172
|
uint32_t ofs,
|
145
173
|
uint32_t case_ofs,
|
146
|
-
const upb_fielddef *f
|
174
|
+
const upb_fielddef *f,
|
175
|
+
const Descriptor* desc) {
|
147
176
|
oneof_handlerdata_t *hd = ALLOC(oneof_handlerdata_t);
|
148
177
|
hd->ofs = ofs;
|
149
178
|
hd->case_ofs = case_ofs;
|
@@ -154,11 +183,10 @@ static const void *newoneofhandlerdata(upb_handlers *h,
|
|
154
183
|
// create a separate ID space. In addition, using the field tag number here
|
155
184
|
// lets us easily look up the field in the oneof accessor.
|
156
185
|
hd->oneof_case_num = upb_fielddef_number(f);
|
157
|
-
if (
|
158
|
-
hd->
|
159
|
-
} else {
|
160
|
-
hd->md = NULL;
|
186
|
+
if (is_value_field(f)) {
|
187
|
+
hd->oneof_case_num |= ONEOF_CASE_MASK;
|
161
188
|
}
|
189
|
+
hd->subklass = field_type_class(desc->layout, f);
|
162
190
|
upb_handlers_addcleanup(h, hd, xfree);
|
163
191
|
return hd;
|
164
192
|
}
|
@@ -254,13 +282,13 @@ static size_t stringdata_handler(void* closure, const void* hd,
|
|
254
282
|
}
|
255
283
|
|
256
284
|
static bool stringdata_end_handler(void* closure, const void* hd) {
|
257
|
-
VALUE rb_str = closure;
|
285
|
+
VALUE rb_str = (VALUE)closure;
|
258
286
|
rb_obj_freeze(rb_str);
|
259
287
|
return true;
|
260
288
|
}
|
261
289
|
|
262
290
|
static bool appendstring_end_handler(void* closure, const void* hd) {
|
263
|
-
VALUE rb_str = closure;
|
291
|
+
VALUE rb_str = (VALUE)closure;
|
264
292
|
rb_obj_freeze(rb_str);
|
265
293
|
return true;
|
266
294
|
}
|
@@ -269,31 +297,36 @@ static bool appendstring_end_handler(void* closure, const void* hd) {
|
|
269
297
|
static void *appendsubmsg_handler(void *closure, const void *hd) {
|
270
298
|
VALUE ary = (VALUE)closure;
|
271
299
|
const submsg_handlerdata_t *submsgdata = hd;
|
272
|
-
VALUE subdesc =
|
273
|
-
get_def_obj((void*)submsgdata->md);
|
274
|
-
VALUE subklass = Descriptor_msgclass(subdesc);
|
275
300
|
MessageHeader* submsg;
|
276
301
|
|
277
|
-
VALUE submsg_rb =
|
302
|
+
VALUE submsg_rb = initialize_rb_class_with_no_args(submsgdata->subklass);
|
278
303
|
RepeatedField_push(ary, submsg_rb);
|
279
304
|
|
280
305
|
TypedData_Get_Struct(submsg_rb, MessageHeader, &Message_type, submsg);
|
281
306
|
return submsg;
|
282
307
|
}
|
283
308
|
|
309
|
+
// Appends a wrapper to a repeated field (a regular Ruby array for now).
|
310
|
+
static void *appendwrapper_handler(void *closure, const void *hd) {
|
311
|
+
VALUE ary = (VALUE)closure;
|
312
|
+
int size = RepeatedField_size(ary);
|
313
|
+
(void)hd;
|
314
|
+
|
315
|
+
RepeatedField_push(ary, Qnil);
|
316
|
+
|
317
|
+
return RepeatedField_index_native(ary, size);
|
318
|
+
}
|
319
|
+
|
284
320
|
// Sets a non-repeated submessage field in a message.
|
285
321
|
static void *submsg_handler(void *closure, const void *hd) {
|
286
322
|
MessageHeader* msg = closure;
|
287
323
|
const submsg_handlerdata_t* submsgdata = hd;
|
288
|
-
VALUE subdesc =
|
289
|
-
get_def_obj((void*)submsgdata->md);
|
290
|
-
VALUE subklass = Descriptor_msgclass(subdesc);
|
291
324
|
VALUE submsg_rb;
|
292
325
|
MessageHeader* submsg;
|
293
326
|
|
294
327
|
if (DEREF(msg, submsgdata->ofs, VALUE) == Qnil) {
|
295
328
|
DEREF(msg, submsgdata->ofs, VALUE) =
|
296
|
-
|
329
|
+
initialize_rb_class_with_no_args(submsgdata->subklass);
|
297
330
|
}
|
298
331
|
|
299
332
|
set_hasbit(closure, submsgdata->hasbit);
|
@@ -304,16 +337,48 @@ static void *submsg_handler(void *closure, const void *hd) {
|
|
304
337
|
return submsg;
|
305
338
|
}
|
306
339
|
|
340
|
+
static void* startwrapper(void* closure, const void* hd) {
|
341
|
+
const submsg_handlerdata_t* submsgdata = hd;
|
342
|
+
char* msg = closure;
|
343
|
+
VALUE* field = (VALUE*)(msg + submsgdata->ofs);
|
344
|
+
|
345
|
+
set_hasbit(closure, submsgdata->hasbit);
|
346
|
+
|
347
|
+
switch (submsgdata->wrapped_type) {
|
348
|
+
case UPB_TYPE_FLOAT:
|
349
|
+
case UPB_TYPE_DOUBLE:
|
350
|
+
*field = DBL2NUM(0);
|
351
|
+
break;
|
352
|
+
case UPB_TYPE_BOOL:
|
353
|
+
*field = Qfalse;
|
354
|
+
break;
|
355
|
+
case UPB_TYPE_STRING:
|
356
|
+
*field = get_frozen_string(NULL, 0, false);
|
357
|
+
break;
|
358
|
+
case UPB_TYPE_BYTES:
|
359
|
+
*field = get_frozen_string(NULL, 0, true);
|
360
|
+
break;
|
361
|
+
case UPB_TYPE_ENUM:
|
362
|
+
case UPB_TYPE_INT32:
|
363
|
+
case UPB_TYPE_INT64:
|
364
|
+
case UPB_TYPE_UINT32:
|
365
|
+
case UPB_TYPE_UINT64:
|
366
|
+
*field = INT2NUM(0);
|
367
|
+
break;
|
368
|
+
case UPB_TYPE_MESSAGE:
|
369
|
+
rb_raise(rb_eRuntimeError,
|
370
|
+
"Internal logic error with well-known types.");
|
371
|
+
}
|
372
|
+
|
373
|
+
return field;
|
374
|
+
}
|
375
|
+
|
307
376
|
// Handler data for startmap/endmap handlers.
|
308
377
|
typedef struct {
|
309
378
|
size_t ofs;
|
310
379
|
upb_fieldtype_t key_field_type;
|
311
380
|
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;
|
381
|
+
VALUE subklass;
|
317
382
|
} map_handlerdata_t;
|
318
383
|
|
319
384
|
// Temporary frame for map parsing: at the beginning of a map entry message, a
|
@@ -349,33 +414,34 @@ rb_data_type_t MapParseFrame_type = {
|
|
349
414
|
{ MapParseFrame_mark, MapParseFrame_free, NULL },
|
350
415
|
};
|
351
416
|
|
352
|
-
static map_parse_frame_t* map_push_frame(VALUE map,
|
353
|
-
const map_handlerdata_t* handlerdata) {
|
354
|
-
map_parse_frame_t* frame = ALLOC(map_parse_frame_t);
|
355
|
-
frame->handlerdata = handlerdata;
|
356
|
-
frame->map = map;
|
357
|
-
native_slot_init(handlerdata->key_field_type, &frame->key_storage);
|
358
|
-
native_slot_init(handlerdata->value_field_type, &frame->value_storage);
|
359
|
-
|
360
|
-
Map_set_frame(map,
|
361
|
-
TypedData_Wrap_Struct(rb_cObject, &MapParseFrame_type, frame));
|
362
|
-
|
363
|
-
return frame;
|
364
|
-
}
|
365
|
-
|
366
417
|
// Handler to begin a map entry: allocates a temporary frame. This is the
|
367
418
|
// 'startsubmsg' handler on the msgdef that contains the map field.
|
368
|
-
static void *
|
419
|
+
static void *startmap_handler(void *closure, const void *hd) {
|
369
420
|
MessageHeader* msg = closure;
|
370
421
|
const map_handlerdata_t* mapdata = hd;
|
422
|
+
map_parse_frame_t* frame = ALLOC(map_parse_frame_t);
|
371
423
|
VALUE map_rb = DEREF(msg, mapdata->ofs, VALUE);
|
372
424
|
|
373
|
-
|
425
|
+
frame->handlerdata = mapdata;
|
426
|
+
frame->map = map_rb;
|
427
|
+
native_slot_init(mapdata->key_field_type, &frame->key_storage);
|
428
|
+
native_slot_init(mapdata->value_field_type, &frame->value_storage);
|
429
|
+
|
430
|
+
Map_set_frame(map_rb,
|
431
|
+
TypedData_Wrap_Struct(rb_cObject, &MapParseFrame_type, frame));
|
432
|
+
|
433
|
+
return frame;
|
434
|
+
}
|
435
|
+
|
436
|
+
static bool endmap_handler(void *closure, const void *hd) {
|
437
|
+
map_parse_frame_t* frame = closure;
|
438
|
+
Map_set_frame(frame->map, Qnil);
|
439
|
+
return true;
|
374
440
|
}
|
375
441
|
|
376
442
|
// Handler to end a map entry: inserts the value defined during the message into
|
377
443
|
// the map. This is the 'endmsg' handler on the map entry msgdef.
|
378
|
-
static bool
|
444
|
+
static bool endmapentry_handler(void* closure, const void* hd, upb_status* s) {
|
379
445
|
map_parse_frame_t* frame = closure;
|
380
446
|
const map_handlerdata_t* mapdata = hd;
|
381
447
|
|
@@ -383,20 +449,11 @@ static bool endmap_handler(void *closure, const void *hd, upb_status* s) {
|
|
383
449
|
mapdata->key_field_type, Qnil,
|
384
450
|
&frame->key_storage);
|
385
451
|
|
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,
|
452
|
+
VALUE value = native_slot_get(
|
453
|
+
mapdata->value_field_type, mapdata->subklass,
|
396
454
|
&frame->value_storage);
|
397
455
|
|
398
456
|
Map_index_set(frame->map, key, value);
|
399
|
-
Map_set_frame(frame->map, Qnil);
|
400
457
|
|
401
458
|
return true;
|
402
459
|
}
|
@@ -411,7 +468,7 @@ static bool endmap_handler(void *closure, const void *hd, upb_status* s) {
|
|
411
468
|
static map_handlerdata_t* new_map_handlerdata(
|
412
469
|
size_t ofs,
|
413
470
|
const upb_msgdef* mapentry_def,
|
414
|
-
Descriptor* desc) {
|
471
|
+
const Descriptor* desc) {
|
415
472
|
const upb_fielddef* key_field;
|
416
473
|
const upb_fielddef* value_field;
|
417
474
|
map_handlerdata_t* hd = ALLOC(map_handlerdata_t);
|
@@ -422,7 +479,7 @@ static map_handlerdata_t* new_map_handlerdata(
|
|
422
479
|
value_field = upb_msgdef_itof(mapentry_def, MAP_VALUE_FIELD);
|
423
480
|
assert(value_field != NULL);
|
424
481
|
hd->value_field_type = upb_fielddef_type(value_field);
|
425
|
-
hd->
|
482
|
+
hd->subklass = field_type_class(desc->layout, value_field);
|
426
483
|
|
427
484
|
return hd;
|
428
485
|
}
|
@@ -488,16 +545,13 @@ static void *oneofsubmsg_handler(void *closure,
|
|
488
545
|
const oneof_handlerdata_t *oneofdata = hd;
|
489
546
|
uint32_t oldcase = DEREF(msg, oneofdata->case_ofs, uint32_t);
|
490
547
|
|
491
|
-
VALUE subdesc =
|
492
|
-
get_def_obj((void*)oneofdata->md);
|
493
|
-
VALUE subklass = Descriptor_msgclass(subdesc);
|
494
548
|
VALUE submsg_rb;
|
495
549
|
MessageHeader* submsg;
|
496
550
|
|
497
551
|
if (oldcase != oneofdata->oneof_case_num ||
|
498
552
|
DEREF(msg, oneofdata->ofs, VALUE) == Qnil) {
|
499
553
|
DEREF(msg, oneofdata->ofs, VALUE) =
|
500
|
-
|
554
|
+
initialize_rb_class_with_no_args(oneofdata->subklass);
|
501
555
|
}
|
502
556
|
// Set the oneof case *after* allocating the new class instance -- otherwise,
|
503
557
|
// if the Ruby GC is invoked as part of a call into the VM, it might invoke
|
@@ -505,22 +559,30 @@ static void *oneofsubmsg_handler(void *closure,
|
|
505
559
|
// indicating a VALUE is present and expect a valid VALUE. See comment in
|
506
560
|
// layout_set() for more detail: basically, the change to the value and the
|
507
561
|
// case must be atomic w.r.t. the Ruby VM.
|
508
|
-
DEREF(msg, oneofdata->case_ofs, uint32_t) =
|
509
|
-
oneofdata->oneof_case_num;
|
562
|
+
DEREF(msg, oneofdata->case_ofs, uint32_t) = oneofdata->oneof_case_num;
|
510
563
|
|
511
564
|
submsg_rb = DEREF(msg, oneofdata->ofs, VALUE);
|
512
565
|
TypedData_Get_Struct(submsg_rb, MessageHeader, &Message_type, submsg);
|
513
566
|
return submsg;
|
514
567
|
}
|
515
568
|
|
569
|
+
static void* oneof_startwrapper(void* closure, const void* hd) {
|
570
|
+
char* msg = closure;
|
571
|
+
const oneof_handlerdata_t *oneofdata = hd;
|
572
|
+
|
573
|
+
DEREF(msg, oneofdata->case_ofs, uint32_t) = oneofdata->oneof_case_num;
|
574
|
+
|
575
|
+
return msg + oneofdata->ofs;
|
576
|
+
}
|
577
|
+
|
516
578
|
// Set up handlers for a repeated field.
|
517
579
|
static void add_handlers_for_repeated_field(upb_handlers *h,
|
580
|
+
const Descriptor* desc,
|
518
581
|
const upb_fielddef *f,
|
519
582
|
size_t offset) {
|
520
|
-
upb_handlerattr attr =
|
521
|
-
|
583
|
+
upb_handlerattr attr = UPB_HANDLERATTR_INIT;
|
584
|
+
attr.handler_data = newhandlerdata(h, offset, -1);
|
522
585
|
upb_handlers_setstartseq(h, f, startseq_handler, &attr);
|
523
|
-
upb_handlerattr_uninit(&attr);
|
524
586
|
|
525
587
|
switch (upb_fielddef_type(f)) {
|
526
588
|
|
@@ -551,20 +613,104 @@ static void add_handlers_for_repeated_field(upb_handlers *h,
|
|
551
613
|
break;
|
552
614
|
}
|
553
615
|
case UPB_TYPE_MESSAGE: {
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
616
|
+
VALUE subklass = field_type_class(desc->layout, f);
|
617
|
+
upb_handlerattr attr = UPB_HANDLERATTR_INIT;
|
618
|
+
attr.handler_data = newsubmsghandlerdata(h, f, 0, -1, subklass);
|
619
|
+
if (is_wrapper(upb_fielddef_msgsubdef(f))) {
|
620
|
+
upb_handlers_setstartsubmsg(h, f, appendwrapper_handler, &attr);
|
621
|
+
} else {
|
622
|
+
upb_handlers_setstartsubmsg(h, f, appendsubmsg_handler, &attr);
|
623
|
+
}
|
558
624
|
break;
|
559
625
|
}
|
560
626
|
}
|
561
627
|
}
|
562
628
|
|
629
|
+
static bool doublewrapper_handler(void* closure, const void* hd, double val) {
|
630
|
+
VALUE* rbval = closure;
|
631
|
+
*rbval = DBL2NUM(val);
|
632
|
+
return true;
|
633
|
+
}
|
634
|
+
|
635
|
+
static bool floatwrapper_handler(void* closure, const void* hd, float val) {
|
636
|
+
VALUE* rbval = closure;
|
637
|
+
*rbval = DBL2NUM(val);
|
638
|
+
return true;
|
639
|
+
}
|
640
|
+
|
641
|
+
static bool int64wrapper_handler(void* closure, const void* hd, int64_t val) {
|
642
|
+
VALUE* rbval = closure;
|
643
|
+
*rbval = LL2NUM(val);
|
644
|
+
return true;
|
645
|
+
}
|
646
|
+
|
647
|
+
static bool uint64wrapper_handler(void* closure, const void* hd, uint64_t val) {
|
648
|
+
VALUE* rbval = closure;
|
649
|
+
*rbval = ULL2NUM(val);
|
650
|
+
return true;
|
651
|
+
}
|
652
|
+
|
653
|
+
static bool int32wrapper_handler(void* closure, const void* hd, int32_t val) {
|
654
|
+
VALUE* rbval = closure;
|
655
|
+
*rbval = INT2NUM(val);
|
656
|
+
return true;
|
657
|
+
}
|
658
|
+
|
659
|
+
static bool uint32wrapper_handler(void* closure, const void* hd, uint32_t val) {
|
660
|
+
VALUE* rbval = closure;
|
661
|
+
*rbval = UINT2NUM(val);
|
662
|
+
return true;
|
663
|
+
}
|
664
|
+
|
665
|
+
static void* startstringwrapper_handler(void* closure, const void* hd,
|
666
|
+
size_t size_hint) {
|
667
|
+
VALUE* rbval = closure;
|
668
|
+
(void)size_hint;
|
669
|
+
*rbval = rb_str_new(NULL, 0);
|
670
|
+
rb_enc_associate(*rbval, kRubyStringUtf8Encoding);
|
671
|
+
return closure;
|
672
|
+
}
|
673
|
+
|
674
|
+
static size_t stringwrapper_handler(void* closure, const void* hd,
|
675
|
+
const char* ptr, size_t len,
|
676
|
+
const upb_bufhandle* handle) {
|
677
|
+
VALUE* rbval = closure;
|
678
|
+
*rbval = noleak_rb_str_cat(*rbval, ptr, len);
|
679
|
+
return len;
|
680
|
+
}
|
681
|
+
|
682
|
+
static void* startbyteswrapper_handler(void* closure, const void* hd,
|
683
|
+
size_t size_hint) {
|
684
|
+
VALUE* rbval = closure;
|
685
|
+
(void)size_hint;
|
686
|
+
*rbval = rb_str_new(NULL, 0);
|
687
|
+
rb_enc_associate(*rbval, kRubyString8bitEncoding);
|
688
|
+
return closure;
|
689
|
+
}
|
690
|
+
|
691
|
+
static size_t byteswrapper_handler(void* closure, const void* hd,
|
692
|
+
const char* ptr, size_t len,
|
693
|
+
const upb_bufhandle* handle) {
|
694
|
+
VALUE* rbval = closure;
|
695
|
+
*rbval = noleak_rb_str_cat(*rbval, ptr, len);
|
696
|
+
return len;
|
697
|
+
}
|
698
|
+
|
699
|
+
static bool boolwrapper_handler(void* closure, const void* hd, bool val) {
|
700
|
+
VALUE* rbval = closure;
|
701
|
+
if (val) {
|
702
|
+
*rbval = Qtrue;
|
703
|
+
} else {
|
704
|
+
*rbval = Qfalse;
|
705
|
+
}
|
706
|
+
return true;
|
707
|
+
}
|
708
|
+
|
563
709
|
// Set up handlers for a singular field.
|
564
|
-
static void add_handlers_for_singular_field(
|
565
|
-
|
566
|
-
|
567
|
-
size_t hasbit_off) {
|
710
|
+
static void add_handlers_for_singular_field(const Descriptor* desc,
|
711
|
+
upb_handlers* h,
|
712
|
+
const upb_fielddef* f,
|
713
|
+
size_t offset, size_t hasbit_off) {
|
568
714
|
// The offset we pass to UPB points to the start of the Message,
|
569
715
|
// rather than the start of where our data is stored.
|
570
716
|
int32_t hasbit = -1;
|
@@ -586,24 +732,24 @@ static void add_handlers_for_singular_field(upb_handlers *h,
|
|
586
732
|
case UPB_TYPE_STRING:
|
587
733
|
case UPB_TYPE_BYTES: {
|
588
734
|
bool is_bytes = upb_fielddef_type(f) == UPB_TYPE_BYTES;
|
589
|
-
upb_handlerattr attr =
|
590
|
-
|
735
|
+
upb_handlerattr attr = UPB_HANDLERATTR_INIT;
|
736
|
+
attr.handler_data = newhandlerdata(h, offset, hasbit);
|
591
737
|
upb_handlers_setstartstr(h, f,
|
592
738
|
is_bytes ? bytes_handler : str_handler,
|
593
739
|
&attr);
|
594
740
|
upb_handlers_setstring(h, f, stringdata_handler, &attr);
|
595
741
|
upb_handlers_setendstr(h, f, stringdata_end_handler, &attr);
|
596
|
-
upb_handlerattr_uninit(&attr);
|
597
742
|
break;
|
598
743
|
}
|
599
744
|
case UPB_TYPE_MESSAGE: {
|
600
|
-
upb_handlerattr attr =
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
745
|
+
upb_handlerattr attr = UPB_HANDLERATTR_INIT;
|
746
|
+
attr.handler_data = newsubmsghandlerdata(
|
747
|
+
h, f, offset, hasbit, field_type_class(desc->layout, f));
|
748
|
+
if (is_wrapper(upb_fielddef_msgsubdef(f))) {
|
749
|
+
upb_handlers_setstartsubmsg(h, f, startwrapper, &attr);
|
750
|
+
} else {
|
751
|
+
upb_handlers_setstartsubmsg(h, f, submsg_handler, &attr);
|
752
|
+
}
|
607
753
|
}
|
608
754
|
}
|
609
755
|
}
|
@@ -612,49 +758,87 @@ static void add_handlers_for_singular_field(upb_handlers *h,
|
|
612
758
|
static void add_handlers_for_mapfield(upb_handlers* h,
|
613
759
|
const upb_fielddef* fielddef,
|
614
760
|
size_t offset,
|
615
|
-
Descriptor* desc) {
|
761
|
+
const Descriptor* desc) {
|
616
762
|
const upb_msgdef* map_msgdef = upb_fielddef_msgsubdef(fielddef);
|
617
763
|
map_handlerdata_t* hd = new_map_handlerdata(offset, map_msgdef, desc);
|
618
|
-
upb_handlerattr attr =
|
764
|
+
upb_handlerattr attr = UPB_HANDLERATTR_INIT;
|
619
765
|
|
620
766
|
upb_handlers_addcleanup(h, hd, xfree);
|
621
|
-
|
622
|
-
upb_handlers_setstartsubmsg(h, fielddef,
|
623
|
-
|
767
|
+
attr.handler_data = hd;
|
768
|
+
upb_handlers_setstartsubmsg(h, fielddef, startmap_handler, &attr);
|
769
|
+
upb_handlers_setendsubmsg(h, fielddef, endmap_handler, &attr);
|
624
770
|
}
|
625
771
|
|
626
772
|
// Adds handlers to a map-entry msgdef.
|
627
|
-
static void add_handlers_for_mapentry(const upb_msgdef* msgdef,
|
628
|
-
|
629
|
-
Descriptor* desc) {
|
773
|
+
static void add_handlers_for_mapentry(const upb_msgdef* msgdef, upb_handlers* h,
|
774
|
+
const Descriptor* desc) {
|
630
775
|
const upb_fielddef* key_field = map_entry_key(msgdef);
|
631
776
|
const upb_fielddef* value_field = map_entry_value(msgdef);
|
632
777
|
map_handlerdata_t* hd = new_map_handlerdata(0, msgdef, desc);
|
633
|
-
upb_handlerattr attr =
|
778
|
+
upb_handlerattr attr = UPB_HANDLERATTR_INIT;
|
634
779
|
|
635
780
|
upb_handlers_addcleanup(h, hd, xfree);
|
636
|
-
|
637
|
-
upb_handlers_setendmsg(h,
|
781
|
+
attr.handler_data = hd;
|
782
|
+
upb_handlers_setendmsg(h, endmapentry_handler, &attr);
|
638
783
|
|
639
784
|
add_handlers_for_singular_field(
|
640
|
-
h, key_field,
|
785
|
+
desc, h, key_field,
|
641
786
|
offsetof(map_parse_frame_t, key_storage),
|
642
787
|
MESSAGE_FIELD_NO_HASBIT);
|
643
788
|
add_handlers_for_singular_field(
|
644
|
-
h, value_field,
|
789
|
+
desc, h, value_field,
|
645
790
|
offsetof(map_parse_frame_t, value_storage),
|
646
791
|
MESSAGE_FIELD_NO_HASBIT);
|
647
792
|
}
|
648
793
|
|
794
|
+
static void add_handlers_for_wrapper(const upb_msgdef* msgdef,
|
795
|
+
upb_handlers* h) {
|
796
|
+
const upb_fielddef* f = upb_msgdef_itof(msgdef, 1);
|
797
|
+
switch (upb_msgdef_wellknowntype(msgdef)) {
|
798
|
+
case UPB_WELLKNOWN_DOUBLEVALUE:
|
799
|
+
upb_handlers_setdouble(h, f, doublewrapper_handler, NULL);
|
800
|
+
break;
|
801
|
+
case UPB_WELLKNOWN_FLOATVALUE:
|
802
|
+
upb_handlers_setfloat(h, f, floatwrapper_handler, NULL);
|
803
|
+
break;
|
804
|
+
case UPB_WELLKNOWN_INT64VALUE:
|
805
|
+
upb_handlers_setint64(h, f, int64wrapper_handler, NULL);
|
806
|
+
break;
|
807
|
+
case UPB_WELLKNOWN_UINT64VALUE:
|
808
|
+
upb_handlers_setuint64(h, f, uint64wrapper_handler, NULL);
|
809
|
+
break;
|
810
|
+
case UPB_WELLKNOWN_INT32VALUE:
|
811
|
+
upb_handlers_setint32(h, f, int32wrapper_handler, NULL);
|
812
|
+
break;
|
813
|
+
case UPB_WELLKNOWN_UINT32VALUE:
|
814
|
+
upb_handlers_setuint32(h, f, uint32wrapper_handler, NULL);
|
815
|
+
break;
|
816
|
+
case UPB_WELLKNOWN_STRINGVALUE:
|
817
|
+
upb_handlers_setstartstr(h, f, startstringwrapper_handler, NULL);
|
818
|
+
upb_handlers_setstring(h, f, stringwrapper_handler, NULL);
|
819
|
+
break;
|
820
|
+
case UPB_WELLKNOWN_BYTESVALUE:
|
821
|
+
upb_handlers_setstartstr(h, f, startbyteswrapper_handler, NULL);
|
822
|
+
upb_handlers_setstring(h, f, byteswrapper_handler, NULL);
|
823
|
+
break;
|
824
|
+
case UPB_WELLKNOWN_BOOLVALUE:
|
825
|
+
upb_handlers_setbool(h, f, boolwrapper_handler, NULL);
|
826
|
+
return;
|
827
|
+
default:
|
828
|
+
rb_raise(rb_eRuntimeError,
|
829
|
+
"Internal logic error with well-known types.");
|
830
|
+
}
|
831
|
+
}
|
832
|
+
|
649
833
|
// Set up handlers for a oneof field.
|
650
834
|
static void add_handlers_for_oneof_field(upb_handlers *h,
|
651
835
|
const upb_fielddef *f,
|
652
836
|
size_t offset,
|
653
|
-
size_t oneof_case_offset
|
654
|
-
|
655
|
-
upb_handlerattr attr =
|
656
|
-
|
657
|
-
|
837
|
+
size_t oneof_case_offset,
|
838
|
+
const Descriptor* desc) {
|
839
|
+
upb_handlerattr attr = UPB_HANDLERATTR_INIT;
|
840
|
+
attr.handler_data =
|
841
|
+
newoneofhandlerdata(h, offset, oneof_case_offset, f, desc);
|
658
842
|
|
659
843
|
switch (upb_fielddef_type(f)) {
|
660
844
|
|
@@ -685,19 +869,21 @@ static void add_handlers_for_oneof_field(upb_handlers *h,
|
|
685
869
|
break;
|
686
870
|
}
|
687
871
|
case UPB_TYPE_MESSAGE: {
|
688
|
-
|
872
|
+
if (is_wrapper(upb_fielddef_msgsubdef(f))) {
|
873
|
+
upb_handlers_setstartsubmsg(h, f, oneof_startwrapper, &attr);
|
874
|
+
} else {
|
875
|
+
upb_handlers_setstartsubmsg(h, f, oneofsubmsg_handler, &attr);
|
876
|
+
}
|
689
877
|
break;
|
690
878
|
}
|
691
879
|
}
|
692
|
-
|
693
|
-
upb_handlerattr_uninit(&attr);
|
694
880
|
}
|
695
881
|
|
696
882
|
static bool unknown_field_handler(void* closure, const void* hd,
|
697
883
|
const char* buf, size_t size) {
|
884
|
+
MessageHeader* msg = (MessageHeader*)closure;
|
698
885
|
UPB_UNUSED(hd);
|
699
886
|
|
700
|
-
MessageHeader* msg = (MessageHeader*)closure;
|
701
887
|
if (msg->unknown_fields == NULL) {
|
702
888
|
msg->unknown_fields = malloc(sizeof(stringsink));
|
703
889
|
stringsink_init(msg->unknown_fields);
|
@@ -708,10 +894,25 @@ static bool unknown_field_handler(void* closure, const void* hd,
|
|
708
894
|
return true;
|
709
895
|
}
|
710
896
|
|
711
|
-
|
897
|
+
size_t get_field_offset(MessageLayout* layout, const upb_fielddef* f) {
|
898
|
+
return layout->fields[upb_fielddef_index(f)].offset + sizeof(MessageHeader);
|
899
|
+
}
|
900
|
+
|
901
|
+
void add_handlers_for_message(const void *closure, upb_handlers *h) {
|
902
|
+
const VALUE descriptor_pool = (VALUE)closure;
|
712
903
|
const upb_msgdef* msgdef = upb_handlers_msgdef(h);
|
713
|
-
Descriptor* desc =
|
904
|
+
Descriptor* desc =
|
905
|
+
ruby_to_Descriptor(get_msgdef_obj(descriptor_pool, msgdef));
|
714
906
|
upb_msg_field_iter i;
|
907
|
+
upb_handlerattr attr = UPB_HANDLERATTR_INIT;
|
908
|
+
|
909
|
+
// Ensure layout exists. We may be invoked to create handlers for a given
|
910
|
+
// message if we are included as a submsg of another message type before our
|
911
|
+
// class is actually built, so to work around this, we just create the layout
|
912
|
+
// (and handlers, in the class-building function) on-demand.
|
913
|
+
if (desc->layout == NULL) {
|
914
|
+
create_layout(desc);
|
915
|
+
}
|
715
916
|
|
716
917
|
// If this is a mapentry message type, set up a special set of handlers and
|
717
918
|
// bail out of the normal (user-defined) message type handling.
|
@@ -720,86 +921,70 @@ static void add_handlers_for_message(const void *closure, upb_handlers *h) {
|
|
720
921
|
return;
|
721
922
|
}
|
722
923
|
|
723
|
-
//
|
724
|
-
|
725
|
-
|
726
|
-
|
727
|
-
if (desc->layout == NULL) {
|
728
|
-
desc->layout = create_layout(desc->msgdef);
|
924
|
+
// If this is a wrapper type, use special handlers and bail.
|
925
|
+
if (is_wrapper(msgdef)) {
|
926
|
+
add_handlers_for_wrapper(msgdef, h);
|
927
|
+
return;
|
729
928
|
}
|
730
929
|
|
731
|
-
upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER;
|
732
930
|
upb_handlers_setunknown(h, unknown_field_handler, &attr);
|
733
931
|
|
734
932
|
for (upb_msg_field_begin(&i, desc->msgdef);
|
735
933
|
!upb_msg_field_done(&i);
|
736
934
|
upb_msg_field_next(&i)) {
|
737
935
|
const upb_fielddef *f = upb_msg_iter_field(&i);
|
738
|
-
|
739
|
-
|
936
|
+
const upb_oneofdef* oneof = upb_fielddef_realcontainingoneof(f);
|
937
|
+
size_t offset = get_field_offset(desc->layout, f);
|
740
938
|
|
741
|
-
if (
|
939
|
+
if (oneof) {
|
742
940
|
size_t oneof_case_offset =
|
743
|
-
desc->layout->
|
941
|
+
desc->layout->oneofs[upb_oneofdef_index(oneof)].case_offset +
|
744
942
|
sizeof(MessageHeader);
|
745
|
-
add_handlers_for_oneof_field(h, f, offset, oneof_case_offset);
|
943
|
+
add_handlers_for_oneof_field(h, f, offset, oneof_case_offset, desc);
|
746
944
|
} else if (is_map_field(f)) {
|
747
945
|
add_handlers_for_mapfield(h, f, offset, desc);
|
748
946
|
} else if (upb_fielddef_isseq(f)) {
|
749
|
-
add_handlers_for_repeated_field(h, f, offset);
|
947
|
+
add_handlers_for_repeated_field(h, desc, f, offset);
|
750
948
|
} else {
|
751
949
|
add_handlers_for_singular_field(
|
752
|
-
h, f, offset,
|
950
|
+
desc, h, f, offset,
|
951
|
+
desc->layout->fields[upb_fielddef_index(f)].hasbit);
|
753
952
|
}
|
754
953
|
}
|
755
954
|
}
|
756
955
|
|
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
956
|
// Constructs the handlers for filling a message's data into an in-memory
|
769
957
|
// object.
|
770
958
|
const upb_handlers* get_fill_handlers(Descriptor* desc) {
|
771
|
-
|
772
|
-
|
773
|
-
new_fill_handlers(desc, &desc->fill_handlers);
|
774
|
-
}
|
775
|
-
return desc->fill_handlers;
|
959
|
+
DescriptorPool* pool = ruby_to_DescriptorPool(desc->descriptor_pool);
|
960
|
+
return upb_handlercache_get(pool->fill_handler_cache, desc->msgdef);
|
776
961
|
}
|
777
962
|
|
778
|
-
|
779
|
-
|
780
|
-
|
781
|
-
|
782
|
-
const upb_handlers* handlers = get_fill_handlers(desc);
|
783
|
-
upb_pbdecodermethodopts opts;
|
784
|
-
upb_pbdecodermethodopts_init(&opts, handlers);
|
963
|
+
static const upb_pbdecodermethod *msgdef_decodermethod(Descriptor* desc) {
|
964
|
+
DescriptorPool* pool = ruby_to_DescriptorPool(desc->descriptor_pool);
|
965
|
+
return upb_pbcodecache_get(pool->fill_method_cache, desc->msgdef);
|
966
|
+
}
|
785
967
|
|
786
|
-
|
968
|
+
static const upb_json_parsermethod *msgdef_jsonparsermethod(Descriptor* desc) {
|
969
|
+
DescriptorPool* pool = ruby_to_DescriptorPool(desc->descriptor_pool);
|
970
|
+
return upb_json_codecache_get(pool->json_fill_method_cache, desc->msgdef);
|
787
971
|
}
|
788
972
|
|
789
|
-
static const
|
790
|
-
|
791
|
-
|
792
|
-
desc, &desc->fill_method);
|
793
|
-
}
|
794
|
-
return desc->fill_method;
|
973
|
+
static const upb_handlers* msgdef_pb_serialize_handlers(Descriptor* desc) {
|
974
|
+
DescriptorPool* pool = ruby_to_DescriptorPool(desc->descriptor_pool);
|
975
|
+
return upb_handlercache_get(pool->pb_serialize_handler_cache, desc->msgdef);
|
795
976
|
}
|
796
977
|
|
797
|
-
static const
|
798
|
-
|
799
|
-
|
800
|
-
|
978
|
+
static const upb_handlers* msgdef_json_serialize_handlers(
|
979
|
+
Descriptor* desc, bool preserve_proto_fieldnames) {
|
980
|
+
DescriptorPool* pool = ruby_to_DescriptorPool(desc->descriptor_pool);
|
981
|
+
if (preserve_proto_fieldnames) {
|
982
|
+
return upb_handlercache_get(pool->json_serialize_handler_preserve_cache,
|
983
|
+
desc->msgdef);
|
984
|
+
} else {
|
985
|
+
return upb_handlercache_get(pool->json_serialize_handler_cache,
|
986
|
+
desc->msgdef);
|
801
987
|
}
|
802
|
-
return desc->json_fill_method;
|
803
988
|
}
|
804
989
|
|
805
990
|
|
@@ -809,7 +994,8 @@ static const upb_json_parsermethod *msgdef_jsonparsermethod(Descriptor* desc) {
|
|
809
994
|
// if any error occurs.
|
810
995
|
#define STACK_ENV_STACKBYTES 4096
|
811
996
|
typedef struct {
|
812
|
-
|
997
|
+
upb_arena *arena;
|
998
|
+
upb_status status;
|
813
999
|
const char* ruby_error_template;
|
814
1000
|
char allocbuf[STACK_ENV_STACKBYTES];
|
815
1001
|
} stackenv;
|
@@ -817,29 +1003,22 @@ typedef struct {
|
|
817
1003
|
static void stackenv_init(stackenv* se, const char* errmsg);
|
818
1004
|
static void stackenv_uninit(stackenv* se);
|
819
1005
|
|
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
1006
|
static void stackenv_init(stackenv* se, const char* errmsg) {
|
836
1007
|
se->ruby_error_template = errmsg;
|
837
|
-
|
838
|
-
|
1008
|
+
se->arena =
|
1009
|
+
upb_arena_init(se->allocbuf, sizeof(se->allocbuf), &upb_alloc_global);
|
1010
|
+
upb_status_clear(&se->status);
|
839
1011
|
}
|
840
1012
|
|
841
1013
|
static void stackenv_uninit(stackenv* se) {
|
842
|
-
|
1014
|
+
upb_arena_free(se->arena);
|
1015
|
+
|
1016
|
+
if (!upb_ok(&se->status)) {
|
1017
|
+
// TODO(haberman): have a way to verify that this is actually a parse error,
|
1018
|
+
// instead of just throwing "parse error" unconditionally.
|
1019
|
+
VALUE errmsg = rb_str_new2(upb_status_errmsg(&se->status));
|
1020
|
+
rb_raise(cParseError, se->ruby_error_template, errmsg);
|
1021
|
+
}
|
843
1022
|
}
|
844
1023
|
|
845
1024
|
/*
|
@@ -861,23 +1040,34 @@ VALUE Message_decode(VALUE klass, VALUE data) {
|
|
861
1040
|
rb_raise(rb_eArgError, "Expected string for binary protobuf data.");
|
862
1041
|
}
|
863
1042
|
|
864
|
-
msg_rb =
|
1043
|
+
msg_rb = initialize_rb_class_with_no_args(msgklass);
|
865
1044
|
TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg);
|
866
1045
|
|
867
1046
|
{
|
868
1047
|
const upb_pbdecodermethod* method = msgdef_decodermethod(desc);
|
869
1048
|
const upb_handlers* h = upb_pbdecodermethod_desthandlers(method);
|
1049
|
+
const upb_msgdef* m = upb_handlers_msgdef(h);
|
1050
|
+
VALUE wrapper = Qnil;
|
1051
|
+
void* ptr = msg;
|
870
1052
|
stackenv se;
|
871
1053
|
upb_sink sink;
|
872
1054
|
upb_pbdecoder* decoder;
|
873
|
-
stackenv_init(&se, "Error occurred during parsing: %
|
1055
|
+
stackenv_init(&se, "Error occurred during parsing: %" PRIsVALUE);
|
874
1056
|
|
875
|
-
|
876
|
-
|
1057
|
+
if (is_wrapper(m)) {
|
1058
|
+
ptr = &wrapper;
|
1059
|
+
}
|
1060
|
+
|
1061
|
+
upb_sink_reset(&sink, h, ptr);
|
1062
|
+
decoder = upb_pbdecoder_create(se.arena, method, sink, &se.status);
|
877
1063
|
upb_bufsrc_putbuf(RSTRING_PTR(data), RSTRING_LEN(data),
|
878
1064
|
upb_pbdecoder_input(decoder));
|
879
1065
|
|
880
1066
|
stackenv_uninit(&se);
|
1067
|
+
|
1068
|
+
if (is_wrapper(m)) {
|
1069
|
+
msg_rb = ruby_wrapper_type(msgklass, wrapper);
|
1070
|
+
}
|
881
1071
|
}
|
882
1072
|
|
883
1073
|
return msg_rb;
|
@@ -891,8 +1081,9 @@ VALUE Message_decode(VALUE klass, VALUE data) {
|
|
891
1081
|
* format) under the interpretration given by this message class's definition
|
892
1082
|
* and returns a message object with the corresponding field values.
|
893
1083
|
*
|
894
|
-
*
|
895
|
-
* ignore_unknown_fields: set true to ignore unknown fields (default is to
|
1084
|
+
* @param options [Hash] options for the decoder
|
1085
|
+
* ignore_unknown_fields: set true to ignore unknown fields (default is to
|
1086
|
+
* raise an error)
|
896
1087
|
*/
|
897
1088
|
VALUE Message_decode_json(int argc, VALUE* argv, VALUE klass) {
|
898
1089
|
VALUE descriptor = rb_ivar_get(klass, descriptor_instancevar_interned);
|
@@ -920,24 +1111,33 @@ VALUE Message_decode_json(int argc, VALUE* argv, VALUE klass) {
|
|
920
1111
|
if (TYPE(data) != T_STRING) {
|
921
1112
|
rb_raise(rb_eArgError, "Expected string for JSON data.");
|
922
1113
|
}
|
1114
|
+
|
923
1115
|
// TODO(cfallin): Check and respect string encoding. If not UTF-8, we need to
|
924
1116
|
// convert, because string handlers pass data directly to message string
|
925
1117
|
// fields.
|
926
1118
|
|
927
|
-
msg_rb =
|
1119
|
+
msg_rb = initialize_rb_class_with_no_args(msgklass);
|
928
1120
|
TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg);
|
929
1121
|
|
930
1122
|
{
|
931
1123
|
const upb_json_parsermethod* method = msgdef_jsonparsermethod(desc);
|
1124
|
+
const upb_handlers* h = get_fill_handlers(desc);
|
1125
|
+
const upb_msgdef* m = upb_handlers_msgdef(h);
|
932
1126
|
stackenv se;
|
933
1127
|
upb_sink sink;
|
934
1128
|
upb_json_parser* parser;
|
935
1129
|
DescriptorPool* pool = ruby_to_DescriptorPool(generated_pool);
|
936
|
-
stackenv_init(&se, "Error occurred during parsing: %
|
1130
|
+
stackenv_init(&se, "Error occurred during parsing: %" PRIsVALUE);
|
1131
|
+
|
1132
|
+
if (is_wrapper(m)) {
|
1133
|
+
rb_raise(
|
1134
|
+
rb_eRuntimeError,
|
1135
|
+
"Parsing a wrapper type from JSON at the top level does not work.");
|
1136
|
+
}
|
937
1137
|
|
938
|
-
upb_sink_reset(&sink,
|
939
|
-
parser = upb_json_parser_create(
|
940
|
-
&
|
1138
|
+
upb_sink_reset(&sink, h, msg);
|
1139
|
+
parser = upb_json_parser_create(se.arena, method, pool->symtab, sink,
|
1140
|
+
&se.status, RTEST(ignore_unknown_fields));
|
941
1141
|
upb_bufsrc_putbuf(RSTRING_PTR(data), RSTRING_LEN(data),
|
942
1142
|
upb_json_parser_input(parser));
|
943
1143
|
|
@@ -953,9 +1153,8 @@ VALUE Message_decode_json(int argc, VALUE* argv, VALUE klass) {
|
|
953
1153
|
|
954
1154
|
/* msgvisitor *****************************************************************/
|
955
1155
|
|
956
|
-
static void putmsg(VALUE msg, const Descriptor* desc,
|
957
|
-
|
958
|
-
bool is_json, bool open_msg);
|
1156
|
+
static void putmsg(VALUE msg, const Descriptor* desc, upb_sink sink, int depth,
|
1157
|
+
bool emit_defaults, bool is_json, bool open_msg);
|
959
1158
|
|
960
1159
|
static upb_selector_t getsel(const upb_fielddef *f, upb_handlertype_t type) {
|
961
1160
|
upb_selector_t ret;
|
@@ -964,7 +1163,7 @@ static upb_selector_t getsel(const upb_fielddef *f, upb_handlertype_t type) {
|
|
964
1163
|
return ret;
|
965
1164
|
}
|
966
1165
|
|
967
|
-
static void putstr(VALUE str, const upb_fielddef *f, upb_sink
|
1166
|
+
static void putstr(VALUE str, const upb_fielddef *f, upb_sink sink) {
|
968
1167
|
upb_sink subsink;
|
969
1168
|
|
970
1169
|
if (str == Qnil) return;
|
@@ -981,12 +1180,12 @@ static void putstr(VALUE str, const upb_fielddef *f, upb_sink *sink) {
|
|
981
1180
|
|
982
1181
|
upb_sink_startstr(sink, getsel(f, UPB_HANDLER_STARTSTR), RSTRING_LEN(str),
|
983
1182
|
&subsink);
|
984
|
-
upb_sink_putstring(
|
1183
|
+
upb_sink_putstring(subsink, getsel(f, UPB_HANDLER_STRING), RSTRING_PTR(str),
|
985
1184
|
RSTRING_LEN(str), NULL);
|
986
1185
|
upb_sink_endstr(sink, getsel(f, UPB_HANDLER_ENDSTR));
|
987
1186
|
}
|
988
1187
|
|
989
|
-
static void putsubmsg(VALUE submsg, const upb_fielddef *f, upb_sink
|
1188
|
+
static void putsubmsg(VALUE submsg, const upb_fielddef *f, upb_sink sink,
|
990
1189
|
int depth, bool emit_defaults, bool is_json) {
|
991
1190
|
upb_sink subsink;
|
992
1191
|
VALUE descriptor;
|
@@ -998,16 +1197,18 @@ static void putsubmsg(VALUE submsg, const upb_fielddef *f, upb_sink *sink,
|
|
998
1197
|
subdesc = ruby_to_Descriptor(descriptor);
|
999
1198
|
|
1000
1199
|
upb_sink_startsubmsg(sink, getsel(f, UPB_HANDLER_STARTSUBMSG), &subsink);
|
1001
|
-
putmsg(submsg, subdesc,
|
1002
|
-
upb_sink_endsubmsg(sink, getsel(f, UPB_HANDLER_ENDSUBMSG));
|
1200
|
+
putmsg(submsg, subdesc, subsink, depth + 1, emit_defaults, is_json, true);
|
1201
|
+
upb_sink_endsubmsg(sink, subsink, getsel(f, UPB_HANDLER_ENDSUBMSG));
|
1003
1202
|
}
|
1004
1203
|
|
1005
|
-
static void putary(VALUE ary, const upb_fielddef
|
1006
|
-
|
1204
|
+
static void putary(VALUE ary, const upb_fielddef* f, upb_sink sink, int depth,
|
1205
|
+
bool emit_defaults, bool is_json) {
|
1007
1206
|
upb_sink subsink;
|
1008
1207
|
upb_fieldtype_t type = upb_fielddef_type(f);
|
1009
1208
|
upb_selector_t sel = 0;
|
1010
1209
|
int size;
|
1210
|
+
int i;
|
1211
|
+
VALUE type_class = ruby_to_RepeatedField(ary)->field_type_class;
|
1011
1212
|
|
1012
1213
|
if (ary == Qnil) return;
|
1013
1214
|
if (!emit_defaults && NUM2INT(RepeatedField_length(ary)) == 0) return;
|
@@ -1021,12 +1222,12 @@ static void putary(VALUE ary, const upb_fielddef *f, upb_sink *sink,
|
|
1021
1222
|
sel = getsel(f, upb_handlers_getprimitivehandlertype(f));
|
1022
1223
|
}
|
1023
1224
|
|
1024
|
-
for (
|
1225
|
+
for (i = 0; i < size; i++) {
|
1025
1226
|
void* memory = RepeatedField_index_native(ary, i);
|
1026
1227
|
switch (type) {
|
1027
|
-
#define T(upbtypeconst, upbtype, ctype)
|
1028
|
-
case upbtypeconst:
|
1029
|
-
upb_sink_put##upbtype(
|
1228
|
+
#define T(upbtypeconst, upbtype, ctype) \
|
1229
|
+
case upbtypeconst: \
|
1230
|
+
upb_sink_put##upbtype(subsink, sel, *((ctype*)memory)); \
|
1030
1231
|
break;
|
1031
1232
|
|
1032
1233
|
T(UPB_TYPE_FLOAT, float, float)
|
@@ -1040,12 +1241,13 @@ static void putary(VALUE ary, const upb_fielddef *f, upb_sink *sink,
|
|
1040
1241
|
|
1041
1242
|
case UPB_TYPE_STRING:
|
1042
1243
|
case UPB_TYPE_BYTES:
|
1043
|
-
putstr(*((VALUE *)memory), f,
|
1244
|
+
putstr(*((VALUE *)memory), f, subsink);
|
1044
1245
|
break;
|
1045
|
-
case UPB_TYPE_MESSAGE:
|
1046
|
-
|
1047
|
-
|
1246
|
+
case UPB_TYPE_MESSAGE: {
|
1247
|
+
VALUE val = native_slot_get(UPB_TYPE_MESSAGE, type_class, memory);
|
1248
|
+
putsubmsg(val, f, subsink, depth, emit_defaults, is_json);
|
1048
1249
|
break;
|
1250
|
+
}
|
1049
1251
|
|
1050
1252
|
#undef T
|
1051
1253
|
|
@@ -1054,14 +1256,16 @@ static void putary(VALUE ary, const upb_fielddef *f, upb_sink *sink,
|
|
1054
1256
|
upb_sink_endseq(sink, getsel(f, UPB_HANDLER_ENDSEQ));
|
1055
1257
|
}
|
1056
1258
|
|
1057
|
-
static void put_ruby_value(VALUE value,
|
1058
|
-
|
1059
|
-
VALUE type_class,
|
1060
|
-
int depth,
|
1061
|
-
upb_sink *sink,
|
1062
|
-
bool emit_defaults,
|
1259
|
+
static void put_ruby_value(VALUE value, const upb_fielddef* f, VALUE type_class,
|
1260
|
+
int depth, upb_sink sink, bool emit_defaults,
|
1063
1261
|
bool is_json) {
|
1064
1262
|
upb_selector_t sel = 0;
|
1263
|
+
|
1264
|
+
if (depth > ENCODE_MAX_NESTING) {
|
1265
|
+
rb_raise(rb_eRuntimeError,
|
1266
|
+
"Maximum recursion depth exceeded during encoding.");
|
1267
|
+
}
|
1268
|
+
|
1065
1269
|
if (upb_fielddef_isprimitive(f)) {
|
1066
1270
|
sel = getsel(f, upb_handlers_getprimitivehandlertype(f));
|
1067
1271
|
}
|
@@ -1104,8 +1308,8 @@ static void put_ruby_value(VALUE value,
|
|
1104
1308
|
}
|
1105
1309
|
}
|
1106
1310
|
|
1107
|
-
static void putmap(VALUE map, const upb_fielddef
|
1108
|
-
|
1311
|
+
static void putmap(VALUE map, const upb_fielddef* f, upb_sink sink, int depth,
|
1312
|
+
bool emit_defaults, bool is_json) {
|
1109
1313
|
Map* self;
|
1110
1314
|
upb_sink subsink;
|
1111
1315
|
const upb_fielddef* key_field;
|
@@ -1129,17 +1333,17 @@ static void putmap(VALUE map, const upb_fielddef *f, upb_sink *sink,
|
|
1129
1333
|
upb_status status;
|
1130
1334
|
|
1131
1335
|
upb_sink entry_sink;
|
1132
|
-
upb_sink_startsubmsg(
|
1336
|
+
upb_sink_startsubmsg(subsink, getsel(f, UPB_HANDLER_STARTSUBMSG),
|
1133
1337
|
&entry_sink);
|
1134
|
-
upb_sink_startmsg(
|
1338
|
+
upb_sink_startmsg(entry_sink);
|
1135
1339
|
|
1136
|
-
put_ruby_value(key, key_field, Qnil, depth + 1,
|
1137
|
-
|
1340
|
+
put_ruby_value(key, key_field, Qnil, depth + 1, entry_sink, emit_defaults,
|
1341
|
+
is_json);
|
1138
1342
|
put_ruby_value(value, value_field, self->value_type_class, depth + 1,
|
1139
|
-
|
1343
|
+
entry_sink, emit_defaults, is_json);
|
1140
1344
|
|
1141
|
-
upb_sink_endmsg(
|
1142
|
-
upb_sink_endsubmsg(
|
1345
|
+
upb_sink_endmsg(entry_sink, &status);
|
1346
|
+
upb_sink_endsubmsg(subsink, entry_sink, getsel(f, UPB_HANDLER_ENDSUBMSG));
|
1143
1347
|
}
|
1144
1348
|
|
1145
1349
|
upb_sink_endseq(sink, getsel(f, UPB_HANDLER_ENDSEQ));
|
@@ -1148,8 +1352,8 @@ static void putmap(VALUE map, const upb_fielddef *f, upb_sink *sink,
|
|
1148
1352
|
static const upb_handlers* msgdef_json_serialize_handlers(
|
1149
1353
|
Descriptor* desc, bool preserve_proto_fieldnames);
|
1150
1354
|
|
1151
|
-
static void putjsonany(VALUE msg_rb, const Descriptor* desc,
|
1152
|
-
|
1355
|
+
static void putjsonany(VALUE msg_rb, const Descriptor* desc, upb_sink sink,
|
1356
|
+
int depth, bool emit_defaults) {
|
1153
1357
|
upb_status status;
|
1154
1358
|
MessageHeader* msg = NULL;
|
1155
1359
|
const upb_fielddef* type_field = upb_msgdef_itof(desc->msgdef, UPB_ANY_TYPE);
|
@@ -1196,16 +1400,14 @@ static void putjsonany(VALUE msg_rb, const Descriptor* desc,
|
|
1196
1400
|
{
|
1197
1401
|
uint32_t value_offset;
|
1198
1402
|
VALUE value_str_rb;
|
1199
|
-
const char* value_str;
|
1200
1403
|
size_t value_len;
|
1201
1404
|
|
1202
1405
|
value_offset = desc->layout->fields[upb_fielddef_index(value_field)].offset;
|
1203
1406
|
value_str_rb = DEREF(Message_data(msg), value_offset, VALUE);
|
1204
|
-
value_str = RSTRING_PTR(value_str_rb);
|
1205
1407
|
value_len = RSTRING_LEN(value_str_rb);
|
1206
1408
|
|
1207
1409
|
if (value_len > 0) {
|
1208
|
-
VALUE payload_desc_rb =
|
1410
|
+
VALUE payload_desc_rb = get_msgdef_obj(generated_pool, payload_type);
|
1209
1411
|
Descriptor* payload_desc = ruby_to_Descriptor(payload_desc_rb);
|
1210
1412
|
VALUE payload_class = Descriptor_msgclass(payload_desc_rb);
|
1211
1413
|
upb_sink subsink;
|
@@ -1223,8 +1425,8 @@ static void putjsonany(VALUE msg_rb, const Descriptor* desc,
|
|
1223
1425
|
|
1224
1426
|
subsink.handlers =
|
1225
1427
|
msgdef_json_serialize_handlers(payload_desc, true);
|
1226
|
-
subsink.closure = sink
|
1227
|
-
putmsg(payload_msg_rb, payload_desc,
|
1428
|
+
subsink.closure = sink.closure;
|
1429
|
+
putmsg(payload_msg_rb, payload_desc, subsink, depth, emit_defaults, true,
|
1228
1430
|
is_wellknown);
|
1229
1431
|
}
|
1230
1432
|
}
|
@@ -1232,18 +1434,54 @@ static void putjsonany(VALUE msg_rb, const Descriptor* desc,
|
|
1232
1434
|
upb_sink_endmsg(sink, &status);
|
1233
1435
|
}
|
1234
1436
|
|
1437
|
+
static void putjsonlistvalue(
|
1438
|
+
VALUE msg_rb, const Descriptor* desc,
|
1439
|
+
upb_sink sink, int depth, bool emit_defaults) {
|
1440
|
+
upb_status status;
|
1441
|
+
upb_sink subsink;
|
1442
|
+
MessageHeader* msg = NULL;
|
1443
|
+
const upb_fielddef* f = upb_msgdef_itof(desc->msgdef, 1);
|
1444
|
+
uint32_t offset =
|
1445
|
+
desc->layout->fields[upb_fielddef_index(f)].offset +
|
1446
|
+
sizeof(MessageHeader);
|
1447
|
+
VALUE ary;
|
1448
|
+
|
1449
|
+
TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg);
|
1450
|
+
|
1451
|
+
upb_sink_startmsg(sink);
|
1452
|
+
|
1453
|
+
ary = DEREF(msg, offset, VALUE);
|
1454
|
+
|
1455
|
+
if (ary == Qnil || RepeatedField_size(ary) == 0) {
|
1456
|
+
upb_sink_startseq(sink, getsel(f, UPB_HANDLER_STARTSEQ), &subsink);
|
1457
|
+
upb_sink_endseq(sink, getsel(f, UPB_HANDLER_ENDSEQ));
|
1458
|
+
} else {
|
1459
|
+
putary(ary, f, sink, depth, emit_defaults, true);
|
1460
|
+
}
|
1461
|
+
|
1462
|
+
upb_sink_endmsg(sink, &status);
|
1463
|
+
}
|
1464
|
+
|
1235
1465
|
static void putmsg(VALUE msg_rb, const Descriptor* desc,
|
1236
|
-
upb_sink
|
1466
|
+
upb_sink sink, int depth, bool emit_defaults,
|
1237
1467
|
bool is_json, bool open_msg) {
|
1238
1468
|
MessageHeader* msg;
|
1239
1469
|
upb_msg_field_iter i;
|
1240
1470
|
upb_status status;
|
1471
|
+
bool json_wrapper = is_wrapper(desc->msgdef) && is_json;
|
1241
1472
|
|
1242
|
-
if (is_json &&
|
1473
|
+
if (is_json &&
|
1474
|
+
upb_msgdef_wellknowntype(desc->msgdef) == UPB_WELLKNOWN_ANY) {
|
1243
1475
|
putjsonany(msg_rb, desc, sink, depth, emit_defaults);
|
1244
1476
|
return;
|
1245
1477
|
}
|
1246
1478
|
|
1479
|
+
if (is_json &&
|
1480
|
+
upb_msgdef_wellknowntype(desc->msgdef) == UPB_WELLKNOWN_LISTVALUE) {
|
1481
|
+
putjsonlistvalue(msg_rb, desc, sink, depth, emit_defaults);
|
1482
|
+
return;
|
1483
|
+
}
|
1484
|
+
|
1247
1485
|
if (open_msg) {
|
1248
1486
|
upb_sink_startmsg(sink);
|
1249
1487
|
}
|
@@ -1268,19 +1506,18 @@ static void putmsg(VALUE msg_rb, const Descriptor* desc,
|
|
1268
1506
|
!upb_msg_field_done(&i);
|
1269
1507
|
upb_msg_field_next(&i)) {
|
1270
1508
|
upb_fielddef *f = upb_msg_iter_field(&i);
|
1509
|
+
const upb_oneofdef* oneof = upb_fielddef_realcontainingoneof(f);
|
1271
1510
|
bool is_matching_oneof = false;
|
1272
1511
|
uint32_t offset =
|
1273
1512
|
desc->layout->fields[upb_fielddef_index(f)].offset +
|
1274
1513
|
sizeof(MessageHeader);
|
1275
1514
|
|
1276
|
-
if (
|
1277
|
-
uint32_t
|
1278
|
-
desc->layout
|
1279
|
-
sizeof(MessageHeader);
|
1515
|
+
if (oneof) {
|
1516
|
+
uint32_t oneof_case =
|
1517
|
+
slot_read_oneof_case(desc->layout, Message_data(msg), oneof);
|
1280
1518
|
// For a oneof, check that this field is actually present -- skip all the
|
1281
1519
|
// below if not.
|
1282
|
-
if (
|
1283
|
-
upb_fielddef_number(f)) {
|
1520
|
+
if (oneof_case != upb_fielddef_number(f)) {
|
1284
1521
|
continue;
|
1285
1522
|
}
|
1286
1523
|
// Otherwise, fall through to the appropriate singular-field handler
|
@@ -1308,29 +1545,30 @@ static void putmsg(VALUE msg_rb, const Descriptor* desc,
|
|
1308
1545
|
is_default = RSTRING_LEN(str) == 0;
|
1309
1546
|
}
|
1310
1547
|
|
1311
|
-
if (is_matching_oneof || emit_defaults || !is_default) {
|
1548
|
+
if (is_matching_oneof || emit_defaults || !is_default || json_wrapper) {
|
1312
1549
|
putstr(str, f, sink);
|
1313
1550
|
}
|
1314
1551
|
} else if (upb_fielddef_issubmsg(f)) {
|
1315
|
-
|
1316
|
-
|
1552
|
+
// OPT: could try to avoid the layout_get() (which will expand lazy
|
1553
|
+
// wrappers).
|
1554
|
+
VALUE val = layout_get(desc->layout, Message_data(msg), f);
|
1555
|
+
putsubmsg(val, f, sink, depth, emit_defaults, is_json);
|
1317
1556
|
} else {
|
1318
1557
|
upb_selector_t sel = getsel(f, upb_handlers_getprimitivehandlertype(f));
|
1319
1558
|
|
1320
|
-
#define T(upbtypeconst, upbtype, ctype, default_value)
|
1321
|
-
case upbtypeconst: {
|
1322
|
-
|
1323
|
-
|
1324
|
-
|
1325
|
-
|
1326
|
-
|
1327
|
-
|
1328
|
-
|
1329
|
-
|
1330
|
-
|
1331
|
-
|
1332
|
-
|
1333
|
-
break;
|
1559
|
+
#define T(upbtypeconst, upbtype, ctype, default_value) \
|
1560
|
+
case upbtypeconst: { \
|
1561
|
+
ctype value = DEREF(msg, offset, ctype); \
|
1562
|
+
bool is_default = false; \
|
1563
|
+
if (upb_fielddef_haspresence(f)) { \
|
1564
|
+
is_default = layout_has(desc->layout, Message_data(msg), f) == Qfalse; \
|
1565
|
+
} else if (upb_msgdef_syntax(desc->msgdef) == UPB_SYNTAX_PROTO3) { \
|
1566
|
+
is_default = default_value == value; \
|
1567
|
+
} \
|
1568
|
+
if (is_matching_oneof || emit_defaults || !is_default || json_wrapper) { \
|
1569
|
+
upb_sink_put##upbtype(sink, sel, value); \
|
1570
|
+
} \
|
1571
|
+
} break;
|
1334
1572
|
|
1335
1573
|
switch (upb_fielddef_type(f)) {
|
1336
1574
|
T(UPB_TYPE_FLOAT, float, float, 0.0)
|
@@ -1348,13 +1586,14 @@ static void putmsg(VALUE msg_rb, const Descriptor* desc,
|
|
1348
1586
|
}
|
1349
1587
|
|
1350
1588
|
#undef T
|
1351
|
-
|
1352
1589
|
}
|
1353
1590
|
}
|
1354
1591
|
|
1355
|
-
|
1356
|
-
|
1357
|
-
|
1592
|
+
{
|
1593
|
+
stringsink* unknown = msg->unknown_fields;
|
1594
|
+
if (unknown != NULL) {
|
1595
|
+
upb_sink_putunknown(sink, unknown->ptr, unknown->len);
|
1596
|
+
}
|
1358
1597
|
}
|
1359
1598
|
|
1360
1599
|
if (open_msg) {
|
@@ -1362,33 +1601,6 @@ static void putmsg(VALUE msg_rb, const Descriptor* desc,
|
|
1362
1601
|
}
|
1363
1602
|
}
|
1364
1603
|
|
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
1604
|
/*
|
1393
1605
|
* call-seq:
|
1394
1606
|
* MessageClass.encode(msg) => bytes
|
@@ -1411,8 +1623,8 @@ VALUE Message_encode(VALUE klass, VALUE msg_rb) {
|
|
1411
1623
|
upb_pb_encoder* encoder;
|
1412
1624
|
VALUE ret;
|
1413
1625
|
|
1414
|
-
stackenv_init(&se, "Error occurred during encoding: %
|
1415
|
-
encoder = upb_pb_encoder_create(
|
1626
|
+
stackenv_init(&se, "Error occurred during encoding: %" PRIsVALUE);
|
1627
|
+
encoder = upb_pb_encoder_create(se.arena, serialize_handlers, sink.sink);
|
1416
1628
|
|
1417
1629
|
putmsg(msg_rb, desc, upb_pb_encoder_input(encoder), 0, false, false, true);
|
1418
1630
|
|
@@ -1469,8 +1681,8 @@ VALUE Message_encode_json(int argc, VALUE* argv, VALUE klass) {
|
|
1469
1681
|
stackenv se;
|
1470
1682
|
VALUE ret;
|
1471
1683
|
|
1472
|
-
stackenv_init(&se, "Error occurred during encoding: %
|
1473
|
-
printer = upb_json_printer_create(
|
1684
|
+
stackenv_init(&se, "Error occurred during encoding: %" PRIsVALUE);
|
1685
|
+
printer = upb_json_printer_create(se.arena, serialize_handlers, sink.sink);
|
1474
1686
|
|
1475
1687
|
putmsg(msg_rb, desc, upb_json_printer_input(printer), 0,
|
1476
1688
|
RTEST(emit_defaults), true, true);
|
@@ -1490,28 +1702,29 @@ static void discard_unknown(VALUE msg_rb, const Descriptor* desc) {
|
|
1490
1702
|
|
1491
1703
|
TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg);
|
1492
1704
|
|
1493
|
-
|
1494
|
-
|
1495
|
-
|
1496
|
-
|
1705
|
+
{
|
1706
|
+
stringsink* unknown = msg->unknown_fields;
|
1707
|
+
if (unknown != NULL) {
|
1708
|
+
stringsink_uninit(unknown);
|
1709
|
+
msg->unknown_fields = NULL;
|
1710
|
+
}
|
1497
1711
|
}
|
1498
1712
|
|
1499
1713
|
for (upb_msg_field_begin(&it, desc->msgdef);
|
1500
1714
|
!upb_msg_field_done(&it);
|
1501
1715
|
upb_msg_field_next(&it)) {
|
1502
1716
|
upb_fielddef *f = upb_msg_iter_field(&it);
|
1717
|
+
const upb_oneofdef* oneof = upb_fielddef_realcontainingoneof(f);
|
1503
1718
|
uint32_t offset =
|
1504
1719
|
desc->layout->fields[upb_fielddef_index(f)].offset +
|
1505
1720
|
sizeof(MessageHeader);
|
1506
1721
|
|
1507
|
-
if (
|
1508
|
-
uint32_t
|
1509
|
-
desc->layout
|
1510
|
-
sizeof(MessageHeader);
|
1722
|
+
if (oneof) {
|
1723
|
+
uint32_t oneof_case =
|
1724
|
+
slot_read_oneof_case(desc->layout, Message_data(msg), oneof);
|
1511
1725
|
// For a oneof, check that this field is actually present -- skip all the
|
1512
1726
|
// below if not.
|
1513
|
-
if (
|
1514
|
-
upb_fielddef_number(f)) {
|
1727
|
+
if (oneof_case != upb_fielddef_number(f)) {
|
1515
1728
|
continue;
|
1516
1729
|
}
|
1517
1730
|
// Otherwise, fall through to the appropriate singular-field handler
|
@@ -1523,10 +1736,12 @@ static void discard_unknown(VALUE msg_rb, const Descriptor* desc) {
|
|
1523
1736
|
}
|
1524
1737
|
|
1525
1738
|
if (is_map_field(f)) {
|
1739
|
+
VALUE map;
|
1740
|
+
Map_iter map_it;
|
1741
|
+
|
1526
1742
|
if (!upb_fielddef_issubmsg(map_field_value(f))) continue;
|
1527
|
-
|
1743
|
+
map = DEREF(msg, offset, VALUE);
|
1528
1744
|
if (map == Qnil) continue;
|
1529
|
-
Map_iter map_it;
|
1530
1745
|
for (Map_begin(map, &map_it); !Map_done(&map_it); Map_next(&map_it)) {
|
1531
1746
|
VALUE submsg = Map_iter_value(&map_it);
|
1532
1747
|
VALUE descriptor = rb_ivar_get(submsg, descriptor_instancevar_interned);
|
@@ -1535,9 +1750,12 @@ static void discard_unknown(VALUE msg_rb, const Descriptor* desc) {
|
|
1535
1750
|
}
|
1536
1751
|
} else if (upb_fielddef_isseq(f)) {
|
1537
1752
|
VALUE ary = DEREF(msg, offset, VALUE);
|
1753
|
+
int size;
|
1754
|
+
int i;
|
1755
|
+
|
1538
1756
|
if (ary == Qnil) continue;
|
1539
|
-
|
1540
|
-
for (
|
1757
|
+
size = NUM2INT(RepeatedField_length(ary));
|
1758
|
+
for (i = 0; i < size; i++) {
|
1541
1759
|
void* memory = RepeatedField_index_native(ary, i);
|
1542
1760
|
VALUE submsg = *((VALUE *)memory);
|
1543
1761
|
VALUE descriptor = rb_ivar_get(submsg, descriptor_instancevar_interned);
|
@@ -1546,9 +1764,12 @@ static void discard_unknown(VALUE msg_rb, const Descriptor* desc) {
|
|
1546
1764
|
}
|
1547
1765
|
} else {
|
1548
1766
|
VALUE submsg = DEREF(msg, offset, VALUE);
|
1767
|
+
VALUE descriptor;
|
1768
|
+
const Descriptor* subdesc;
|
1769
|
+
|
1549
1770
|
if (submsg == Qnil) continue;
|
1550
|
-
|
1551
|
-
|
1771
|
+
descriptor = rb_ivar_get(submsg, descriptor_instancevar_interned);
|
1772
|
+
subdesc = ruby_to_Descriptor(descriptor);
|
1552
1773
|
discard_unknown(submsg, subdesc);
|
1553
1774
|
}
|
1554
1775
|
}
|