1// Protocol Buffers - Google's data interchange format 2// Copyright 2014 Google Inc. All rights reserved. 3// https://developers.google.com/protocol-buffers/ 4// 5// Redistribution and use in source and binary forms, with or without 6// modification, are permitted provided that the following conditions are 7// met: 8// 9// * Redistributions of source code must retain the above copyright 10// notice, this list of conditions and the following disclaimer. 11// * Redistributions in binary form must reproduce the above 12// copyright notice, this list of conditions and the following disclaimer 13// in the documentation and/or other materials provided with the 14// distribution. 15// * Neither the name of Google Inc. nor the names of its 16// contributors may be used to endorse or promote products derived from 17// this software without specific prior written permission. 18// 19// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 31#include "protobuf.h" 32 33VALUE initialize_rb_class_with_no_args(VALUE klass) { 34 return rb_funcall(klass, rb_intern("new"), 0); 35} 36 37// This function is equivalent to rb_str_cat(), but unlike the real 38// rb_str_cat(), it doesn't leak memory in some versions of Ruby. 39// For more information, see: 40// https://bugs.ruby-lang.org/issues/11328 41VALUE noleak_rb_str_cat(VALUE rb_str, const char *str, long len) { 42 char *p; 43 size_t oldlen = RSTRING_LEN(rb_str); 44 rb_str_modify_expand(rb_str, len); 45 p = RSTRING_PTR(rb_str); 46 memcpy(p + oldlen, str, len); 47 rb_str_set_len(rb_str, oldlen + len); 48 return rb_str; 49} 50 51bool 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 68// The code below also comes from upb's prototype Ruby binding, developed by 69// haberman@. 70 71/* stringsink *****************************************************************/ 72 73static void *stringsink_start(void *_sink, const void *hd, size_t size_hint) { 74 stringsink *sink = _sink; 75 sink->len = 0; 76 return sink; 77} 78 79static size_t stringsink_string(void *_sink, const void *hd, const char *ptr, 80 size_t len, const upb_bufhandle *handle) { 81 stringsink *sink = _sink; 82 size_t new_size = sink->size; 83 84 UPB_UNUSED(hd); 85 UPB_UNUSED(handle); 86 87 while (sink->len + len > new_size) { 88 new_size *= 2; 89 } 90 91 if (new_size != sink->size) { 92 sink->ptr = realloc(sink->ptr, new_size); 93 sink->size = new_size; 94 } 95 96 memcpy(sink->ptr + sink->len, ptr, len); 97 sink->len += len; 98 99 return len; 100} 101 102void stringsink_init(stringsink *sink) { 103 upb_byteshandler_init(&sink->handler); 104 upb_byteshandler_setstartstr(&sink->handler, stringsink_start, NULL); 105 upb_byteshandler_setstring(&sink->handler, stringsink_string, NULL); 106 107 upb_bytessink_reset(&sink->sink, &sink->handler, sink); 108 109 sink->size = 32; 110 sink->ptr = malloc(sink->size); 111 sink->len = 0; 112} 113 114void stringsink_uninit(stringsink *sink) { 115 free(sink->ptr); 116} 117 118// ----------------------------------------------------------------------------- 119// Parsing. 120// ----------------------------------------------------------------------------- 121 122#define DEREF(msg, ofs, type) *(type*)(((uint8_t *)msg) + ofs) 123 124typedef struct { 125 size_t ofs; 126 int32_t hasbit; 127} field_handlerdata_t; 128 129// Creates a handlerdata that contains the offset and the hasbit for the field 130static const void* newhandlerdata(upb_handlers* h, uint32_t ofs, int32_t hasbit) { 131 field_handlerdata_t *hd = ALLOC(field_handlerdata_t); 132 hd->ofs = ofs; 133 hd->hasbit = hasbit; 134 upb_handlers_addcleanup(h, hd, xfree); 135 return hd; 136} 137 138typedef struct { 139 size_t ofs; 140 int32_t hasbit; 141 upb_fieldtype_t wrapped_type; // Only for wrappers. 142 VALUE subklass; 143} submsg_handlerdata_t; 144 145// Creates a handlerdata that contains offset and submessage type information. 146static const void *newsubmsghandlerdata(upb_handlers* h, 147 const upb_fielddef *f, 148 uint32_t ofs, 149 int32_t hasbit, 150 VALUE subklass) { 151 submsg_handlerdata_t *hd = ALLOC(submsg_handlerdata_t); 152 const upb_msgdef *subm = upb_fielddef_msgsubdef(f); 153 hd->ofs = ofs; 154 hd->hasbit = hasbit; 155 hd->subklass = subklass; 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 } 161 return hd; 162} 163 164typedef struct { 165 size_t ofs; // union data slot 166 size_t case_ofs; // oneof_case field 167 uint32_t oneof_case_num; // oneof-case number to place in oneof_case field 168 VALUE subklass; 169} oneof_handlerdata_t; 170 171static const void *newoneofhandlerdata(upb_handlers *h, 172 uint32_t ofs, 173 uint32_t case_ofs, 174 const upb_fielddef *f, 175 const Descriptor* desc) { 176 oneof_handlerdata_t *hd = ALLOC(oneof_handlerdata_t); 177 hd->ofs = ofs; 178 hd->case_ofs = case_ofs; 179 // We reuse the field tag number as a oneof union discriminant tag. Note that 180 // we don't expose these numbers to the user, so the only requirement is that 181 // we have some unique ID for each union case/possibility. The field tag 182 // numbers are already present and are easy to use so there's no reason to 183 // create a separate ID space. In addition, using the field tag number here 184 // lets us easily look up the field in the oneof accessor. 185 hd->oneof_case_num = upb_fielddef_number(f); 186 if (is_value_field(f)) { 187 hd->oneof_case_num |= ONEOF_CASE_MASK; 188 } 189 hd->subklass = field_type_class(desc->layout, f); 190 upb_handlers_addcleanup(h, hd, xfree); 191 return hd; 192} 193 194// A handler that starts a repeated field. Gets the Repeated*Field instance for 195// this field (such an instance always exists even in an empty message). 196static void *startseq_handler(void* closure, const void* hd) { 197 MessageHeader* msg = closure; 198 const size_t *ofs = hd; 199 return (void*)DEREF(msg, *ofs, VALUE); 200} 201 202// Handlers that append primitive values to a repeated field. 203#define DEFINE_APPEND_HANDLER(type, ctype) \ 204 static bool append##type##_handler(void *closure, const void *hd, \ 205 ctype val) { \ 206 VALUE ary = (VALUE)closure; \ 207 RepeatedField_push_native(ary, &val); \ 208 return true; \ 209 } 210 211DEFINE_APPEND_HANDLER(bool, bool) 212DEFINE_APPEND_HANDLER(int32, int32_t) 213DEFINE_APPEND_HANDLER(uint32, uint32_t) 214DEFINE_APPEND_HANDLER(float, float) 215DEFINE_APPEND_HANDLER(int64, int64_t) 216DEFINE_APPEND_HANDLER(uint64, uint64_t) 217DEFINE_APPEND_HANDLER(double, double) 218 219// Appends a string to a repeated field. 220static void* appendstr_handler(void *closure, 221 const void *hd, 222 size_t size_hint) { 223 VALUE ary = (VALUE)closure; 224 VALUE str = rb_str_new2(""); 225 rb_enc_associate(str, kRubyStringUtf8Encoding); 226 RepeatedField_push_native(ary, &str); 227 return (void*)str; 228} 229 230static void set_hasbit(void *closure, int32_t hasbit) { 231 if (hasbit > 0) { 232 uint8_t* storage = closure; 233 storage[hasbit/8] |= 1 << (hasbit % 8); 234 } 235} 236 237// Appends a 'bytes' string to a repeated field. 238static void* appendbytes_handler(void *closure, 239 const void *hd, 240 size_t size_hint) { 241 VALUE ary = (VALUE)closure; 242 VALUE str = rb_str_new2(""); 243 rb_enc_associate(str, kRubyString8bitEncoding); 244 RepeatedField_push_native(ary, &str); 245 return (void*)str; 246} 247 248// Sets a non-repeated string field in a message. 249static void* str_handler(void *closure, 250 const void *hd, 251 size_t size_hint) { 252 MessageHeader* msg = closure; 253 const field_handlerdata_t *fieldhandler = hd; 254 255 VALUE str = rb_str_new2(""); 256 rb_enc_associate(str, kRubyStringUtf8Encoding); 257 DEREF(msg, fieldhandler->ofs, VALUE) = str; 258 set_hasbit(closure, fieldhandler->hasbit); 259 return (void*)str; 260} 261 262// Sets a non-repeated 'bytes' field in a message. 263static void* bytes_handler(void *closure, 264 const void *hd, 265 size_t size_hint) { 266 MessageHeader* msg = closure; 267 const field_handlerdata_t *fieldhandler = hd; 268 269 VALUE str = rb_str_new2(""); 270 rb_enc_associate(str, kRubyString8bitEncoding); 271 DEREF(msg, fieldhandler->ofs, VALUE) = str; 272 set_hasbit(closure, fieldhandler->hasbit); 273 return (void*)str; 274} 275 276static size_t stringdata_handler(void* closure, const void* hd, 277 const char* str, size_t len, 278 const upb_bufhandle* handle) { 279 VALUE rb_str = (VALUE)closure; 280 noleak_rb_str_cat(rb_str, str, len); 281 return len; 282} 283 284static bool stringdata_end_handler(void* closure, const void* hd) { 285 VALUE rb_str = (VALUE)closure; 286 rb_obj_freeze(rb_str); 287 return true; 288} 289 290static bool appendstring_end_handler(void* closure, const void* hd) { 291 VALUE rb_str = (VALUE)closure; 292 rb_obj_freeze(rb_str); 293 return true; 294} 295 296// Appends a submessage to a repeated field (a regular Ruby array for now). 297static void *appendsubmsg_handler(void *closure, const void *hd) { 298 VALUE ary = (VALUE)closure; 299 const submsg_handlerdata_t *submsgdata = hd; 300 MessageHeader* submsg; 301 302 VALUE submsg_rb = initialize_rb_class_with_no_args(submsgdata->subklass); 303 RepeatedField_push(ary, submsg_rb); 304 305 TypedData_Get_Struct(submsg_rb, MessageHeader, &Message_type, submsg); 306 return submsg; 307} 308 309// Appends a wrapper to a repeated field (a regular Ruby array for now). 310static 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 320// Sets a non-repeated submessage field in a message. 321static void *submsg_handler(void *closure, const void *hd) { 322 MessageHeader* msg = closure; 323 const submsg_handlerdata_t* submsgdata = hd; 324 VALUE submsg_rb; 325 MessageHeader* submsg; 326 327 if (DEREF(msg, submsgdata->ofs, VALUE) == Qnil) { 328 DEREF(msg, submsgdata->ofs, VALUE) = 329 initialize_rb_class_with_no_args(submsgdata->subklass); 330 } 331 332 set_hasbit(closure, submsgdata->hasbit); 333 334 submsg_rb = DEREF(msg, submsgdata->ofs, VALUE); 335 TypedData_Get_Struct(submsg_rb, MessageHeader, &Message_type, submsg); 336 337 return submsg; 338} 339 340static 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 376// Handler data for startmap/endmap handlers. 377typedef struct { 378 size_t ofs; 379 upb_fieldtype_t key_field_type; 380 upb_fieldtype_t value_field_type; 381 VALUE subklass; 382} map_handlerdata_t; 383 384// Temporary frame for map parsing: at the beginning of a map entry message, a 385// submsg handler allocates a frame to hold (i) a reference to the Map object 386// into which this message will be inserted and (ii) storage slots to 387// temporarily hold the key and value for this map entry until the end of the 388// submessage. When the submessage ends, another handler is called to insert the 389// value into the map. 390typedef struct { 391 VALUE map; 392 const map_handlerdata_t* handlerdata; 393 char key_storage[NATIVE_SLOT_MAX_SIZE]; 394 char value_storage[NATIVE_SLOT_MAX_SIZE]; 395} map_parse_frame_t; 396 397static void MapParseFrame_mark(void* _self) { 398 map_parse_frame_t* frame = _self; 399 400 // This shouldn't strictly be necessary since this should be rooted by the 401 // message itself, but it can't hurt. 402 rb_gc_mark(frame->map); 403 404 native_slot_mark(frame->handlerdata->key_field_type, &frame->key_storage); 405 native_slot_mark(frame->handlerdata->value_field_type, &frame->value_storage); 406} 407 408void MapParseFrame_free(void* self) { 409 xfree(self); 410} 411 412rb_data_type_t MapParseFrame_type = { 413 "MapParseFrame", 414 { MapParseFrame_mark, MapParseFrame_free, NULL }, 415}; 416 417// Handler to begin a map entry: allocates a temporary frame. This is the 418// 'startsubmsg' handler on the msgdef that contains the map field. 419static void *startmap_handler(void *closure, const void *hd) { 420 MessageHeader* msg = closure; 421 const map_handlerdata_t* mapdata = hd; 422 map_parse_frame_t* frame = ALLOC(map_parse_frame_t); 423 VALUE map_rb = DEREF(msg, mapdata->ofs, VALUE); 424 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 436static 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; 440} 441 442// Handler to end a map entry: inserts the value defined during the message into 443// the map. This is the 'endmsg' handler on the map entry msgdef. 444static bool endmapentry_handler(void* closure, const void* hd, upb_status* s) { 445 map_parse_frame_t* frame = closure; 446 const map_handlerdata_t* mapdata = hd; 447 448 VALUE key = native_slot_get( 449 mapdata->key_field_type, Qnil, 450 &frame->key_storage); 451 452 VALUE value = native_slot_get( 453 mapdata->value_field_type, mapdata->subklass, 454 &frame->value_storage); 455 456 Map_index_set(frame->map, key, value); 457 458 return true; 459} 460 461// Allocates a new map_handlerdata_t given the map entry message definition. If 462// the offset of the field within the parent message is also given, that is 463// added to the handler data as well. Note that this is called *twice* per map 464// field: once in the parent message handler setup when setting the startsubmsg 465// handler and once in the map entry message handler setup when setting the 466// key/value and endmsg handlers. The reason is that there is no easy way to 467// pass the handlerdata down to the sub-message handler setup. 468static map_handlerdata_t* new_map_handlerdata( 469 size_t ofs, 470 const upb_msgdef* mapentry_def, 471 const Descriptor* desc) { 472 const upb_fielddef* key_field; 473 const upb_fielddef* value_field; 474 map_handlerdata_t* hd = ALLOC(map_handlerdata_t); 475 hd->ofs = ofs; 476 key_field = upb_msgdef_itof(mapentry_def, MAP_KEY_FIELD); 477 assert(key_field != NULL); 478 hd->key_field_type = upb_fielddef_type(key_field); 479 value_field = upb_msgdef_itof(mapentry_def, MAP_VALUE_FIELD); 480 assert(value_field != NULL); 481 hd->value_field_type = upb_fielddef_type(value_field); 482 hd->subklass = field_type_class(desc->layout, value_field); 483 484 return hd; 485} 486 487// Handlers that set primitive values in oneofs. 488#define DEFINE_ONEOF_HANDLER(type, ctype) \ 489 static bool oneof##type##_handler(void *closure, const void *hd, \ 490 ctype val) { \ 491 const oneof_handlerdata_t *oneofdata = hd; \ 492 DEREF(closure, oneofdata->case_ofs, uint32_t) = \ 493 oneofdata->oneof_case_num; \ 494 DEREF(closure, oneofdata->ofs, ctype) = val; \ 495 return true; \ 496 } 497 498DEFINE_ONEOF_HANDLER(bool, bool) 499DEFINE_ONEOF_HANDLER(int32, int32_t) 500DEFINE_ONEOF_HANDLER(uint32, uint32_t) 501DEFINE_ONEOF_HANDLER(float, float) 502DEFINE_ONEOF_HANDLER(int64, int64_t) 503DEFINE_ONEOF_HANDLER(uint64, uint64_t) 504DEFINE_ONEOF_HANDLER(double, double) 505 506#undef DEFINE_ONEOF_HANDLER 507 508// Handlers for strings in a oneof. 509static void *oneofstr_handler(void *closure, 510 const void *hd, 511 size_t size_hint) { 512 MessageHeader* msg = closure; 513 const oneof_handlerdata_t *oneofdata = hd; 514 VALUE str = rb_str_new2(""); 515 rb_enc_associate(str, kRubyStringUtf8Encoding); 516 DEREF(msg, oneofdata->case_ofs, uint32_t) = 517 oneofdata->oneof_case_num; 518 DEREF(msg, oneofdata->ofs, VALUE) = str; 519 return (void*)str; 520} 521 522static void *oneofbytes_handler(void *closure, 523 const void *hd, 524 size_t size_hint) { 525 MessageHeader* msg = closure; 526 const oneof_handlerdata_t *oneofdata = hd; 527 VALUE str = rb_str_new2(""); 528 rb_enc_associate(str, kRubyString8bitEncoding); 529 DEREF(msg, oneofdata->case_ofs, uint32_t) = 530 oneofdata->oneof_case_num; 531 DEREF(msg, oneofdata->ofs, VALUE) = str; 532 return (void*)str; 533} 534 535static bool oneofstring_end_handler(void* closure, const void* hd) { 536 VALUE rb_str = rb_str_new2(""); 537 rb_obj_freeze(rb_str); 538 return true; 539} 540 541// Handler for a submessage field in a oneof. 542static void *oneofsubmsg_handler(void *closure, 543 const void *hd) { 544 MessageHeader* msg = closure; 545 const oneof_handlerdata_t *oneofdata = hd; 546 uint32_t oldcase = DEREF(msg, oneofdata->case_ofs, uint32_t); 547 548 VALUE submsg_rb; 549 MessageHeader* submsg; 550 551 if (oldcase != oneofdata->oneof_case_num || 552 DEREF(msg, oneofdata->ofs, VALUE) == Qnil) { 553 DEREF(msg, oneofdata->ofs, VALUE) = 554 initialize_rb_class_with_no_args(oneofdata->subklass); 555 } 556 // Set the oneof case *after* allocating the new class instance -- otherwise, 557 // if the Ruby GC is invoked as part of a call into the VM, it might invoke 558 // our mark routines, and our mark routines might see the case value 559 // indicating a VALUE is present and expect a valid VALUE. See comment in 560 // layout_set() for more detail: basically, the change to the value and the 561 // case must be atomic w.r.t. the Ruby VM. 562 DEREF(msg, oneofdata->case_ofs, uint32_t) = oneofdata->oneof_case_num; 563 564 submsg_rb = DEREF(msg, oneofdata->ofs, VALUE); 565 TypedData_Get_Struct(submsg_rb, MessageHeader, &Message_type, submsg); 566 return submsg; 567} 568 569static 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 578// Set up handlers for a repeated field. 579static void add_handlers_for_repeated_field(upb_handlers *h, 580 const Descriptor* desc, 581 const upb_fielddef *f, 582 size_t offset) { 583 upb_handlerattr attr = UPB_HANDLERATTR_INIT; 584 attr.handler_data = newhandlerdata(h, offset, -1); 585 upb_handlers_setstartseq(h, f, startseq_handler, &attr); 586 587 switch (upb_fielddef_type(f)) { 588 589#define SET_HANDLER(utype, ltype) \ 590 case utype: \ 591 upb_handlers_set##ltype(h, f, append##ltype##_handler, NULL); \ 592 break; 593 594 SET_HANDLER(UPB_TYPE_BOOL, bool); 595 SET_HANDLER(UPB_TYPE_INT32, int32); 596 SET_HANDLER(UPB_TYPE_UINT32, uint32); 597 SET_HANDLER(UPB_TYPE_ENUM, int32); 598 SET_HANDLER(UPB_TYPE_FLOAT, float); 599 SET_HANDLER(UPB_TYPE_INT64, int64); 600 SET_HANDLER(UPB_TYPE_UINT64, uint64); 601 SET_HANDLER(UPB_TYPE_DOUBLE, double); 602 603#undef SET_HANDLER 604 605 case UPB_TYPE_STRING: 606 case UPB_TYPE_BYTES: { 607 bool is_bytes = upb_fielddef_type(f) == UPB_TYPE_BYTES; 608 upb_handlers_setstartstr(h, f, is_bytes ? 609 appendbytes_handler : appendstr_handler, 610 NULL); 611 upb_handlers_setstring(h, f, stringdata_handler, NULL); 612 upb_handlers_setendstr(h, f, appendstring_end_handler, NULL); 613 break; 614 } 615 case UPB_TYPE_MESSAGE: { 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 } 624 break; 625 } 626 } 627} 628 629static bool doublewrapper_handler(void* closure, const void* hd, double val) { 630 VALUE* rbval = closure; 631 *rbval = DBL2NUM(val); 632 return true; 633} 634 635static bool floatwrapper_handler(void* closure, const void* hd, float val) { 636 VALUE* rbval = closure; 637 *rbval = DBL2NUM(val); 638 return true; 639} 640 641static bool int64wrapper_handler(void* closure, const void* hd, int64_t val) { 642 VALUE* rbval = closure; 643 *rbval = LL2NUM(val); 644 return true; 645} 646 647static bool uint64wrapper_handler(void* closure, const void* hd, uint64_t val) { 648 VALUE* rbval = closure; 649 *rbval = ULL2NUM(val); 650 return true; 651} 652 653static bool int32wrapper_handler(void* closure, const void* hd, int32_t val) { 654 VALUE* rbval = closure; 655 *rbval = INT2NUM(val); 656 return true; 657} 658 659static bool uint32wrapper_handler(void* closure, const void* hd, uint32_t val) { 660 VALUE* rbval = closure; 661 *rbval = UINT2NUM(val); 662 return true; 663} 664 665static 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 674static 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 682static 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 691static 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 699static 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 709// Set up handlers for a singular field. 710static 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) { 714 // The offset we pass to UPB points to the start of the Message, 715 // rather than the start of where our data is stored. 716 int32_t hasbit = -1; 717 if (hasbit_off != MESSAGE_FIELD_NO_HASBIT) { 718 hasbit = hasbit_off + sizeof(MessageHeader) * 8; 719 } 720 721 switch (upb_fielddef_type(f)) { 722 case UPB_TYPE_BOOL: 723 case UPB_TYPE_INT32: 724 case UPB_TYPE_UINT32: 725 case UPB_TYPE_ENUM: 726 case UPB_TYPE_FLOAT: 727 case UPB_TYPE_INT64: 728 case UPB_TYPE_UINT64: 729 case UPB_TYPE_DOUBLE: 730 upb_msg_setscalarhandler(h, f, offset, hasbit); 731 break; 732 case UPB_TYPE_STRING: 733 case UPB_TYPE_BYTES: { 734 bool is_bytes = upb_fielddef_type(f) == UPB_TYPE_BYTES; 735 upb_handlerattr attr = UPB_HANDLERATTR_INIT; 736 attr.handler_data = newhandlerdata(h, offset, hasbit); 737 upb_handlers_setstartstr(h, f, 738 is_bytes ? bytes_handler : str_handler, 739 &attr); 740 upb_handlers_setstring(h, f, stringdata_handler, &attr); 741 upb_handlers_setendstr(h, f, stringdata_end_handler, &attr); 742 break; 743 } 744 case UPB_TYPE_MESSAGE: { 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 } 753 } 754 } 755} 756 757// Adds handlers to a map field. 758static void add_handlers_for_mapfield(upb_handlers* h, 759 const upb_fielddef* fielddef, 760 size_t offset, 761 const Descriptor* desc) { 762 const upb_msgdef* map_msgdef = upb_fielddef_msgsubdef(fielddef); 763 map_handlerdata_t* hd = new_map_handlerdata(offset, map_msgdef, desc); 764 upb_handlerattr attr = UPB_HANDLERATTR_INIT; 765 766 upb_handlers_addcleanup(h, hd, xfree); 767 attr.handler_data = hd; 768 upb_handlers_setstartsubmsg(h, fielddef, startmap_handler, &attr); 769 upb_handlers_setendsubmsg(h, fielddef, endmap_handler, &attr); 770} 771 772// Adds handlers to a map-entry msgdef. 773static void add_handlers_for_mapentry(const upb_msgdef* msgdef, upb_handlers* h, 774 const Descriptor* desc) { 775 const upb_fielddef* key_field = map_entry_key(msgdef); 776 const upb_fielddef* value_field = map_entry_value(msgdef); 777 map_handlerdata_t* hd = new_map_handlerdata(0, msgdef, desc); 778 upb_handlerattr attr = UPB_HANDLERATTR_INIT; 779 780 upb_handlers_addcleanup(h, hd, xfree); 781 attr.handler_data = hd; 782 upb_handlers_setendmsg(h, endmapentry_handler, &attr); 783 784 add_handlers_for_singular_field( 785 desc, h, key_field, 786 offsetof(map_parse_frame_t, key_storage), 787 MESSAGE_FIELD_NO_HASBIT); 788 add_handlers_for_singular_field( 789 desc, h, value_field, 790 offsetof(map_parse_frame_t, value_storage), 791 MESSAGE_FIELD_NO_HASBIT); 792} 793 794static 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 833// Set up handlers for a oneof field. 834static void add_handlers_for_oneof_field(upb_handlers *h, 835 const upb_fielddef *f, 836 size_t offset, 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); 842 843 switch (upb_fielddef_type(f)) { 844 845#define SET_HANDLER(utype, ltype) \ 846 case utype: \ 847 upb_handlers_set##ltype(h, f, oneof##ltype##_handler, &attr); \ 848 break; 849 850 SET_HANDLER(UPB_TYPE_BOOL, bool); 851 SET_HANDLER(UPB_TYPE_INT32, int32); 852 SET_HANDLER(UPB_TYPE_UINT32, uint32); 853 SET_HANDLER(UPB_TYPE_ENUM, int32); 854 SET_HANDLER(UPB_TYPE_FLOAT, float); 855 SET_HANDLER(UPB_TYPE_INT64, int64); 856 SET_HANDLER(UPB_TYPE_UINT64, uint64); 857 SET_HANDLER(UPB_TYPE_DOUBLE, double); 858 859#undef SET_HANDLER 860 861 case UPB_TYPE_STRING: 862 case UPB_TYPE_BYTES: { 863 bool is_bytes = upb_fielddef_type(f) == UPB_TYPE_BYTES; 864 upb_handlers_setstartstr(h, f, is_bytes ? 865 oneofbytes_handler : oneofstr_handler, 866 &attr); 867 upb_handlers_setstring(h, f, stringdata_handler, NULL); 868 upb_handlers_setendstr(h, f, oneofstring_end_handler, &attr); 869 break; 870 } 871 case UPB_TYPE_MESSAGE: { 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 } 877 break; 878 } 879 } 880} 881 882static bool unknown_field_handler(void* closure, const void* hd, 883 const char* buf, size_t size) { 884 MessageHeader* msg = (MessageHeader*)closure; 885 UPB_UNUSED(hd); 886 887 if (msg->unknown_fields == NULL) { 888 msg->unknown_fields = malloc(sizeof(stringsink)); 889 stringsink_init(msg->unknown_fields); 890 } 891 892 stringsink_string(msg->unknown_fields, NULL, buf, size, NULL); 893 894 return true; 895} 896 897size_t get_field_offset(MessageLayout* layout, const upb_fielddef* f) { 898 return layout->fields[upb_fielddef_index(f)].offset + sizeof(MessageHeader); 899} 900 901void add_handlers_for_message(const void *closure, upb_handlers *h) { 902 const VALUE descriptor_pool = (VALUE)closure; 903 const upb_msgdef* msgdef = upb_handlers_msgdef(h); 904 Descriptor* desc = 905 ruby_to_Descriptor(get_msgdef_obj(descriptor_pool, msgdef)); 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 } 916 917 // If this is a mapentry message type, set up a special set of handlers and 918 // bail out of the normal (user-defined) message type handling. 919 if (upb_msgdef_mapentry(msgdef)) { 920 add_handlers_for_mapentry(msgdef, h, desc); 921 return; 922 } 923 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; 928 } 929 930 upb_handlers_setunknown(h, unknown_field_handler, &attr); 931 932 for (upb_msg_field_begin(&i, desc->msgdef); 933 !upb_msg_field_done(&i); 934 upb_msg_field_next(&i)) { 935 const upb_fielddef *f = upb_msg_iter_field(&i); 936 const upb_oneofdef* oneof = upb_fielddef_realcontainingoneof(f); 937 size_t offset = get_field_offset(desc->layout, f); 938 939 if (oneof) { 940 size_t oneof_case_offset = 941 desc->layout->oneofs[upb_oneofdef_index(oneof)].case_offset + 942 sizeof(MessageHeader); 943 add_handlers_for_oneof_field(h, f, offset, oneof_case_offset, desc); 944 } else if (is_map_field(f)) { 945 add_handlers_for_mapfield(h, f, offset, desc); 946 } else if (upb_fielddef_isseq(f)) { 947 add_handlers_for_repeated_field(h, desc, f, offset); 948 } else { 949 add_handlers_for_singular_field( 950 desc, h, f, offset, 951 desc->layout->fields[upb_fielddef_index(f)].hasbit); 952 } 953 } 954} 955 956// Constructs the handlers for filling a message's data into an in-memory 957// object. 958const upb_handlers* get_fill_handlers(Descriptor* desc) { 959 DescriptorPool* pool = ruby_to_DescriptorPool(desc->descriptor_pool); 960 return upb_handlercache_get(pool->fill_handler_cache, desc->msgdef); 961} 962 963static 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} 967 968static 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); 971} 972 973static 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); 976} 977 978static 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); 987 } 988} 989 990 991// Stack-allocated context during an encode/decode operation. Contains the upb 992// environment and its stack-based allocator, an initial buffer for allocations 993// to avoid malloc() when possible, and a template for Ruby exception messages 994// if any error occurs. 995#define STACK_ENV_STACKBYTES 4096 996typedef struct { 997 upb_arena *arena; 998 upb_status status; 999 const char* ruby_error_template; 1000 char allocbuf[STACK_ENV_STACKBYTES]; 1001} stackenv; 1002 1003static void stackenv_init(stackenv* se, const char* errmsg); 1004static void stackenv_uninit(stackenv* se); 1005 1006static void stackenv_init(stackenv* se, const char* errmsg) { 1007 se->ruby_error_template = errmsg; 1008 se->arena = 1009 upb_arena_init(se->allocbuf, sizeof(se->allocbuf), &upb_alloc_global); 1010 upb_status_clear(&se->status); 1011} 1012 1013static void stackenv_uninit(stackenv* se) { 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 } 1022} 1023 1024/* 1025 * call-seq: 1026 * MessageClass.decode(data) => message 1027 * 1028 * Decodes the given data (as a string containing bytes in protocol buffers wire 1029 * format) under the interpretration given by this message class's definition 1030 * and returns a message object with the corresponding field values. 1031 */ 1032VALUE Message_decode(VALUE klass, VALUE data) { 1033 VALUE descriptor = rb_ivar_get(klass, descriptor_instancevar_interned); 1034 Descriptor* desc = ruby_to_Descriptor(descriptor); 1035 VALUE msgklass = Descriptor_msgclass(descriptor); 1036 VALUE msg_rb; 1037 MessageHeader* msg; 1038 1039 if (TYPE(data) != T_STRING) { 1040 rb_raise(rb_eArgError, "Expected string for binary protobuf data."); 1041 } 1042 1043 msg_rb = initialize_rb_class_with_no_args(msgklass); 1044 TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg); 1045 1046 { 1047 const upb_pbdecodermethod* method = msgdef_decodermethod(desc); 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; 1052 stackenv se; 1053 upb_sink sink; 1054 upb_pbdecoder* decoder; 1055 stackenv_init(&se, "Error occurred during parsing: %" PRIsVALUE); 1056 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); 1063 upb_bufsrc_putbuf(RSTRING_PTR(data), RSTRING_LEN(data), 1064 upb_pbdecoder_input(decoder)); 1065 1066 stackenv_uninit(&se); 1067 1068 if (is_wrapper(m)) { 1069 msg_rb = ruby_wrapper_type(msgklass, wrapper); 1070 } 1071 } 1072 1073 return msg_rb; 1074} 1075 1076/* 1077 * call-seq: 1078 * MessageClass.decode_json(data, options = {}) => message 1079 * 1080 * Decodes the given data (as a string containing bytes in protocol buffers wire 1081 * format) under the interpretration given by this message class's definition 1082 * and returns a message object with the corresponding field values. 1083 * 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) 1087 */ 1088VALUE Message_decode_json(int argc, VALUE* argv, VALUE klass) { 1089 VALUE descriptor = rb_ivar_get(klass, descriptor_instancevar_interned); 1090 Descriptor* desc = ruby_to_Descriptor(descriptor); 1091 VALUE msgklass = Descriptor_msgclass(descriptor); 1092 VALUE msg_rb; 1093 VALUE data = argv[0]; 1094 VALUE ignore_unknown_fields = Qfalse; 1095 MessageHeader* msg; 1096 1097 if (argc < 1 || argc > 2) { 1098 rb_raise(rb_eArgError, "Expected 1 or 2 arguments."); 1099 } 1100 1101 if (argc == 2) { 1102 VALUE hash_args = argv[1]; 1103 if (TYPE(hash_args) != T_HASH) { 1104 rb_raise(rb_eArgError, "Expected hash arguments."); 1105 } 1106 1107 ignore_unknown_fields = rb_hash_lookup2( 1108 hash_args, ID2SYM(rb_intern("ignore_unknown_fields")), Qfalse); 1109 } 1110 1111 if (TYPE(data) != T_STRING) { 1112 rb_raise(rb_eArgError, "Expected string for JSON data."); 1113 } 1114 1115 // TODO(cfallin): Check and respect string encoding. If not UTF-8, we need to 1116 // convert, because string handlers pass data directly to message string 1117 // fields. 1118 1119 msg_rb = initialize_rb_class_with_no_args(msgklass); 1120 TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg); 1121 1122 { 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); 1126 stackenv se; 1127 upb_sink sink; 1128 upb_json_parser* parser; 1129 DescriptorPool* pool = ruby_to_DescriptorPool(generated_pool); 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 } 1137 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)); 1141 upb_bufsrc_putbuf(RSTRING_PTR(data), RSTRING_LEN(data), 1142 upb_json_parser_input(parser)); 1143 1144 stackenv_uninit(&se); 1145 } 1146 1147 return msg_rb; 1148} 1149 1150// ----------------------------------------------------------------------------- 1151// Serializing. 1152// ----------------------------------------------------------------------------- 1153 1154/* msgvisitor *****************************************************************/ 1155 1156static void putmsg(VALUE msg, const Descriptor* desc, upb_sink sink, int depth, 1157 bool emit_defaults, bool is_json, bool open_msg); 1158 1159static upb_selector_t getsel(const upb_fielddef *f, upb_handlertype_t type) { 1160 upb_selector_t ret; 1161 bool ok = upb_handlers_getselector(f, type, &ret); 1162 UPB_ASSERT(ok); 1163 return ret; 1164} 1165 1166static void putstr(VALUE str, const upb_fielddef *f, upb_sink sink) { 1167 upb_sink subsink; 1168 1169 if (str == Qnil) return; 1170 1171 assert(BUILTIN_TYPE(str) == RUBY_T_STRING); 1172 1173 // We should be guaranteed that the string has the correct encoding because 1174 // we ensured this at assignment time and then froze the string. 1175 if (upb_fielddef_type(f) == UPB_TYPE_STRING) { 1176 assert(rb_enc_from_index(ENCODING_GET(str)) == kRubyStringUtf8Encoding); 1177 } else { 1178 assert(rb_enc_from_index(ENCODING_GET(str)) == kRubyString8bitEncoding); 1179 } 1180 1181 upb_sink_startstr(sink, getsel(f, UPB_HANDLER_STARTSTR), RSTRING_LEN(str), 1182 &subsink); 1183 upb_sink_putstring(subsink, getsel(f, UPB_HANDLER_STRING), RSTRING_PTR(str), 1184 RSTRING_LEN(str), NULL); 1185 upb_sink_endstr(sink, getsel(f, UPB_HANDLER_ENDSTR)); 1186} 1187 1188static void putsubmsg(VALUE submsg, const upb_fielddef *f, upb_sink sink, 1189 int depth, bool emit_defaults, bool is_json) { 1190 upb_sink subsink; 1191 VALUE descriptor; 1192 Descriptor* subdesc; 1193 1194 if (submsg == Qnil) return; 1195 1196 descriptor = rb_ivar_get(submsg, descriptor_instancevar_interned); 1197 subdesc = ruby_to_Descriptor(descriptor); 1198 1199 upb_sink_startsubmsg(sink, getsel(f, UPB_HANDLER_STARTSUBMSG), &subsink); 1200 putmsg(submsg, subdesc, subsink, depth + 1, emit_defaults, is_json, true); 1201 upb_sink_endsubmsg(sink, subsink, getsel(f, UPB_HANDLER_ENDSUBMSG)); 1202} 1203 1204static void putary(VALUE ary, const upb_fielddef* f, upb_sink sink, int depth, 1205 bool emit_defaults, bool is_json) { 1206 upb_sink subsink; 1207 upb_fieldtype_t type = upb_fielddef_type(f); 1208 upb_selector_t sel = 0; 1209 int size; 1210 int i; 1211 VALUE type_class = ruby_to_RepeatedField(ary)->field_type_class; 1212 1213 if (ary == Qnil) return; 1214 if (!emit_defaults && NUM2INT(RepeatedField_length(ary)) == 0) return; 1215 1216 size = NUM2INT(RepeatedField_length(ary)); 1217 if (size == 0 && !emit_defaults) return; 1218 1219 upb_sink_startseq(sink, getsel(f, UPB_HANDLER_STARTSEQ), &subsink); 1220 1221 if (upb_fielddef_isprimitive(f)) { 1222 sel = getsel(f, upb_handlers_getprimitivehandlertype(f)); 1223 } 1224 1225 for (i = 0; i < size; i++) { 1226 void* memory = RepeatedField_index_native(ary, i); 1227 switch (type) { 1228#define T(upbtypeconst, upbtype, ctype) \ 1229 case upbtypeconst: \ 1230 upb_sink_put##upbtype(subsink, sel, *((ctype*)memory)); \ 1231 break; 1232 1233 T(UPB_TYPE_FLOAT, float, float) 1234 T(UPB_TYPE_DOUBLE, double, double) 1235 T(UPB_TYPE_BOOL, bool, int8_t) 1236 case UPB_TYPE_ENUM: 1237 T(UPB_TYPE_INT32, int32, int32_t) 1238 T(UPB_TYPE_UINT32, uint32, uint32_t) 1239 T(UPB_TYPE_INT64, int64, int64_t) 1240 T(UPB_TYPE_UINT64, uint64, uint64_t) 1241 1242 case UPB_TYPE_STRING: 1243 case UPB_TYPE_BYTES: 1244 putstr(*((VALUE *)memory), f, subsink); 1245 break; 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); 1249 break; 1250 } 1251 1252#undef T 1253 1254 } 1255 } 1256 upb_sink_endseq(sink, getsel(f, UPB_HANDLER_ENDSEQ)); 1257} 1258 1259static void put_ruby_value(VALUE value, const upb_fielddef* f, VALUE type_class, 1260 int depth, upb_sink sink, bool emit_defaults, 1261 bool is_json) { 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 1269 if (upb_fielddef_isprimitive(f)) { 1270 sel = getsel(f, upb_handlers_getprimitivehandlertype(f)); 1271 } 1272 1273 switch (upb_fielddef_type(f)) { 1274 case UPB_TYPE_INT32: 1275 upb_sink_putint32(sink, sel, NUM2INT(value)); 1276 break; 1277 case UPB_TYPE_INT64: 1278 upb_sink_putint64(sink, sel, NUM2LL(value)); 1279 break; 1280 case UPB_TYPE_UINT32: 1281 upb_sink_putuint32(sink, sel, NUM2UINT(value)); 1282 break; 1283 case UPB_TYPE_UINT64: 1284 upb_sink_putuint64(sink, sel, NUM2ULL(value)); 1285 break; 1286 case UPB_TYPE_FLOAT: 1287 upb_sink_putfloat(sink, sel, NUM2DBL(value)); 1288 break; 1289 case UPB_TYPE_DOUBLE: 1290 upb_sink_putdouble(sink, sel, NUM2DBL(value)); 1291 break; 1292 case UPB_TYPE_ENUM: { 1293 if (TYPE(value) == T_SYMBOL) { 1294 value = rb_funcall(type_class, rb_intern("resolve"), 1, value); 1295 } 1296 upb_sink_putint32(sink, sel, NUM2INT(value)); 1297 break; 1298 } 1299 case UPB_TYPE_BOOL: 1300 upb_sink_putbool(sink, sel, value == Qtrue); 1301 break; 1302 case UPB_TYPE_STRING: 1303 case UPB_TYPE_BYTES: 1304 putstr(value, f, sink); 1305 break; 1306 case UPB_TYPE_MESSAGE: 1307 putsubmsg(value, f, sink, depth, emit_defaults, is_json); 1308 } 1309} 1310 1311static void putmap(VALUE map, const upb_fielddef* f, upb_sink sink, int depth, 1312 bool emit_defaults, bool is_json) { 1313 Map* self; 1314 upb_sink subsink; 1315 const upb_fielddef* key_field; 1316 const upb_fielddef* value_field; 1317 Map_iter it; 1318 1319 if (map == Qnil) return; 1320 if (!emit_defaults && Map_length(map) == 0) return; 1321 1322 self = ruby_to_Map(map); 1323 1324 upb_sink_startseq(sink, getsel(f, UPB_HANDLER_STARTSEQ), &subsink); 1325 1326 assert(upb_fielddef_type(f) == UPB_TYPE_MESSAGE); 1327 key_field = map_field_key(f); 1328 value_field = map_field_value(f); 1329 1330 for (Map_begin(map, &it); !Map_done(&it); Map_next(&it)) { 1331 VALUE key = Map_iter_key(&it); 1332 VALUE value = Map_iter_value(&it); 1333 upb_status status; 1334 1335 upb_sink entry_sink; 1336 upb_sink_startsubmsg(subsink, getsel(f, UPB_HANDLER_STARTSUBMSG), 1337 &entry_sink); 1338 upb_sink_startmsg(entry_sink); 1339 1340 put_ruby_value(key, key_field, Qnil, depth + 1, entry_sink, emit_defaults, 1341 is_json); 1342 put_ruby_value(value, value_field, self->value_type_class, depth + 1, 1343 entry_sink, emit_defaults, is_json); 1344 1345 upb_sink_endmsg(entry_sink, &status); 1346 upb_sink_endsubmsg(subsink, entry_sink, getsel(f, UPB_HANDLER_ENDSUBMSG)); 1347 } 1348 1349 upb_sink_endseq(sink, getsel(f, UPB_HANDLER_ENDSEQ)); 1350} 1351 1352static const upb_handlers* msgdef_json_serialize_handlers( 1353 Descriptor* desc, bool preserve_proto_fieldnames); 1354 1355static void putjsonany(VALUE msg_rb, const Descriptor* desc, upb_sink sink, 1356 int depth, bool emit_defaults) { 1357 upb_status status; 1358 MessageHeader* msg = NULL; 1359 const upb_fielddef* type_field = upb_msgdef_itof(desc->msgdef, UPB_ANY_TYPE); 1360 const upb_fielddef* value_field = upb_msgdef_itof(desc->msgdef, UPB_ANY_VALUE); 1361 1362 size_t type_url_offset; 1363 VALUE type_url_str_rb; 1364 const upb_msgdef *payload_type = NULL; 1365 1366 TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg); 1367 1368 upb_sink_startmsg(sink); 1369 1370 /* Handle type url */ 1371 type_url_offset = desc->layout->fields[upb_fielddef_index(type_field)].offset; 1372 type_url_str_rb = DEREF(Message_data(msg), type_url_offset, VALUE); 1373 if (RSTRING_LEN(type_url_str_rb) > 0) { 1374 putstr(type_url_str_rb, type_field, sink); 1375 } 1376 1377 { 1378 const char* type_url_str = RSTRING_PTR(type_url_str_rb); 1379 size_t type_url_len = RSTRING_LEN(type_url_str_rb); 1380 DescriptorPool* pool = ruby_to_DescriptorPool(generated_pool); 1381 1382 if (type_url_len <= 20 || 1383 strncmp(type_url_str, "type.googleapis.com/", 20) != 0) { 1384 rb_raise(rb_eRuntimeError, "Invalid type url: %s", type_url_str); 1385 return; 1386 } 1387 1388 /* Resolve type url */ 1389 type_url_str += 20; 1390 type_url_len -= 20; 1391 1392 payload_type = upb_symtab_lookupmsg2( 1393 pool->symtab, type_url_str, type_url_len); 1394 if (payload_type == NULL) { 1395 rb_raise(rb_eRuntimeError, "Unknown type: %s", type_url_str); 1396 return; 1397 } 1398 } 1399 1400 { 1401 uint32_t value_offset; 1402 VALUE value_str_rb; 1403 size_t value_len; 1404 1405 value_offset = desc->layout->fields[upb_fielddef_index(value_field)].offset; 1406 value_str_rb = DEREF(Message_data(msg), value_offset, VALUE); 1407 value_len = RSTRING_LEN(value_str_rb); 1408 1409 if (value_len > 0) { 1410 VALUE payload_desc_rb = get_msgdef_obj(generated_pool, payload_type); 1411 Descriptor* payload_desc = ruby_to_Descriptor(payload_desc_rb); 1412 VALUE payload_class = Descriptor_msgclass(payload_desc_rb); 1413 upb_sink subsink; 1414 bool is_wellknown; 1415 1416 VALUE payload_msg_rb = Message_decode(payload_class, value_str_rb); 1417 1418 is_wellknown = 1419 upb_msgdef_wellknowntype(payload_desc->msgdef) != 1420 UPB_WELLKNOWN_UNSPECIFIED; 1421 if (is_wellknown) { 1422 upb_sink_startstr(sink, getsel(value_field, UPB_HANDLER_STARTSTR), 0, 1423 &subsink); 1424 } 1425 1426 subsink.handlers = 1427 msgdef_json_serialize_handlers(payload_desc, true); 1428 subsink.closure = sink.closure; 1429 putmsg(payload_msg_rb, payload_desc, subsink, depth, emit_defaults, true, 1430 is_wellknown); 1431 } 1432 } 1433 1434 upb_sink_endmsg(sink, &status); 1435} 1436 1437static 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 1465static void putmsg(VALUE msg_rb, const Descriptor* desc, 1466 upb_sink sink, int depth, bool emit_defaults, 1467 bool is_json, bool open_msg) { 1468 MessageHeader* msg; 1469 upb_msg_field_iter i; 1470 upb_status status; 1471 bool json_wrapper = is_wrapper(desc->msgdef) && is_json; 1472 1473 if (is_json && 1474 upb_msgdef_wellknowntype(desc->msgdef) == UPB_WELLKNOWN_ANY) { 1475 putjsonany(msg_rb, desc, sink, depth, emit_defaults); 1476 return; 1477 } 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 1485 if (open_msg) { 1486 upb_sink_startmsg(sink); 1487 } 1488 1489 // Protect against cycles (possible because users may freely reassign message 1490 // and repeated fields) by imposing a maximum recursion depth. 1491 if (depth > ENCODE_MAX_NESTING) { 1492 rb_raise(rb_eRuntimeError, 1493 "Maximum recursion depth exceeded during encoding."); 1494 } 1495 1496 TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg); 1497 1498 if (desc != msg->descriptor) { 1499 rb_raise(rb_eArgError, 1500 "The type of given msg is '%s', expect '%s'.", 1501 upb_msgdef_fullname(msg->descriptor->msgdef), 1502 upb_msgdef_fullname(desc->msgdef)); 1503 } 1504 1505 for (upb_msg_field_begin(&i, desc->msgdef); 1506 !upb_msg_field_done(&i); 1507 upb_msg_field_next(&i)) { 1508 upb_fielddef *f = upb_msg_iter_field(&i); 1509 const upb_oneofdef* oneof = upb_fielddef_realcontainingoneof(f); 1510 bool is_matching_oneof = false; 1511 uint32_t offset = 1512 desc->layout->fields[upb_fielddef_index(f)].offset + 1513 sizeof(MessageHeader); 1514 1515 if (oneof) { 1516 uint32_t oneof_case = 1517 slot_read_oneof_case(desc->layout, Message_data(msg), oneof); 1518 // For a oneof, check that this field is actually present -- skip all the 1519 // below if not. 1520 if (oneof_case != upb_fielddef_number(f)) { 1521 continue; 1522 } 1523 // Otherwise, fall through to the appropriate singular-field handler 1524 // below. 1525 is_matching_oneof = true; 1526 } 1527 1528 if (is_map_field(f)) { 1529 VALUE map = DEREF(msg, offset, VALUE); 1530 if (map != Qnil || emit_defaults) { 1531 putmap(map, f, sink, depth, emit_defaults, is_json); 1532 } 1533 } else if (upb_fielddef_isseq(f)) { 1534 VALUE ary = DEREF(msg, offset, VALUE); 1535 if (ary != Qnil) { 1536 putary(ary, f, sink, depth, emit_defaults, is_json); 1537 } 1538 } else if (upb_fielddef_isstring(f)) { 1539 VALUE str = DEREF(msg, offset, VALUE); 1540 bool is_default = false; 1541 1542 if (upb_msgdef_syntax(desc->msgdef) == UPB_SYNTAX_PROTO2) { 1543 is_default = layout_has(desc->layout, Message_data(msg), f) == Qfalse; 1544 } else if (upb_msgdef_syntax(desc->msgdef) == UPB_SYNTAX_PROTO3) { 1545 is_default = RSTRING_LEN(str) == 0; 1546 } 1547 1548 if (is_matching_oneof || emit_defaults || !is_default || json_wrapper) { 1549 putstr(str, f, sink); 1550 } 1551 } else if (upb_fielddef_issubmsg(f)) { 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); 1556 } else { 1557 upb_selector_t sel = getsel(f, upb_handlers_getprimitivehandlertype(f)); 1558 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; 1572 1573 switch (upb_fielddef_type(f)) { 1574 T(UPB_TYPE_FLOAT, float, float, 0.0) 1575 T(UPB_TYPE_DOUBLE, double, double, 0.0) 1576 T(UPB_TYPE_BOOL, bool, uint8_t, 0) 1577 case UPB_TYPE_ENUM: 1578 T(UPB_TYPE_INT32, int32, int32_t, 0) 1579 T(UPB_TYPE_UINT32, uint32, uint32_t, 0) 1580 T(UPB_TYPE_INT64, int64, int64_t, 0) 1581 T(UPB_TYPE_UINT64, uint64, uint64_t, 0) 1582 1583 case UPB_TYPE_STRING: 1584 case UPB_TYPE_BYTES: 1585 case UPB_TYPE_MESSAGE: rb_raise(rb_eRuntimeError, "Internal error."); 1586 } 1587 1588#undef T 1589 } 1590 } 1591 1592 { 1593 stringsink* unknown = msg->unknown_fields; 1594 if (unknown != NULL) { 1595 upb_sink_putunknown(sink, unknown->ptr, unknown->len); 1596 } 1597 } 1598 1599 if (open_msg) { 1600 upb_sink_endmsg(sink, &status); 1601 } 1602} 1603 1604/* 1605 * call-seq: 1606 * MessageClass.encode(msg) => bytes 1607 * 1608 * Encodes the given message object to its serialized form in protocol buffers 1609 * wire format. 1610 */ 1611VALUE Message_encode(VALUE klass, VALUE msg_rb) { 1612 VALUE descriptor = rb_ivar_get(klass, descriptor_instancevar_interned); 1613 Descriptor* desc = ruby_to_Descriptor(descriptor); 1614 1615 stringsink sink; 1616 stringsink_init(&sink); 1617 1618 { 1619 const upb_handlers* serialize_handlers = 1620 msgdef_pb_serialize_handlers(desc); 1621 1622 stackenv se; 1623 upb_pb_encoder* encoder; 1624 VALUE ret; 1625 1626 stackenv_init(&se, "Error occurred during encoding: %" PRIsVALUE); 1627 encoder = upb_pb_encoder_create(se.arena, serialize_handlers, sink.sink); 1628 1629 putmsg(msg_rb, desc, upb_pb_encoder_input(encoder), 0, false, false, true); 1630 1631 ret = rb_str_new(sink.ptr, sink.len); 1632 1633 stackenv_uninit(&se); 1634 stringsink_uninit(&sink); 1635 1636 return ret; 1637 } 1638} 1639 1640/* 1641 * call-seq: 1642 * MessageClass.encode_json(msg, options = {}) => json_string 1643 * 1644 * Encodes the given message object into its serialized JSON representation. 1645 * @param options [Hash] options for the decoder 1646 * preserve_proto_fieldnames: set true to use original fieldnames (default is to camelCase) 1647 * emit_defaults: set true to emit 0/false values (default is to omit them) 1648 */ 1649VALUE Message_encode_json(int argc, VALUE* argv, VALUE klass) { 1650 VALUE descriptor = rb_ivar_get(klass, descriptor_instancevar_interned); 1651 Descriptor* desc = ruby_to_Descriptor(descriptor); 1652 VALUE msg_rb; 1653 VALUE preserve_proto_fieldnames = Qfalse; 1654 VALUE emit_defaults = Qfalse; 1655 stringsink sink; 1656 1657 if (argc < 1 || argc > 2) { 1658 rb_raise(rb_eArgError, "Expected 1 or 2 arguments."); 1659 } 1660 1661 msg_rb = argv[0]; 1662 1663 if (argc == 2) { 1664 VALUE hash_args = argv[1]; 1665 if (TYPE(hash_args) != T_HASH) { 1666 rb_raise(rb_eArgError, "Expected hash arguments."); 1667 } 1668 preserve_proto_fieldnames = rb_hash_lookup2( 1669 hash_args, ID2SYM(rb_intern("preserve_proto_fieldnames")), Qfalse); 1670 1671 emit_defaults = rb_hash_lookup2( 1672 hash_args, ID2SYM(rb_intern("emit_defaults")), Qfalse); 1673 } 1674 1675 stringsink_init(&sink); 1676 1677 { 1678 const upb_handlers* serialize_handlers = 1679 msgdef_json_serialize_handlers(desc, RTEST(preserve_proto_fieldnames)); 1680 upb_json_printer* printer; 1681 stackenv se; 1682 VALUE ret; 1683 1684 stackenv_init(&se, "Error occurred during encoding: %" PRIsVALUE); 1685 printer = upb_json_printer_create(se.arena, serialize_handlers, sink.sink); 1686 1687 putmsg(msg_rb, desc, upb_json_printer_input(printer), 0, 1688 RTEST(emit_defaults), true, true); 1689 1690 ret = rb_enc_str_new(sink.ptr, sink.len, rb_utf8_encoding()); 1691 1692 stackenv_uninit(&se); 1693 stringsink_uninit(&sink); 1694 1695 return ret; 1696 } 1697} 1698 1699static void discard_unknown(VALUE msg_rb, const Descriptor* desc) { 1700 MessageHeader* msg; 1701 upb_msg_field_iter it; 1702 1703 TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg); 1704 1705 { 1706 stringsink* unknown = msg->unknown_fields; 1707 if (unknown != NULL) { 1708 stringsink_uninit(unknown); 1709 msg->unknown_fields = NULL; 1710 } 1711 } 1712 1713 for (upb_msg_field_begin(&it, desc->msgdef); 1714 !upb_msg_field_done(&it); 1715 upb_msg_field_next(&it)) { 1716 upb_fielddef *f = upb_msg_iter_field(&it); 1717 const upb_oneofdef* oneof = upb_fielddef_realcontainingoneof(f); 1718 uint32_t offset = 1719 desc->layout->fields[upb_fielddef_index(f)].offset + 1720 sizeof(MessageHeader); 1721 1722 if (oneof) { 1723 uint32_t oneof_case = 1724 slot_read_oneof_case(desc->layout, Message_data(msg), oneof); 1725 // For a oneof, check that this field is actually present -- skip all the 1726 // below if not. 1727 if (oneof_case != upb_fielddef_number(f)) { 1728 continue; 1729 } 1730 // Otherwise, fall through to the appropriate singular-field handler 1731 // below. 1732 } 1733 1734 if (!upb_fielddef_issubmsg(f)) { 1735 continue; 1736 } 1737 1738 if (is_map_field(f)) { 1739 VALUE map; 1740 Map_iter map_it; 1741 1742 if (!upb_fielddef_issubmsg(map_field_value(f))) continue; 1743 map = DEREF(msg, offset, VALUE); 1744 if (map == Qnil) continue; 1745 for (Map_begin(map, &map_it); !Map_done(&map_it); Map_next(&map_it)) { 1746 VALUE submsg = Map_iter_value(&map_it); 1747 VALUE descriptor = rb_ivar_get(submsg, descriptor_instancevar_interned); 1748 const Descriptor* subdesc = ruby_to_Descriptor(descriptor); 1749 discard_unknown(submsg, subdesc); 1750 } 1751 } else if (upb_fielddef_isseq(f)) { 1752 VALUE ary = DEREF(msg, offset, VALUE); 1753 int size; 1754 int i; 1755 1756 if (ary == Qnil) continue; 1757 size = NUM2INT(RepeatedField_length(ary)); 1758 for (i = 0; i < size; i++) { 1759 void* memory = RepeatedField_index_native(ary, i); 1760 VALUE submsg = *((VALUE *)memory); 1761 VALUE descriptor = rb_ivar_get(submsg, descriptor_instancevar_interned); 1762 const Descriptor* subdesc = ruby_to_Descriptor(descriptor); 1763 discard_unknown(submsg, subdesc); 1764 } 1765 } else { 1766 VALUE submsg = DEREF(msg, offset, VALUE); 1767 VALUE descriptor; 1768 const Descriptor* subdesc; 1769 1770 if (submsg == Qnil) continue; 1771 descriptor = rb_ivar_get(submsg, descriptor_instancevar_interned); 1772 subdesc = ruby_to_Descriptor(descriptor); 1773 discard_unknown(submsg, subdesc); 1774 } 1775 } 1776} 1777 1778/* 1779 * call-seq: 1780 * Google::Protobuf.discard_unknown(msg) 1781 * 1782 * Discard unknown fields in the given message object and recursively discard 1783 * unknown fields in submessages. 1784 */ 1785VALUE Google_Protobuf_discard_unknown(VALUE self, VALUE msg_rb) { 1786 VALUE klass = CLASS_OF(msg_rb); 1787 VALUE descriptor = rb_ivar_get(klass, descriptor_instancevar_interned); 1788 Descriptor* desc = ruby_to_Descriptor(descriptor); 1789 if (klass == cRepeatedField || klass == cMap) { 1790 rb_raise(rb_eArgError, "Expected proto msg for discard unknown."); 1791 } else { 1792 discard_unknown(msg_rb, desc); 1793 } 1794 return Qnil; 1795} 1796