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 33 #include <math.h> 34 35 #include <ruby/encoding.h> 36 37 // ----------------------------------------------------------------------------- 38 // Ruby <-> native slot management. 39 // ----------------------------------------------------------------------------- 40 41 #define DEREF(memory, type) *(type*)(memory) 42 43 size_t native_slot_size(upb_fieldtype_t type) { 44 switch (type) { 45 case UPB_TYPE_FLOAT: return 4; 46 case UPB_TYPE_DOUBLE: return 8; 47 case UPB_TYPE_BOOL: return 1; 48 case UPB_TYPE_STRING: return sizeof(VALUE); 49 case UPB_TYPE_BYTES: return sizeof(VALUE); 50 case UPB_TYPE_MESSAGE: return sizeof(VALUE); 51 case UPB_TYPE_ENUM: return 4; 52 case UPB_TYPE_INT32: return 4; 53 case UPB_TYPE_INT64: return 8; 54 case UPB_TYPE_UINT32: return 4; 55 case UPB_TYPE_UINT64: return 8; 56 default: return 0; 57 } 58 } 59 60 static bool is_ruby_num(VALUE value) { 61 return (TYPE(value) == T_FLOAT || 62 TYPE(value) == T_FIXNUM || 63 TYPE(value) == T_BIGNUM); 64 } 65 66 void native_slot_check_int_range_precision(upb_fieldtype_t type, VALUE val) { 67 if (!is_ruby_num(val)) { 68 rb_raise(rb_eTypeError, "Expected number type for integral field."); 69 } 70 71 // NUM2{INT,UINT,LL,ULL} macros do the appropriate range checks on upper 72 // bound; we just need to do precision checks (i.e., disallow rounding) and 73 // check for < 0 on unsigned types. 74 if (TYPE(val) == T_FLOAT) { 75 double dbl_val = NUM2DBL(val); 76 if (floor(dbl_val) != dbl_val) { 77 rb_raise(rb_eRangeError, 78 "Non-integral floating point value assigned to integer field."); 79 } 80 } 81 if (type == UPB_TYPE_UINT32 || type == UPB_TYPE_UINT64) { 82 if (NUM2DBL(val) < 0) { 83 rb_raise(rb_eRangeError, 84 "Assigning negative value to unsigned integer field."); 85 } 86 } 87 } 88 89 void native_slot_validate_string_encoding(upb_fieldtype_t type, VALUE value) { 90 bool bad_encoding = false; 91 rb_encoding* string_encoding = rb_enc_from_index(ENCODING_GET(value)); 92 if (type == UPB_TYPE_STRING) { 93 bad_encoding = 94 string_encoding != kRubyStringUtf8Encoding && 95 string_encoding != kRubyStringASCIIEncoding; 96 } else { 97 bad_encoding = 98 string_encoding != kRubyString8bitEncoding; 99 } 100 // Check that encoding is UTF-8 or ASCII (for string fields) or ASCII-8BIT 101 // (for bytes fields). 102 if (bad_encoding) { 103 rb_raise(rb_eTypeError, "Encoding for '%s' fields must be %s (was %s)", 104 (type == UPB_TYPE_STRING) ? "string" : "bytes", 105 (type == UPB_TYPE_STRING) ? "UTF-8 or ASCII" : "ASCII-8BIT", 106 rb_enc_name(string_encoding)); 107 } 108 } 109 110 void native_slot_set(upb_fieldtype_t type, VALUE type_class, 111 void* memory, VALUE value) { 112 native_slot_set_value_and_case(type, type_class, memory, value, NULL, 0); 113 } 114 115 void native_slot_set_value_and_case(upb_fieldtype_t type, VALUE type_class, 116 void* memory, VALUE value, 117 uint32_t* case_memory, 118 uint32_t case_number) { 119 // Note that in order to atomically change the value in memory and the case 120 // value (w.r.t. Ruby VM calls), we must set the value at |memory| only after 121 // all Ruby VM calls are complete. The case is then set at the bottom of this 122 // function. 123 switch (type) { 124 case UPB_TYPE_FLOAT: 125 if (!is_ruby_num(value)) { 126 rb_raise(rb_eTypeError, "Expected number type for float field."); 127 } 128 DEREF(memory, float) = NUM2DBL(value); 129 break; 130 case UPB_TYPE_DOUBLE: 131 if (!is_ruby_num(value)) { 132 rb_raise(rb_eTypeError, "Expected number type for double field."); 133 } 134 DEREF(memory, double) = NUM2DBL(value); 135 break; 136 case UPB_TYPE_BOOL: { 137 int8_t val = -1; 138 if (value == Qtrue) { 139 val = 1; 140 } else if (value == Qfalse) { 141 val = 0; 142 } else { 143 rb_raise(rb_eTypeError, "Invalid argument for boolean field."); 144 } 145 DEREF(memory, int8_t) = val; 146 break; 147 } 148 case UPB_TYPE_STRING: 149 case UPB_TYPE_BYTES: { 150 if (CLASS_OF(value) != rb_cString) { 151 rb_raise(rb_eTypeError, "Invalid argument for string field."); 152 } 153 native_slot_validate_string_encoding(type, value); 154 DEREF(memory, VALUE) = value; 155 break; 156 } 157 case UPB_TYPE_MESSAGE: { 158 if (CLASS_OF(value) == CLASS_OF(Qnil)) { 159 value = Qnil; 160 } else if (CLASS_OF(value) != type_class) { 161 rb_raise(rb_eTypeError, 162 "Invalid type %s to assign to submessage field.", 163 rb_class2name(CLASS_OF(value))); 164 } 165 DEREF(memory, VALUE) = value; 166 break; 167 } 168 case UPB_TYPE_ENUM: { 169 int32_t int_val = 0; 170 if (!is_ruby_num(value) && TYPE(value) != T_SYMBOL) { 171 rb_raise(rb_eTypeError, 172 "Expected number or symbol type for enum field."); 173 } 174 if (TYPE(value) == T_SYMBOL) { 175 // Ensure that the given symbol exists in the enum module. 176 VALUE lookup = rb_funcall(type_class, rb_intern("resolve"), 1, value); 177 if (lookup == Qnil) { 178 rb_raise(rb_eRangeError, "Unknown symbol value for enum field."); 179 } else { 180 int_val = NUM2INT(lookup); 181 } 182 } else { 183 native_slot_check_int_range_precision(UPB_TYPE_INT32, value); 184 int_val = NUM2INT(value); 185 } 186 DEREF(memory, int32_t) = int_val; 187 break; 188 } 189 case UPB_TYPE_INT32: 190 case UPB_TYPE_INT64: 191 case UPB_TYPE_UINT32: 192 case UPB_TYPE_UINT64: 193 native_slot_check_int_range_precision(type, value); 194 switch (type) { 195 case UPB_TYPE_INT32: 196 DEREF(memory, int32_t) = NUM2INT(value); 197 break; 198 case UPB_TYPE_INT64: 199 DEREF(memory, int64_t) = NUM2LL(value); 200 break; 201 case UPB_TYPE_UINT32: 202 DEREF(memory, uint32_t) = NUM2UINT(value); 203 break; 204 case UPB_TYPE_UINT64: 205 DEREF(memory, uint64_t) = NUM2ULL(value); 206 break; 207 default: 208 break; 209 } 210 break; 211 default: 212 break; 213 } 214 215 if (case_memory != NULL) { 216 *case_memory = case_number; 217 } 218 } 219 220 VALUE native_slot_get(upb_fieldtype_t type, 221 VALUE type_class, 222 const void* memory) { 223 switch (type) { 224 case UPB_TYPE_FLOAT: 225 return DBL2NUM(DEREF(memory, float)); 226 case UPB_TYPE_DOUBLE: 227 return DBL2NUM(DEREF(memory, double)); 228 case UPB_TYPE_BOOL: 229 return DEREF(memory, int8_t) ? Qtrue : Qfalse; 230 case UPB_TYPE_STRING: 231 case UPB_TYPE_BYTES: 232 case UPB_TYPE_MESSAGE: 233 return DEREF(memory, VALUE); 234 case UPB_TYPE_ENUM: { 235 int32_t val = DEREF(memory, int32_t); 236 VALUE symbol = enum_lookup(type_class, INT2NUM(val)); 237 if (symbol == Qnil) { 238 return INT2NUM(val); 239 } else { 240 return symbol; 241 } 242 } 243 case UPB_TYPE_INT32: 244 return INT2NUM(DEREF(memory, int32_t)); 245 case UPB_TYPE_INT64: 246 return LL2NUM(DEREF(memory, int64_t)); 247 case UPB_TYPE_UINT32: 248 return UINT2NUM(DEREF(memory, uint32_t)); 249 case UPB_TYPE_UINT64: 250 return ULL2NUM(DEREF(memory, uint64_t)); 251 default: 252 return Qnil; 253 } 254 } 255 256 void native_slot_init(upb_fieldtype_t type, void* memory) { 257 switch (type) { 258 case UPB_TYPE_FLOAT: 259 DEREF(memory, float) = 0.0; 260 break; 261 case UPB_TYPE_DOUBLE: 262 DEREF(memory, double) = 0.0; 263 break; 264 case UPB_TYPE_BOOL: 265 DEREF(memory, int8_t) = 0; 266 break; 267 case UPB_TYPE_STRING: 268 case UPB_TYPE_BYTES: 269 DEREF(memory, VALUE) = rb_str_new2(""); 270 rb_enc_associate(DEREF(memory, VALUE), (type == UPB_TYPE_BYTES) ? 271 kRubyString8bitEncoding : kRubyStringUtf8Encoding); 272 break; 273 case UPB_TYPE_MESSAGE: 274 DEREF(memory, VALUE) = Qnil; 275 break; 276 case UPB_TYPE_ENUM: 277 case UPB_TYPE_INT32: 278 DEREF(memory, int32_t) = 0; 279 break; 280 case UPB_TYPE_INT64: 281 DEREF(memory, int64_t) = 0; 282 break; 283 case UPB_TYPE_UINT32: 284 DEREF(memory, uint32_t) = 0; 285 break; 286 case UPB_TYPE_UINT64: 287 DEREF(memory, uint64_t) = 0; 288 break; 289 default: 290 break; 291 } 292 } 293 294 void native_slot_mark(upb_fieldtype_t type, void* memory) { 295 switch (type) { 296 case UPB_TYPE_STRING: 297 case UPB_TYPE_BYTES: 298 case UPB_TYPE_MESSAGE: 299 rb_gc_mark(DEREF(memory, VALUE)); 300 break; 301 default: 302 break; 303 } 304 } 305 306 void native_slot_dup(upb_fieldtype_t type, void* to, void* from) { 307 memcpy(to, from, native_slot_size(type)); 308 } 309 310 void native_slot_deep_copy(upb_fieldtype_t type, void* to, void* from) { 311 switch (type) { 312 case UPB_TYPE_STRING: 313 case UPB_TYPE_BYTES: { 314 VALUE from_val = DEREF(from, VALUE); 315 DEREF(to, VALUE) = (from_val != Qnil) ? 316 rb_funcall(from_val, rb_intern("dup"), 0) : Qnil; 317 break; 318 } 319 case UPB_TYPE_MESSAGE: { 320 VALUE from_val = DEREF(from, VALUE); 321 DEREF(to, VALUE) = (from_val != Qnil) ? 322 Message_deep_copy(from_val) : Qnil; 323 break; 324 } 325 default: 326 memcpy(to, from, native_slot_size(type)); 327 } 328 } 329 330 bool native_slot_eq(upb_fieldtype_t type, void* mem1, void* mem2) { 331 switch (type) { 332 case UPB_TYPE_STRING: 333 case UPB_TYPE_BYTES: 334 case UPB_TYPE_MESSAGE: { 335 VALUE val1 = DEREF(mem1, VALUE); 336 VALUE val2 = DEREF(mem2, VALUE); 337 VALUE ret = rb_funcall(val1, rb_intern("=="), 1, val2); 338 return ret == Qtrue; 339 } 340 default: 341 return !memcmp(mem1, mem2, native_slot_size(type)); 342 } 343 } 344 345 // ----------------------------------------------------------------------------- 346 // Map field utilities. 347 // ----------------------------------------------------------------------------- 348 349 const upb_msgdef* tryget_map_entry_msgdef(const upb_fielddef* field) { 350 const upb_msgdef* subdef; 351 if (upb_fielddef_label(field) != UPB_LABEL_REPEATED || 352 upb_fielddef_type(field) != UPB_TYPE_MESSAGE) { 353 return NULL; 354 } 355 subdef = upb_fielddef_msgsubdef(field); 356 return upb_msgdef_mapentry(subdef) ? subdef : NULL; 357 } 358 359 const upb_msgdef *map_entry_msgdef(const upb_fielddef* field) { 360 const upb_msgdef* subdef = tryget_map_entry_msgdef(field); 361 assert(subdef); 362 return subdef; 363 } 364 365 bool is_map_field(const upb_fielddef *field) { 366 return tryget_map_entry_msgdef(field) != NULL; 367 } 368 369 const upb_fielddef* map_field_key(const upb_fielddef* field) { 370 const upb_msgdef* subdef = map_entry_msgdef(field); 371 return map_entry_key(subdef); 372 } 373 374 const upb_fielddef* map_field_value(const upb_fielddef* field) { 375 const upb_msgdef* subdef = map_entry_msgdef(field); 376 return map_entry_value(subdef); 377 } 378 379 const upb_fielddef* map_entry_key(const upb_msgdef* msgdef) { 380 const upb_fielddef* key_field = upb_msgdef_itof(msgdef, MAP_KEY_FIELD); 381 assert(key_field != NULL); 382 return key_field; 383 } 384 385 const upb_fielddef* map_entry_value(const upb_msgdef* msgdef) { 386 const upb_fielddef* value_field = upb_msgdef_itof(msgdef, MAP_VALUE_FIELD); 387 assert(value_field != NULL); 388 return value_field; 389 } 390 391 // ----------------------------------------------------------------------------- 392 // Memory layout management. 393 // ----------------------------------------------------------------------------- 394 395 static size_t align_up_to(size_t offset, size_t granularity) { 396 // Granularity must be a power of two. 397 return (offset + granularity - 1) & ~(granularity - 1); 398 } 399 400 MessageLayout* create_layout(const upb_msgdef* msgdef) { 401 MessageLayout* layout = ALLOC(MessageLayout); 402 int nfields = upb_msgdef_numfields(msgdef); 403 upb_msg_field_iter it; 404 upb_msg_oneof_iter oit; 405 size_t off = 0; 406 407 layout->fields = ALLOC_N(MessageField, nfields); 408 409 for (upb_msg_field_begin(&it, msgdef); 410 !upb_msg_field_done(&it); 411 upb_msg_field_next(&it)) { 412 const upb_fielddef* field = upb_msg_iter_field(&it); 413 size_t field_size; 414 415 if (upb_fielddef_containingoneof(field)) { 416 // Oneofs are handled separately below. 417 continue; 418 } 419 420 // Allocate |field_size| bytes for this field in the layout. 421 field_size = 0; 422 if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) { 423 field_size = sizeof(VALUE); 424 } else { 425 field_size = native_slot_size(upb_fielddef_type(field)); 426 } 427 // Align current offset up to |size| granularity. 428 off = align_up_to(off, field_size); 429 layout->fields[upb_fielddef_index(field)].offset = off; 430 layout->fields[upb_fielddef_index(field)].case_offset = 431 MESSAGE_FIELD_NO_CASE; 432 off += field_size; 433 } 434 435 // Handle oneofs now -- we iterate over oneofs specifically and allocate only 436 // one slot per oneof. 437 // 438 // We assign all value slots first, then pack the 'case' fields at the end, 439 // since in the common case (modern 64-bit platform) these are 8 bytes and 4 440 // bytes respectively and we want to avoid alignment overhead. 441 // 442 // Note that we reserve 4 bytes (a uint32) per 'case' slot because the value 443 // space for oneof cases is conceptually as wide as field tag numbers. In 444 // practice, it's unlikely that a oneof would have more than e.g. 256 or 64K 445 // members (8 or 16 bits respectively), so conceivably we could assign 446 // consecutive case numbers and then pick a smaller oneof case slot size, but 447 // the complexity to implement this indirection is probably not worthwhile. 448 for (upb_msg_oneof_begin(&oit, msgdef); 449 !upb_msg_oneof_done(&oit); 450 upb_msg_oneof_next(&oit)) { 451 const upb_oneofdef* oneof = upb_msg_iter_oneof(&oit); 452 upb_oneof_iter fit; 453 454 // Always allocate NATIVE_SLOT_MAX_SIZE bytes, but share the slot between 455 // all fields. 456 size_t field_size = NATIVE_SLOT_MAX_SIZE; 457 // Align the offset. 458 off = align_up_to(off, field_size); 459 // Assign all fields in the oneof this same offset. 460 for (upb_oneof_begin(&fit, oneof); 461 !upb_oneof_done(&fit); 462 upb_oneof_next(&fit)) { 463 const upb_fielddef* field = upb_oneof_iter_field(&fit); 464 layout->fields[upb_fielddef_index(field)].offset = off; 465 } 466 off += field_size; 467 } 468 469 // Now the case fields. 470 for (upb_msg_oneof_begin(&oit, msgdef); 471 !upb_msg_oneof_done(&oit); 472 upb_msg_oneof_next(&oit)) { 473 const upb_oneofdef* oneof = upb_msg_iter_oneof(&oit); 474 upb_oneof_iter fit; 475 476 size_t field_size = sizeof(uint32_t); 477 // Align the offset. 478 off = (off + field_size - 1) & ~(field_size - 1); 479 // Assign all fields in the oneof this same offset. 480 for (upb_oneof_begin(&fit, oneof); 481 !upb_oneof_done(&fit); 482 upb_oneof_next(&fit)) { 483 const upb_fielddef* field = upb_oneof_iter_field(&fit); 484 layout->fields[upb_fielddef_index(field)].case_offset = off; 485 } 486 off += field_size; 487 } 488 489 layout->size = off; 490 491 layout->msgdef = msgdef; 492 upb_msgdef_ref(layout->msgdef, &layout->msgdef); 493 494 return layout; 495 } 496 497 void free_layout(MessageLayout* layout) { 498 xfree(layout->fields); 499 upb_msgdef_unref(layout->msgdef, &layout->msgdef); 500 xfree(layout); 501 } 502 503 VALUE field_type_class(const upb_fielddef* field) { 504 VALUE type_class = Qnil; 505 if (upb_fielddef_type(field) == UPB_TYPE_MESSAGE) { 506 VALUE submsgdesc = 507 get_def_obj(upb_fielddef_subdef(field)); 508 type_class = Descriptor_msgclass(submsgdesc); 509 } else if (upb_fielddef_type(field) == UPB_TYPE_ENUM) { 510 VALUE subenumdesc = 511 get_def_obj(upb_fielddef_subdef(field)); 512 type_class = EnumDescriptor_enummodule(subenumdesc); 513 } 514 return type_class; 515 } 516 517 static void* slot_memory(MessageLayout* layout, 518 const void* storage, 519 const upb_fielddef* field) { 520 return ((uint8_t *)storage) + 521 layout->fields[upb_fielddef_index(field)].offset; 522 } 523 524 static uint32_t* slot_oneof_case(MessageLayout* layout, 525 const void* storage, 526 const upb_fielddef* field) { 527 return (uint32_t *)(((uint8_t *)storage) + 528 layout->fields[upb_fielddef_index(field)].case_offset); 529 } 530 531 532 VALUE layout_get(MessageLayout* layout, 533 const void* storage, 534 const upb_fielddef* field) { 535 void* memory = slot_memory(layout, storage, field); 536 uint32_t* oneof_case = slot_oneof_case(layout, storage, field); 537 538 if (upb_fielddef_containingoneof(field)) { 539 if (*oneof_case != upb_fielddef_number(field)) { 540 return Qnil; 541 } 542 return native_slot_get(upb_fielddef_type(field), 543 field_type_class(field), 544 memory); 545 } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) { 546 return *((VALUE *)memory); 547 } else { 548 return native_slot_get(upb_fielddef_type(field), 549 field_type_class(field), 550 memory); 551 } 552 } 553 554 static void check_repeated_field_type(VALUE val, const upb_fielddef* field) { 555 RepeatedField* self; 556 assert(upb_fielddef_label(field) == UPB_LABEL_REPEATED); 557 558 if (!RB_TYPE_P(val, T_DATA) || !RTYPEDDATA_P(val) || 559 RTYPEDDATA_TYPE(val) != &RepeatedField_type) { 560 rb_raise(rb_eTypeError, "Expected repeated field array"); 561 } 562 563 self = ruby_to_RepeatedField(val); 564 if (self->field_type != upb_fielddef_type(field)) { 565 rb_raise(rb_eTypeError, "Repeated field array has wrong element type"); 566 } 567 568 if (self->field_type == UPB_TYPE_MESSAGE || 569 self->field_type == UPB_TYPE_ENUM) { 570 if (self->field_type_class != 571 get_def_obj(upb_fielddef_subdef(field))) { 572 rb_raise(rb_eTypeError, 573 "Repeated field array has wrong message/enum class"); 574 } 575 } 576 } 577 578 static void check_map_field_type(VALUE val, const upb_fielddef* field) { 579 const upb_fielddef* key_field = map_field_key(field); 580 const upb_fielddef* value_field = map_field_value(field); 581 Map* self; 582 583 if (!RB_TYPE_P(val, T_DATA) || !RTYPEDDATA_P(val) || 584 RTYPEDDATA_TYPE(val) != &Map_type) { 585 rb_raise(rb_eTypeError, "Expected Map instance"); 586 } 587 588 self = ruby_to_Map(val); 589 if (self->key_type != upb_fielddef_type(key_field)) { 590 rb_raise(rb_eTypeError, "Map key type does not match field's key type"); 591 } 592 if (self->value_type != upb_fielddef_type(value_field)) { 593 rb_raise(rb_eTypeError, "Map value type does not match field's value type"); 594 } 595 if (upb_fielddef_type(value_field) == UPB_TYPE_MESSAGE || 596 upb_fielddef_type(value_field) == UPB_TYPE_ENUM) { 597 if (self->value_type_class != 598 get_def_obj(upb_fielddef_subdef(value_field))) { 599 rb_raise(rb_eTypeError, 600 "Map value type has wrong message/enum class"); 601 } 602 } 603 } 604 605 606 void layout_set(MessageLayout* layout, 607 void* storage, 608 const upb_fielddef* field, 609 VALUE val) { 610 void* memory = slot_memory(layout, storage, field); 611 uint32_t* oneof_case = slot_oneof_case(layout, storage, field); 612 613 if (upb_fielddef_containingoneof(field)) { 614 if (val == Qnil) { 615 // Assigning nil to a oneof field clears the oneof completely. 616 *oneof_case = ONEOF_CASE_NONE; 617 memset(memory, 0, NATIVE_SLOT_MAX_SIZE); 618 } else { 619 // The transition between field types for a single oneof (union) slot is 620 // somewhat complex because we need to ensure that a GC triggered at any 621 // point by a call into the Ruby VM sees a valid state for this field and 622 // does not either go off into the weeds (following what it thinks is a 623 // VALUE but is actually a different field type) or miss an object (seeing 624 // what it thinks is a primitive field but is actually a VALUE for the new 625 // field type). 626 // 627 // In order for the transition to be safe, the oneof case slot must be in 628 // sync with the value slot whenever the Ruby VM has been called. Thus, we 629 // use native_slot_set_value_and_case(), which ensures that both the value 630 // and case number are altered atomically (w.r.t. the Ruby VM). 631 native_slot_set_value_and_case( 632 upb_fielddef_type(field), field_type_class(field), 633 memory, val, 634 oneof_case, upb_fielddef_number(field)); 635 } 636 } else if (is_map_field(field)) { 637 check_map_field_type(val, field); 638 DEREF(memory, VALUE) = val; 639 } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) { 640 check_repeated_field_type(val, field); 641 DEREF(memory, VALUE) = val; 642 } else { 643 native_slot_set(upb_fielddef_type(field), field_type_class(field), 644 memory, val); 645 } 646 } 647 648 void layout_init(MessageLayout* layout, 649 void* storage) { 650 upb_msg_field_iter it; 651 for (upb_msg_field_begin(&it, layout->msgdef); 652 !upb_msg_field_done(&it); 653 upb_msg_field_next(&it)) { 654 const upb_fielddef* field = upb_msg_iter_field(&it); 655 void* memory = slot_memory(layout, storage, field); 656 uint32_t* oneof_case = slot_oneof_case(layout, storage, field); 657 658 if (upb_fielddef_containingoneof(field)) { 659 memset(memory, 0, NATIVE_SLOT_MAX_SIZE); 660 *oneof_case = ONEOF_CASE_NONE; 661 } else if (is_map_field(field)) { 662 VALUE map = Qnil; 663 664 const upb_fielddef* key_field = map_field_key(field); 665 const upb_fielddef* value_field = map_field_value(field); 666 VALUE type_class = field_type_class(value_field); 667 668 if (type_class != Qnil) { 669 VALUE args[3] = { 670 fieldtype_to_ruby(upb_fielddef_type(key_field)), 671 fieldtype_to_ruby(upb_fielddef_type(value_field)), 672 type_class, 673 }; 674 map = rb_class_new_instance(3, args, cMap); 675 } else { 676 VALUE args[2] = { 677 fieldtype_to_ruby(upb_fielddef_type(key_field)), 678 fieldtype_to_ruby(upb_fielddef_type(value_field)), 679 }; 680 map = rb_class_new_instance(2, args, cMap); 681 } 682 683 DEREF(memory, VALUE) = map; 684 } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) { 685 VALUE ary = Qnil; 686 687 VALUE type_class = field_type_class(field); 688 689 if (type_class != Qnil) { 690 VALUE args[2] = { 691 fieldtype_to_ruby(upb_fielddef_type(field)), 692 type_class, 693 }; 694 ary = rb_class_new_instance(2, args, cRepeatedField); 695 } else { 696 VALUE args[1] = { fieldtype_to_ruby(upb_fielddef_type(field)) }; 697 ary = rb_class_new_instance(1, args, cRepeatedField); 698 } 699 700 DEREF(memory, VALUE) = ary; 701 } else { 702 native_slot_init(upb_fielddef_type(field), memory); 703 } 704 } 705 } 706 707 void layout_mark(MessageLayout* layout, void* storage) { 708 upb_msg_field_iter it; 709 for (upb_msg_field_begin(&it, layout->msgdef); 710 !upb_msg_field_done(&it); 711 upb_msg_field_next(&it)) { 712 const upb_fielddef* field = upb_msg_iter_field(&it); 713 void* memory = slot_memory(layout, storage, field); 714 uint32_t* oneof_case = slot_oneof_case(layout, storage, field); 715 716 if (upb_fielddef_containingoneof(field)) { 717 if (*oneof_case == upb_fielddef_number(field)) { 718 native_slot_mark(upb_fielddef_type(field), memory); 719 } 720 } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) { 721 rb_gc_mark(DEREF(memory, VALUE)); 722 } else { 723 native_slot_mark(upb_fielddef_type(field), memory); 724 } 725 } 726 } 727 728 void layout_dup(MessageLayout* layout, void* to, void* from) { 729 upb_msg_field_iter it; 730 for (upb_msg_field_begin(&it, layout->msgdef); 731 !upb_msg_field_done(&it); 732 upb_msg_field_next(&it)) { 733 const upb_fielddef* field = upb_msg_iter_field(&it); 734 735 void* to_memory = slot_memory(layout, to, field); 736 uint32_t* to_oneof_case = slot_oneof_case(layout, to, field); 737 void* from_memory = slot_memory(layout, from, field); 738 uint32_t* from_oneof_case = slot_oneof_case(layout, from, field); 739 740 if (upb_fielddef_containingoneof(field)) { 741 if (*from_oneof_case == upb_fielddef_number(field)) { 742 *to_oneof_case = *from_oneof_case; 743 native_slot_dup(upb_fielddef_type(field), to_memory, from_memory); 744 } 745 } else if (is_map_field(field)) { 746 DEREF(to_memory, VALUE) = Map_dup(DEREF(from_memory, VALUE)); 747 } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) { 748 DEREF(to_memory, VALUE) = RepeatedField_dup(DEREF(from_memory, VALUE)); 749 } else { 750 native_slot_dup(upb_fielddef_type(field), to_memory, from_memory); 751 } 752 } 753 } 754 755 void layout_deep_copy(MessageLayout* layout, void* to, void* from) { 756 upb_msg_field_iter it; 757 for (upb_msg_field_begin(&it, layout->msgdef); 758 !upb_msg_field_done(&it); 759 upb_msg_field_next(&it)) { 760 const upb_fielddef* field = upb_msg_iter_field(&it); 761 762 void* to_memory = slot_memory(layout, to, field); 763 uint32_t* to_oneof_case = slot_oneof_case(layout, to, field); 764 void* from_memory = slot_memory(layout, from, field); 765 uint32_t* from_oneof_case = slot_oneof_case(layout, from, field); 766 767 if (upb_fielddef_containingoneof(field)) { 768 if (*from_oneof_case == upb_fielddef_number(field)) { 769 *to_oneof_case = *from_oneof_case; 770 native_slot_deep_copy(upb_fielddef_type(field), to_memory, from_memory); 771 } 772 } else if (is_map_field(field)) { 773 DEREF(to_memory, VALUE) = 774 Map_deep_copy(DEREF(from_memory, VALUE)); 775 } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) { 776 DEREF(to_memory, VALUE) = 777 RepeatedField_deep_copy(DEREF(from_memory, VALUE)); 778 } else { 779 native_slot_deep_copy(upb_fielddef_type(field), to_memory, from_memory); 780 } 781 } 782 } 783 784 VALUE layout_eq(MessageLayout* layout, void* msg1, void* msg2) { 785 upb_msg_field_iter it; 786 for (upb_msg_field_begin(&it, layout->msgdef); 787 !upb_msg_field_done(&it); 788 upb_msg_field_next(&it)) { 789 const upb_fielddef* field = upb_msg_iter_field(&it); 790 791 void* msg1_memory = slot_memory(layout, msg1, field); 792 uint32_t* msg1_oneof_case = slot_oneof_case(layout, msg1, field); 793 void* msg2_memory = slot_memory(layout, msg2, field); 794 uint32_t* msg2_oneof_case = slot_oneof_case(layout, msg2, field); 795 796 if (upb_fielddef_containingoneof(field)) { 797 if (*msg1_oneof_case != *msg2_oneof_case || 798 (*msg1_oneof_case == upb_fielddef_number(field) && 799 !native_slot_eq(upb_fielddef_type(field), 800 msg1_memory, 801 msg2_memory))) { 802 return Qfalse; 803 } 804 } else if (is_map_field(field)) { 805 if (!Map_eq(DEREF(msg1_memory, VALUE), 806 DEREF(msg2_memory, VALUE))) { 807 return Qfalse; 808 } 809 } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) { 810 if (!RepeatedField_eq(DEREF(msg1_memory, VALUE), 811 DEREF(msg2_memory, VALUE))) { 812 return Qfalse; 813 } 814 } else { 815 if (!native_slot_eq(upb_fielddef_type(field), 816 msg1_memory, msg2_memory)) { 817 return Qfalse; 818 } 819 } 820 } 821 return Qtrue; 822 } 823 824 VALUE layout_hash(MessageLayout* layout, void* storage) { 825 upb_msg_field_iter it; 826 st_index_t h = rb_hash_start(0); 827 VALUE hash_sym = rb_intern("hash"); 828 for (upb_msg_field_begin(&it, layout->msgdef); 829 !upb_msg_field_done(&it); 830 upb_msg_field_next(&it)) { 831 const upb_fielddef* field = upb_msg_iter_field(&it); 832 VALUE field_val = layout_get(layout, storage, field); 833 h = rb_hash_uint(h, NUM2LONG(rb_funcall(field_val, hash_sym, 0))); 834 } 835 h = rb_hash_end(h); 836 837 return INT2FIX(h); 838 } 839 840 VALUE layout_inspect(MessageLayout* layout, void* storage) { 841 VALUE str = rb_str_new2(""); 842 843 upb_msg_field_iter it; 844 bool first = true; 845 for (upb_msg_field_begin(&it, layout->msgdef); 846 !upb_msg_field_done(&it); 847 upb_msg_field_next(&it)) { 848 const upb_fielddef* field = upb_msg_iter_field(&it); 849 VALUE field_val = layout_get(layout, storage, field); 850 851 if (!first) { 852 str = rb_str_cat2(str, ", "); 853 } else { 854 first = false; 855 } 856 str = rb_str_cat2(str, upb_fielddef_name(field)); 857 str = rb_str_cat2(str, ": "); 858 859 str = rb_str_append(str, rb_funcall(field_val, rb_intern("inspect"), 0)); 860 } 861 862 return str; 863 } 864