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 CHARPTR_AT(msg, ofs) ((char*)msg + ofs) 42 #define DEREF_OFFSET(msg, ofs, type) *(type*)CHARPTR_AT(msg, ofs) 43 #define DEREF(memory, type) *(type*)(memory) 44 native_slot_size(upb_fieldtype_t type)45 size_t native_slot_size(upb_fieldtype_t type) { 46 switch (type) { 47 case UPB_TYPE_FLOAT: return 4; 48 case UPB_TYPE_DOUBLE: return 8; 49 case UPB_TYPE_BOOL: return 1; 50 case UPB_TYPE_STRING: return sizeof(VALUE); 51 case UPB_TYPE_BYTES: return sizeof(VALUE); 52 case UPB_TYPE_MESSAGE: return sizeof(VALUE); 53 case UPB_TYPE_ENUM: return 4; 54 case UPB_TYPE_INT32: return 4; 55 case UPB_TYPE_INT64: return 8; 56 case UPB_TYPE_UINT32: return 4; 57 case UPB_TYPE_UINT64: return 8; 58 default: return 0; 59 } 60 } 61 is_ruby_num(VALUE value)62 static bool is_ruby_num(VALUE value) { 63 return (TYPE(value) == T_FLOAT || 64 TYPE(value) == T_FIXNUM || 65 TYPE(value) == T_BIGNUM); 66 } 67 native_slot_check_int_range_precision(const char * name,upb_fieldtype_t type,VALUE val)68 void native_slot_check_int_range_precision(const char* name, upb_fieldtype_t type, VALUE val) { 69 if (!is_ruby_num(val)) { 70 rb_raise(cTypeError, "Expected number type for integral field '%s' (given %s).", 71 name, rb_class2name(CLASS_OF(val))); 72 } 73 74 // NUM2{INT,UINT,LL,ULL} macros do the appropriate range checks on upper 75 // bound; we just need to do precision checks (i.e., disallow rounding) and 76 // check for < 0 on unsigned types. 77 if (TYPE(val) == T_FLOAT) { 78 double dbl_val = NUM2DBL(val); 79 if (floor(dbl_val) != dbl_val) { 80 rb_raise(rb_eRangeError, 81 "Non-integral floating point value assigned to integer field '%s' (given %s).", 82 name, rb_class2name(CLASS_OF(val))); 83 } 84 } 85 if (type == UPB_TYPE_UINT32 || type == UPB_TYPE_UINT64) { 86 if (NUM2DBL(val) < 0) { 87 rb_raise(rb_eRangeError, 88 "Assigning negative value to unsigned integer field '%s' (given %s).", 89 name, rb_class2name(CLASS_OF(val))); 90 } 91 } 92 } 93 native_slot_encode_and_freeze_string(upb_fieldtype_t type,VALUE value)94 VALUE native_slot_encode_and_freeze_string(upb_fieldtype_t type, VALUE value) { 95 rb_encoding* desired_encoding = (type == UPB_TYPE_STRING) ? 96 kRubyStringUtf8Encoding : kRubyString8bitEncoding; 97 VALUE desired_encoding_value = rb_enc_from_encoding(desired_encoding); 98 99 if (rb_obj_encoding(value) != desired_encoding_value || !OBJ_FROZEN(value)) { 100 // Note: this will not duplicate underlying string data unless necessary. 101 value = rb_str_encode(value, desired_encoding_value, 0, Qnil); 102 103 if (type == UPB_TYPE_STRING && 104 rb_enc_str_coderange(value) == ENC_CODERANGE_BROKEN) { 105 rb_raise(rb_eEncodingError, "String is invalid UTF-8"); 106 } 107 108 // Ensure the data remains valid. Since we called #encode a moment ago, 109 // this does not freeze the string the user assigned. 110 rb_obj_freeze(value); 111 } 112 113 return value; 114 } 115 native_slot_set(const char * name,upb_fieldtype_t type,VALUE type_class,void * memory,VALUE value)116 void native_slot_set(const char* name, 117 upb_fieldtype_t type, VALUE type_class, 118 void* memory, VALUE value) { 119 native_slot_set_value_and_case(name, type, type_class, memory, value, NULL, 0); 120 } 121 native_slot_set_value_and_case(const char * name,upb_fieldtype_t type,VALUE type_class,void * memory,VALUE value,uint32_t * case_memory,uint32_t case_number)122 void native_slot_set_value_and_case(const char* name, 123 upb_fieldtype_t type, VALUE type_class, 124 void* memory, VALUE value, 125 uint32_t* case_memory, 126 uint32_t case_number) { 127 // Note that in order to atomically change the value in memory and the case 128 // value (w.r.t. Ruby VM calls), we must set the value at |memory| only after 129 // all Ruby VM calls are complete. The case is then set at the bottom of this 130 // function. 131 switch (type) { 132 case UPB_TYPE_FLOAT: 133 if (!is_ruby_num(value)) { 134 rb_raise(cTypeError, "Expected number type for float field '%s' (given %s).", 135 name, rb_class2name(CLASS_OF(value))); 136 } 137 DEREF(memory, float) = NUM2DBL(value); 138 break; 139 case UPB_TYPE_DOUBLE: 140 if (!is_ruby_num(value)) { 141 rb_raise(cTypeError, "Expected number type for double field '%s' (given %s).", 142 name, rb_class2name(CLASS_OF(value))); 143 } 144 DEREF(memory, double) = NUM2DBL(value); 145 break; 146 case UPB_TYPE_BOOL: { 147 int8_t val = -1; 148 if (value == Qtrue) { 149 val = 1; 150 } else if (value == Qfalse) { 151 val = 0; 152 } else { 153 rb_raise(cTypeError, "Invalid argument for boolean field '%s' (given %s).", 154 name, rb_class2name(CLASS_OF(value))); 155 } 156 DEREF(memory, int8_t) = val; 157 break; 158 } 159 case UPB_TYPE_STRING: 160 if (CLASS_OF(value) == rb_cSymbol) { 161 value = rb_funcall(value, rb_intern("to_s"), 0); 162 } else if (CLASS_OF(value) != rb_cString) { 163 rb_raise(cTypeError, "Invalid argument for string field '%s' (given %s).", 164 name, rb_class2name(CLASS_OF(value))); 165 } 166 167 DEREF(memory, VALUE) = native_slot_encode_and_freeze_string(type, value); 168 break; 169 170 case UPB_TYPE_BYTES: { 171 if (CLASS_OF(value) != rb_cString) { 172 rb_raise(cTypeError, "Invalid argument for bytes field '%s' (given %s).", 173 name, rb_class2name(CLASS_OF(value))); 174 } 175 176 DEREF(memory, VALUE) = native_slot_encode_and_freeze_string(type, value); 177 break; 178 } 179 case UPB_TYPE_MESSAGE: { 180 if (CLASS_OF(value) == CLASS_OF(Qnil)) { 181 value = Qnil; 182 } else if (CLASS_OF(value) != type_class) { 183 // check for possible implicit conversions 184 VALUE converted_value = Qnil; 185 const char* field_type_name = rb_class2name(type_class); 186 187 if (strcmp(field_type_name, "Google::Protobuf::Timestamp") == 0 && 188 rb_obj_is_kind_of(value, rb_cTime)) { 189 // Time -> Google::Protobuf::Timestamp 190 VALUE hash = rb_hash_new(); 191 rb_hash_aset(hash, rb_str_new2("seconds"), 192 rb_funcall(value, rb_intern("to_i"), 0)); 193 rb_hash_aset(hash, rb_str_new2("nanos"), 194 rb_funcall(value, rb_intern("nsec"), 0)); 195 { 196 VALUE args[1] = {hash}; 197 converted_value = rb_class_new_instance(1, args, type_class); 198 } 199 } else if (strcmp(field_type_name, "Google::Protobuf::Duration") == 0 && 200 rb_obj_is_kind_of(value, rb_cNumeric)) { 201 // Numeric -> Google::Protobuf::Duration 202 VALUE hash = rb_hash_new(); 203 rb_hash_aset(hash, rb_str_new2("seconds"), 204 rb_funcall(value, rb_intern("to_i"), 0)); 205 { 206 VALUE n_value = 207 rb_funcall(value, rb_intern("remainder"), 1, INT2NUM(1)); 208 n_value = 209 rb_funcall(n_value, rb_intern("*"), 1, INT2NUM(1000000000)); 210 n_value = rb_funcall(n_value, rb_intern("round"), 0); 211 rb_hash_aset(hash, rb_str_new2("nanos"), n_value); 212 } 213 { 214 VALUE args[1] = { hash }; 215 converted_value = rb_class_new_instance(1, args, type_class); 216 } 217 } 218 219 // raise if no suitable conversaion could be found 220 if (converted_value == Qnil) { 221 rb_raise(cTypeError, 222 "Invalid type %s to assign to submessage field '%s'.", 223 rb_class2name(CLASS_OF(value)), name); 224 } else { 225 value = converted_value; 226 } 227 } 228 DEREF(memory, VALUE) = value; 229 break; 230 } 231 case UPB_TYPE_ENUM: { 232 int32_t int_val = 0; 233 if (TYPE(value) == T_STRING) { 234 value = rb_funcall(value, rb_intern("to_sym"), 0); 235 } else if (!is_ruby_num(value) && TYPE(value) != T_SYMBOL) { 236 rb_raise(cTypeError, 237 "Expected number or symbol type for enum field '%s'.", name); 238 } 239 if (TYPE(value) == T_SYMBOL) { 240 // Ensure that the given symbol exists in the enum module. 241 VALUE lookup = rb_funcall(type_class, rb_intern("resolve"), 1, value); 242 if (lookup == Qnil) { 243 rb_raise(rb_eRangeError, "Unknown symbol value for enum field '%s'.", name); 244 } else { 245 int_val = NUM2INT(lookup); 246 } 247 } else { 248 native_slot_check_int_range_precision(name, UPB_TYPE_INT32, value); 249 int_val = NUM2INT(value); 250 } 251 DEREF(memory, int32_t) = int_val; 252 break; 253 } 254 case UPB_TYPE_INT32: 255 case UPB_TYPE_INT64: 256 case UPB_TYPE_UINT32: 257 case UPB_TYPE_UINT64: 258 native_slot_check_int_range_precision(name, type, value); 259 switch (type) { 260 case UPB_TYPE_INT32: 261 DEREF(memory, int32_t) = NUM2INT(value); 262 break; 263 case UPB_TYPE_INT64: 264 DEREF(memory, int64_t) = NUM2LL(value); 265 break; 266 case UPB_TYPE_UINT32: 267 DEREF(memory, uint32_t) = NUM2UINT(value); 268 break; 269 case UPB_TYPE_UINT64: 270 DEREF(memory, uint64_t) = NUM2ULL(value); 271 break; 272 default: 273 break; 274 } 275 break; 276 default: 277 break; 278 } 279 280 if (case_memory != NULL) { 281 *case_memory = case_number; 282 } 283 } 284 native_slot_get(upb_fieldtype_t type,VALUE type_class,const void * memory)285 VALUE native_slot_get(upb_fieldtype_t type, 286 VALUE type_class, 287 const void* memory) { 288 switch (type) { 289 case UPB_TYPE_FLOAT: 290 return DBL2NUM(DEREF(memory, float)); 291 case UPB_TYPE_DOUBLE: 292 return DBL2NUM(DEREF(memory, double)); 293 case UPB_TYPE_BOOL: 294 return DEREF(memory, int8_t) ? Qtrue : Qfalse; 295 case UPB_TYPE_STRING: 296 case UPB_TYPE_BYTES: 297 return DEREF(memory, VALUE); 298 case UPB_TYPE_MESSAGE: { 299 VALUE val = DEREF(memory, VALUE); 300 301 // Lazily expand wrapper type if necessary. 302 int type = TYPE(val); 303 if (type != T_DATA && type != T_NIL) { 304 // This must be a wrapper type. 305 val = ruby_wrapper_type(type_class, val); 306 DEREF(memory, VALUE) = val; 307 } 308 309 return val; 310 } 311 case UPB_TYPE_ENUM: { 312 int32_t val = DEREF(memory, int32_t); 313 VALUE symbol = enum_lookup(type_class, INT2NUM(val)); 314 if (symbol == Qnil) { 315 return INT2NUM(val); 316 } else { 317 return symbol; 318 } 319 } 320 case UPB_TYPE_INT32: 321 return INT2NUM(DEREF(memory, int32_t)); 322 case UPB_TYPE_INT64: 323 return LL2NUM(DEREF(memory, int64_t)); 324 case UPB_TYPE_UINT32: 325 return UINT2NUM(DEREF(memory, uint32_t)); 326 case UPB_TYPE_UINT64: 327 return ULL2NUM(DEREF(memory, uint64_t)); 328 default: 329 return Qnil; 330 } 331 } 332 native_slot_init(upb_fieldtype_t type,void * memory)333 void native_slot_init(upb_fieldtype_t type, void* memory) { 334 switch (type) { 335 case UPB_TYPE_FLOAT: 336 DEREF(memory, float) = 0.0; 337 break; 338 case UPB_TYPE_DOUBLE: 339 DEREF(memory, double) = 0.0; 340 break; 341 case UPB_TYPE_BOOL: 342 DEREF(memory, int8_t) = 0; 343 break; 344 case UPB_TYPE_STRING: 345 case UPB_TYPE_BYTES: 346 DEREF(memory, VALUE) = rb_str_new2(""); 347 rb_enc_associate(DEREF(memory, VALUE), (type == UPB_TYPE_BYTES) ? 348 kRubyString8bitEncoding : kRubyStringUtf8Encoding); 349 break; 350 case UPB_TYPE_MESSAGE: 351 DEREF(memory, VALUE) = Qnil; 352 break; 353 case UPB_TYPE_ENUM: 354 case UPB_TYPE_INT32: 355 DEREF(memory, int32_t) = 0; 356 break; 357 case UPB_TYPE_INT64: 358 DEREF(memory, int64_t) = 0; 359 break; 360 case UPB_TYPE_UINT32: 361 DEREF(memory, uint32_t) = 0; 362 break; 363 case UPB_TYPE_UINT64: 364 DEREF(memory, uint64_t) = 0; 365 break; 366 default: 367 break; 368 } 369 } 370 native_slot_mark(upb_fieldtype_t type,void * memory)371 void native_slot_mark(upb_fieldtype_t type, void* memory) { 372 switch (type) { 373 case UPB_TYPE_STRING: 374 case UPB_TYPE_BYTES: 375 case UPB_TYPE_MESSAGE: 376 rb_gc_mark(DEREF(memory, VALUE)); 377 break; 378 default: 379 break; 380 } 381 } 382 native_slot_dup(upb_fieldtype_t type,void * to,void * from)383 void native_slot_dup(upb_fieldtype_t type, void* to, void* from) { 384 memcpy(to, from, native_slot_size(type)); 385 } 386 native_slot_deep_copy(upb_fieldtype_t type,VALUE type_class,void * to,void * from)387 void native_slot_deep_copy(upb_fieldtype_t type, VALUE type_class, void* to, 388 void* from) { 389 switch (type) { 390 case UPB_TYPE_STRING: 391 case UPB_TYPE_BYTES: { 392 VALUE from_val = DEREF(from, VALUE); 393 DEREF(to, VALUE) = (from_val != Qnil) ? 394 rb_funcall(from_val, rb_intern("dup"), 0) : Qnil; 395 break; 396 } 397 case UPB_TYPE_MESSAGE: { 398 VALUE from_val = native_slot_get(type, type_class, from); 399 DEREF(to, VALUE) = (from_val != Qnil) ? 400 Message_deep_copy(from_val) : Qnil; 401 break; 402 } 403 default: 404 memcpy(to, from, native_slot_size(type)); 405 } 406 } 407 native_slot_eq(upb_fieldtype_t type,VALUE type_class,void * mem1,void * mem2)408 bool native_slot_eq(upb_fieldtype_t type, VALUE type_class, void* mem1, 409 void* mem2) { 410 switch (type) { 411 case UPB_TYPE_STRING: 412 case UPB_TYPE_BYTES: 413 case UPB_TYPE_MESSAGE: { 414 VALUE val1 = native_slot_get(type, type_class, mem1); 415 VALUE val2 = native_slot_get(type, type_class, mem2); 416 VALUE ret = rb_funcall(val1, rb_intern("=="), 1, val2); 417 return ret == Qtrue; 418 } 419 default: 420 return !memcmp(mem1, mem2, native_slot_size(type)); 421 } 422 } 423 424 // ----------------------------------------------------------------------------- 425 // Map field utilities. 426 // ----------------------------------------------------------------------------- 427 tryget_map_entry_msgdef(const upb_fielddef * field)428 const upb_msgdef* tryget_map_entry_msgdef(const upb_fielddef* field) { 429 const upb_msgdef* subdef; 430 if (upb_fielddef_label(field) != UPB_LABEL_REPEATED || 431 upb_fielddef_type(field) != UPB_TYPE_MESSAGE) { 432 return NULL; 433 } 434 subdef = upb_fielddef_msgsubdef(field); 435 return upb_msgdef_mapentry(subdef) ? subdef : NULL; 436 } 437 map_entry_msgdef(const upb_fielddef * field)438 const upb_msgdef *map_entry_msgdef(const upb_fielddef* field) { 439 const upb_msgdef* subdef = tryget_map_entry_msgdef(field); 440 assert(subdef); 441 return subdef; 442 } 443 is_map_field(const upb_fielddef * field)444 bool is_map_field(const upb_fielddef *field) { 445 const upb_msgdef* subdef = tryget_map_entry_msgdef(field); 446 if (subdef == NULL) return false; 447 448 // Map fields are a proto3 feature. 449 // If we're using proto2 syntax we need to fallback to the repeated field. 450 return upb_msgdef_syntax(subdef) == UPB_SYNTAX_PROTO3; 451 } 452 map_field_key(const upb_fielddef * field)453 const upb_fielddef* map_field_key(const upb_fielddef* field) { 454 const upb_msgdef* subdef = map_entry_msgdef(field); 455 return map_entry_key(subdef); 456 } 457 map_field_value(const upb_fielddef * field)458 const upb_fielddef* map_field_value(const upb_fielddef* field) { 459 const upb_msgdef* subdef = map_entry_msgdef(field); 460 return map_entry_value(subdef); 461 } 462 map_entry_key(const upb_msgdef * msgdef)463 const upb_fielddef* map_entry_key(const upb_msgdef* msgdef) { 464 const upb_fielddef* key_field = upb_msgdef_itof(msgdef, MAP_KEY_FIELD); 465 assert(key_field != NULL); 466 return key_field; 467 } 468 map_entry_value(const upb_msgdef * msgdef)469 const upb_fielddef* map_entry_value(const upb_msgdef* msgdef) { 470 const upb_fielddef* value_field = upb_msgdef_itof(msgdef, MAP_VALUE_FIELD); 471 assert(value_field != NULL); 472 return value_field; 473 } 474 475 // ----------------------------------------------------------------------------- 476 // Memory layout management. 477 // ----------------------------------------------------------------------------- 478 field_contains_hasbit(MessageLayout * layout,const upb_fielddef * field)479 bool field_contains_hasbit(MessageLayout* layout, 480 const upb_fielddef* field) { 481 return layout->fields[upb_fielddef_index(field)].hasbit != 482 MESSAGE_FIELD_NO_HASBIT; 483 } 484 align_up_to(size_t offset,size_t granularity)485 static size_t align_up_to(size_t offset, size_t granularity) { 486 // Granularity must be a power of two. 487 return (offset + granularity - 1) & ~(granularity - 1); 488 } 489 is_value_field(const upb_fielddef * f)490 bool is_value_field(const upb_fielddef* f) { 491 return upb_fielddef_isseq(f) || upb_fielddef_issubmsg(f) || 492 upb_fielddef_isstring(f); 493 } 494 create_layout(Descriptor * desc)495 void create_layout(Descriptor* desc) { 496 const upb_msgdef *msgdef = desc->msgdef; 497 MessageLayout* layout = ALLOC(MessageLayout); 498 int nfields = upb_msgdef_numfields(msgdef); 499 int noneofs = upb_msgdef_numrealoneofs(msgdef); 500 upb_msg_field_iter it; 501 upb_msg_oneof_iter oit; 502 size_t off = 0; 503 size_t hasbit = 0; 504 int i; 505 506 (void)i; 507 508 layout->empty_template = NULL; 509 layout->desc = desc; 510 desc->layout = layout; 511 512 layout->fields = ALLOC_N(MessageField, nfields); 513 layout->oneofs = NULL; 514 515 if (noneofs > 0) { 516 layout->oneofs = ALLOC_N(MessageOneof, noneofs); 517 } 518 519 #ifndef NDEBUG 520 for (i = 0; i < nfields; i++) { 521 layout->fields[i].offset = -1; 522 } 523 524 for (i = 0; i < noneofs; i++) { 525 layout->oneofs[i].offset = -1; 526 } 527 #endif 528 529 for (upb_msg_field_begin(&it, msgdef); 530 !upb_msg_field_done(&it); 531 upb_msg_field_next(&it)) { 532 const upb_fielddef* field = upb_msg_iter_field(&it); 533 if (upb_fielddef_haspresence(field) && 534 !upb_fielddef_realcontainingoneof(field)) { 535 layout->fields[upb_fielddef_index(field)].hasbit = hasbit++; 536 } else { 537 layout->fields[upb_fielddef_index(field)].hasbit = 538 MESSAGE_FIELD_NO_HASBIT; 539 } 540 } 541 542 if (hasbit != 0) { 543 off += (hasbit + 8 - 1) / 8; 544 } 545 546 off = align_up_to(off, sizeof(VALUE)); 547 layout->value_offset = off; 548 layout->repeated_count = 0; 549 layout->map_count = 0; 550 layout->value_count = 0; 551 552 // Place all VALUE fields for repeated fields. 553 for (upb_msg_field_begin(&it, msgdef); 554 !upb_msg_field_done(&it); 555 upb_msg_field_next(&it)) { 556 const upb_fielddef* field = upb_msg_iter_field(&it); 557 if (upb_fielddef_realcontainingoneof(field) || !upb_fielddef_isseq(field) || 558 upb_fielddef_ismap(field)) { 559 continue; 560 } 561 562 layout->fields[upb_fielddef_index(field)].offset = off; 563 off += sizeof(VALUE); 564 layout->repeated_count++; 565 } 566 567 // Place all VALUE fields for map fields. 568 for (upb_msg_field_begin(&it, msgdef); 569 !upb_msg_field_done(&it); 570 upb_msg_field_next(&it)) { 571 const upb_fielddef* field = upb_msg_iter_field(&it); 572 if (upb_fielddef_realcontainingoneof(field) || !upb_fielddef_isseq(field) || 573 !upb_fielddef_ismap(field)) { 574 continue; 575 } 576 577 layout->fields[upb_fielddef_index(field)].offset = off; 578 off += sizeof(VALUE); 579 layout->map_count++; 580 } 581 582 layout->value_count = layout->repeated_count + layout->map_count; 583 584 // Next place all other (non-oneof) VALUE fields. 585 for (upb_msg_field_begin(&it, msgdef); 586 !upb_msg_field_done(&it); 587 upb_msg_field_next(&it)) { 588 const upb_fielddef* field = upb_msg_iter_field(&it); 589 if (upb_fielddef_realcontainingoneof(field) || !is_value_field(field) || 590 upb_fielddef_isseq(field)) { 591 continue; 592 } 593 594 layout->fields[upb_fielddef_index(field)].offset = off; 595 off += sizeof(VALUE); 596 layout->value_count++; 597 } 598 599 // Now place all other (non-oneof) fields. 600 for (upb_msg_field_begin(&it, msgdef); 601 !upb_msg_field_done(&it); 602 upb_msg_field_next(&it)) { 603 const upb_fielddef* field = upb_msg_iter_field(&it); 604 size_t field_size; 605 606 if (upb_fielddef_realcontainingoneof(field) || is_value_field(field)) { 607 continue; 608 } 609 610 // Allocate |field_size| bytes for this field in the layout. 611 field_size = native_slot_size(upb_fielddef_type(field)); 612 613 // Align current offset up to |size| granularity. 614 off = align_up_to(off, field_size); 615 layout->fields[upb_fielddef_index(field)].offset = off; 616 off += field_size; 617 } 618 619 // Handle oneofs now -- we iterate over oneofs specifically and allocate only 620 // one slot per oneof. 621 // 622 // We assign all value slots first, then pack the 'case' fields at the end, 623 // since in the common case (modern 64-bit platform) these are 8 bytes and 4 624 // bytes respectively and we want to avoid alignment overhead. 625 // 626 // Note that we reserve 4 bytes (a uint32) per 'case' slot because the value 627 // space for oneof cases is conceptually as wide as field tag numbers. In 628 // practice, it's unlikely that a oneof would have more than e.g. 256 or 64K 629 // members (8 or 16 bits respectively), so conceivably we could assign 630 // consecutive case numbers and then pick a smaller oneof case slot size, but 631 // the complexity to implement this indirection is probably not worthwhile. 632 for (upb_msg_oneof_begin(&oit, msgdef); 633 !upb_msg_oneof_done(&oit); 634 upb_msg_oneof_next(&oit)) { 635 const upb_oneofdef* oneof = upb_msg_iter_oneof(&oit); 636 upb_oneof_iter fit; 637 638 // Always allocate NATIVE_SLOT_MAX_SIZE bytes, but share the slot between 639 // all fields. 640 size_t field_size = NATIVE_SLOT_MAX_SIZE; 641 642 if (upb_oneofdef_issynthetic(oneof)) continue; 643 assert(upb_oneofdef_index(oneof) < noneofs); 644 645 // Align the offset. 646 off = align_up_to(off, field_size); 647 // Assign all fields in the oneof this same offset. 648 for (upb_oneof_begin(&fit, oneof); 649 !upb_oneof_done(&fit); 650 upb_oneof_next(&fit)) { 651 const upb_fielddef* field = upb_oneof_iter_field(&fit); 652 layout->fields[upb_fielddef_index(field)].offset = off; 653 layout->oneofs[upb_oneofdef_index(oneof)].offset = off; 654 } 655 off += field_size; 656 } 657 658 // Now the case fields. 659 for (upb_msg_oneof_begin(&oit, msgdef); 660 !upb_msg_oneof_done(&oit); 661 upb_msg_oneof_next(&oit)) { 662 const upb_oneofdef* oneof = upb_msg_iter_oneof(&oit); 663 size_t field_size = sizeof(uint32_t); 664 if (upb_oneofdef_issynthetic(oneof)) continue; 665 assert(upb_oneofdef_index(oneof) < noneofs); 666 // Align the offset. 667 off = (off + field_size - 1) & ~(field_size - 1); 668 layout->oneofs[upb_oneofdef_index(oneof)].case_offset = off; 669 off += field_size; 670 } 671 672 layout->size = off; 673 layout->msgdef = msgdef; 674 675 #ifndef NDEBUG 676 for (i = 0; i < nfields; i++) { 677 assert(layout->fields[i].offset != -1); 678 } 679 680 for (i = 0; i < noneofs; i++) { 681 assert(layout->oneofs[i].offset != -1); 682 } 683 #endif 684 685 // Create the empty message template. 686 layout->empty_template = ALLOC_N(char, layout->size); 687 memset(layout->empty_template, 0, layout->size); 688 689 for (upb_msg_field_begin(&it, layout->msgdef); 690 !upb_msg_field_done(&it); 691 upb_msg_field_next(&it)) { 692 layout_clear(layout, layout->empty_template, upb_msg_iter_field(&it)); 693 } 694 } 695 free_layout(MessageLayout * layout)696 void free_layout(MessageLayout* layout) { 697 xfree(layout->empty_template); 698 xfree(layout->fields); 699 xfree(layout->oneofs); 700 xfree(layout); 701 } 702 field_type_class(const MessageLayout * layout,const upb_fielddef * field)703 VALUE field_type_class(const MessageLayout* layout, const upb_fielddef* field) { 704 VALUE type_class = Qnil; 705 if (upb_fielddef_type(field) == UPB_TYPE_MESSAGE) { 706 VALUE submsgdesc = get_msgdef_obj(layout->desc->descriptor_pool, 707 upb_fielddef_msgsubdef(field)); 708 type_class = Descriptor_msgclass(submsgdesc); 709 } else if (upb_fielddef_type(field) == UPB_TYPE_ENUM) { 710 VALUE subenumdesc = get_enumdef_obj(layout->desc->descriptor_pool, 711 upb_fielddef_enumsubdef(field)); 712 type_class = EnumDescriptor_enummodule(subenumdesc); 713 } 714 return type_class; 715 } 716 slot_memory(MessageLayout * layout,const void * storage,const upb_fielddef * field)717 static void* slot_memory(MessageLayout* layout, 718 const void* storage, 719 const upb_fielddef* field) { 720 return ((uint8_t *)storage) + 721 layout->fields[upb_fielddef_index(field)].offset; 722 } 723 slot_oneof_case(MessageLayout * layout,const void * storage,const upb_oneofdef * oneof)724 static uint32_t* slot_oneof_case(MessageLayout* layout, 725 const void* storage, 726 const upb_oneofdef* oneof) { 727 return (uint32_t*)(((uint8_t*)storage) + 728 layout->oneofs[upb_oneofdef_index(oneof)].case_offset); 729 } 730 slot_read_oneof_case(MessageLayout * layout,const void * storage,const upb_oneofdef * oneof)731 uint32_t slot_read_oneof_case(MessageLayout* layout, const void* storage, 732 const upb_oneofdef* oneof) { 733 uint32_t* ptr = slot_oneof_case(layout, storage, oneof); 734 return *ptr & ~ONEOF_CASE_MASK; 735 } 736 slot_set_hasbit(MessageLayout * layout,const void * storage,const upb_fielddef * field)737 static void slot_set_hasbit(MessageLayout* layout, 738 const void* storage, 739 const upb_fielddef* field) { 740 size_t hasbit = layout->fields[upb_fielddef_index(field)].hasbit; 741 assert(hasbit != MESSAGE_FIELD_NO_HASBIT); 742 743 ((uint8_t*)storage)[hasbit / 8] |= 1 << (hasbit % 8); 744 } 745 slot_clear_hasbit(MessageLayout * layout,const void * storage,const upb_fielddef * field)746 static void slot_clear_hasbit(MessageLayout* layout, 747 const void* storage, 748 const upb_fielddef* field) { 749 size_t hasbit = layout->fields[upb_fielddef_index(field)].hasbit; 750 assert(hasbit != MESSAGE_FIELD_NO_HASBIT); 751 ((uint8_t*)storage)[hasbit / 8] &= ~(1 << (hasbit % 8)); 752 } 753 slot_is_hasbit_set(MessageLayout * layout,const void * storage,const upb_fielddef * field)754 static bool slot_is_hasbit_set(MessageLayout* layout, 755 const void* storage, 756 const upb_fielddef* field) { 757 size_t hasbit = layout->fields[upb_fielddef_index(field)].hasbit; 758 assert(field_contains_hasbit(layout, field)); 759 return DEREF_OFFSET( 760 (uint8_t*)storage, hasbit / 8, char) & (1 << (hasbit % 8)); 761 } 762 layout_has(MessageLayout * layout,const void * storage,const upb_fielddef * field)763 VALUE layout_has(MessageLayout* layout, 764 const void* storage, 765 const upb_fielddef* field) { 766 const upb_oneofdef* oneof = upb_fielddef_realcontainingoneof(field); 767 assert(upb_fielddef_haspresence(field)); 768 if (oneof) { 769 uint32_t oneof_case = slot_read_oneof_case(layout, storage, oneof); 770 return oneof_case == upb_fielddef_number(field) ? Qtrue : Qfalse; 771 } else { 772 return slot_is_hasbit_set(layout, storage, field) ? Qtrue : Qfalse; 773 } 774 } 775 layout_clear(MessageLayout * layout,const void * storage,const upb_fielddef * field)776 void layout_clear(MessageLayout* layout, 777 const void* storage, 778 const upb_fielddef* field) { 779 void* memory = slot_memory(layout, storage, field); 780 const upb_oneofdef* oneof = upb_fielddef_realcontainingoneof(field); 781 782 if (field_contains_hasbit(layout, field)) { 783 slot_clear_hasbit(layout, storage, field); 784 } 785 786 if (oneof) { 787 uint32_t* oneof_case = slot_oneof_case(layout, storage, oneof); 788 memset(memory, 0, NATIVE_SLOT_MAX_SIZE); 789 *oneof_case = ONEOF_CASE_NONE; 790 } else if (is_map_field(field)) { 791 VALUE map = Qnil; 792 793 const upb_fielddef* key_field = map_field_key(field); 794 const upb_fielddef* value_field = map_field_value(field); 795 VALUE type_class = field_type_class(layout, value_field); 796 797 if (type_class != Qnil) { 798 VALUE args[3] = { 799 fieldtype_to_ruby(upb_fielddef_type(key_field)), 800 fieldtype_to_ruby(upb_fielddef_type(value_field)), 801 type_class, 802 }; 803 map = rb_class_new_instance(3, args, cMap); 804 } else { 805 VALUE args[2] = { 806 fieldtype_to_ruby(upb_fielddef_type(key_field)), 807 fieldtype_to_ruby(upb_fielddef_type(value_field)), 808 }; 809 map = rb_class_new_instance(2, args, cMap); 810 } 811 812 DEREF(memory, VALUE) = map; 813 } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) { 814 VALUE ary = Qnil; 815 816 VALUE type_class = field_type_class(layout, field); 817 818 if (type_class != Qnil) { 819 VALUE args[2] = { 820 fieldtype_to_ruby(upb_fielddef_type(field)), 821 type_class, 822 }; 823 ary = rb_class_new_instance(2, args, cRepeatedField); 824 } else { 825 VALUE args[1] = { fieldtype_to_ruby(upb_fielddef_type(field)) }; 826 ary = rb_class_new_instance(1, args, cRepeatedField); 827 } 828 829 DEREF(memory, VALUE) = ary; 830 } else { 831 native_slot_set(upb_fielddef_name(field), upb_fielddef_type(field), 832 field_type_class(layout, field), memory, 833 layout_get_default(field)); 834 } 835 } 836 layout_get_default(const upb_fielddef * field)837 VALUE layout_get_default(const upb_fielddef *field) { 838 switch (upb_fielddef_type(field)) { 839 case UPB_TYPE_FLOAT: return DBL2NUM(upb_fielddef_defaultfloat(field)); 840 case UPB_TYPE_DOUBLE: return DBL2NUM(upb_fielddef_defaultdouble(field)); 841 case UPB_TYPE_BOOL: 842 return upb_fielddef_defaultbool(field) ? Qtrue : Qfalse; 843 case UPB_TYPE_MESSAGE: return Qnil; 844 case UPB_TYPE_ENUM: { 845 const upb_enumdef *enumdef = upb_fielddef_enumsubdef(field); 846 int32_t num = upb_fielddef_defaultint32(field); 847 const char *label = upb_enumdef_iton(enumdef, num); 848 if (label) { 849 return ID2SYM(rb_intern(label)); 850 } else { 851 return INT2NUM(num); 852 } 853 } 854 case UPB_TYPE_INT32: return INT2NUM(upb_fielddef_defaultint32(field)); 855 case UPB_TYPE_INT64: return LL2NUM(upb_fielddef_defaultint64(field));; 856 case UPB_TYPE_UINT32: return UINT2NUM(upb_fielddef_defaultuint32(field)); 857 case UPB_TYPE_UINT64: return ULL2NUM(upb_fielddef_defaultuint64(field)); 858 case UPB_TYPE_STRING: 859 case UPB_TYPE_BYTES: { 860 size_t size; 861 const char *str = upb_fielddef_defaultstr(field, &size); 862 return get_frozen_string(str, size, 863 upb_fielddef_type(field) == UPB_TYPE_BYTES); 864 } 865 default: return Qnil; 866 } 867 } 868 layout_get(MessageLayout * layout,const void * storage,const upb_fielddef * field)869 VALUE layout_get(MessageLayout* layout, 870 const void* storage, 871 const upb_fielddef* field) { 872 void* memory = slot_memory(layout, storage, field); 873 const upb_oneofdef* oneof = upb_fielddef_realcontainingoneof(field); 874 bool field_set; 875 if (field_contains_hasbit(layout, field)) { 876 field_set = slot_is_hasbit_set(layout, storage, field); 877 } else { 878 field_set = true; 879 } 880 881 if (oneof) { 882 uint32_t oneof_case = slot_read_oneof_case(layout, storage, oneof); 883 if (oneof_case != upb_fielddef_number(field)) { 884 return layout_get_default(field); 885 } 886 return native_slot_get(upb_fielddef_type(field), 887 field_type_class(layout, field), memory); 888 } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) { 889 return *((VALUE *)memory); 890 } else if (!field_set) { 891 return layout_get_default(field); 892 } else { 893 return native_slot_get(upb_fielddef_type(field), 894 field_type_class(layout, field), memory); 895 } 896 } 897 check_repeated_field_type(const MessageLayout * layout,VALUE val,const upb_fielddef * field)898 static void check_repeated_field_type(const MessageLayout* layout, VALUE val, 899 const upb_fielddef* field) { 900 RepeatedField* self; 901 assert(upb_fielddef_label(field) == UPB_LABEL_REPEATED); 902 903 if (!RB_TYPE_P(val, T_DATA) || !RTYPEDDATA_P(val) || 904 RTYPEDDATA_TYPE(val) != &RepeatedField_type) { 905 rb_raise(cTypeError, "Expected repeated field array"); 906 } 907 908 self = ruby_to_RepeatedField(val); 909 if (self->field_type != upb_fielddef_type(field)) { 910 rb_raise(cTypeError, "Repeated field array has wrong element type"); 911 } 912 913 if (self->field_type_class != field_type_class(layout, field)) { 914 rb_raise(cTypeError, "Repeated field array has wrong message/enum class"); 915 } 916 } 917 check_map_field_type(const MessageLayout * layout,VALUE val,const upb_fielddef * field)918 static void check_map_field_type(const MessageLayout* layout, VALUE val, 919 const upb_fielddef* field) { 920 const upb_fielddef* key_field = map_field_key(field); 921 const upb_fielddef* value_field = map_field_value(field); 922 Map* self; 923 924 if (!RB_TYPE_P(val, T_DATA) || !RTYPEDDATA_P(val) || 925 RTYPEDDATA_TYPE(val) != &Map_type) { 926 rb_raise(cTypeError, "Expected Map instance"); 927 } 928 929 self = ruby_to_Map(val); 930 if (self->key_type != upb_fielddef_type(key_field)) { 931 rb_raise(cTypeError, "Map key type does not match field's key type"); 932 } 933 if (self->value_type != upb_fielddef_type(value_field)) { 934 rb_raise(cTypeError, "Map value type does not match field's value type"); 935 } 936 if (self->value_type_class != field_type_class(layout, value_field)) { 937 rb_raise(cTypeError, "Map value type has wrong message/enum class"); 938 } 939 } 940 layout_set(MessageLayout * layout,void * storage,const upb_fielddef * field,VALUE val)941 void layout_set(MessageLayout* layout, 942 void* storage, 943 const upb_fielddef* field, 944 VALUE val) { 945 void* memory = slot_memory(layout, storage, field); 946 const upb_oneofdef* oneof = upb_fielddef_realcontainingoneof(field); 947 948 if (oneof) { 949 uint32_t* oneof_case = slot_oneof_case(layout, storage, oneof); 950 if (val == Qnil) { 951 // Assigning nil to a oneof field clears the oneof completely. 952 *oneof_case = ONEOF_CASE_NONE; 953 memset(memory, 0, NATIVE_SLOT_MAX_SIZE); 954 } else { 955 // The transition between field types for a single oneof (union) slot is 956 // somewhat complex because we need to ensure that a GC triggered at any 957 // point by a call into the Ruby VM sees a valid state for this field and 958 // does not either go off into the weeds (following what it thinks is a 959 // VALUE but is actually a different field type) or miss an object (seeing 960 // what it thinks is a primitive field but is actually a VALUE for the new 961 // field type). 962 // 963 // In order for the transition to be safe, the oneof case slot must be in 964 // sync with the value slot whenever the Ruby VM has been called. Thus, we 965 // use native_slot_set_value_and_case(), which ensures that both the value 966 // and case number are altered atomically (w.r.t. the Ruby VM). 967 uint32_t case_value = upb_fielddef_number(field); 968 if (upb_fielddef_issubmsg(field) || upb_fielddef_isstring(field)) { 969 case_value |= ONEOF_CASE_MASK; 970 } 971 972 native_slot_set_value_and_case( 973 upb_fielddef_name(field), upb_fielddef_type(field), 974 field_type_class(layout, field), memory, val, oneof_case, case_value); 975 } 976 } else if (is_map_field(field)) { 977 check_map_field_type(layout, val, field); 978 DEREF(memory, VALUE) = val; 979 } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) { 980 check_repeated_field_type(layout, val, field); 981 DEREF(memory, VALUE) = val; 982 } else { 983 native_slot_set(upb_fielddef_name(field), upb_fielddef_type(field), 984 field_type_class(layout, field), memory, val); 985 } 986 987 if (layout->fields[upb_fielddef_index(field)].hasbit != 988 MESSAGE_FIELD_NO_HASBIT) { 989 if (val == Qnil) { 990 // No other field type has a hasbit and allows nil assignment. 991 if (upb_fielddef_type(field) != UPB_TYPE_MESSAGE) { 992 fprintf(stderr, "field: %s\n", upb_fielddef_fullname(field)); 993 } 994 assert(upb_fielddef_type(field) == UPB_TYPE_MESSAGE); 995 slot_clear_hasbit(layout, storage, field); 996 } else { 997 slot_set_hasbit(layout, storage, field); 998 } 999 } 1000 } 1001 layout_init(MessageLayout * layout,void * storage)1002 void layout_init(MessageLayout* layout, void* storage) { 1003 VALUE* value = (VALUE*)CHARPTR_AT(storage, layout->value_offset); 1004 int i; 1005 1006 for (i = 0; i < layout->repeated_count; i++, value++) { 1007 *value = RepeatedField_new_this_type(*value); 1008 } 1009 1010 for (i = 0; i < layout->map_count; i++, value++) { 1011 *value = Map_new_this_type(*value); 1012 } 1013 } 1014 layout_mark(MessageLayout * layout,void * storage)1015 void layout_mark(MessageLayout* layout, void* storage) { 1016 VALUE* values = (VALUE*)CHARPTR_AT(storage, layout->value_offset); 1017 int noneofs = upb_msgdef_numrealoneofs(layout->msgdef); 1018 int i; 1019 1020 for (i = 0; i < layout->value_count; i++) { 1021 rb_gc_mark(values[i]); 1022 } 1023 1024 for (i = 0; i < noneofs; i++) { 1025 MessageOneof* oneof = &layout->oneofs[i]; 1026 uint32_t* case_ptr = (uint32_t*)CHARPTR_AT(storage, oneof->case_offset); 1027 if (*case_ptr & ONEOF_CASE_MASK) { 1028 rb_gc_mark(DEREF_OFFSET(storage, oneof->offset, VALUE)); 1029 } 1030 } 1031 } 1032 layout_dup(MessageLayout * layout,void * to,void * from)1033 void layout_dup(MessageLayout* layout, void* to, void* from) { 1034 upb_msg_field_iter it; 1035 for (upb_msg_field_begin(&it, layout->msgdef); 1036 !upb_msg_field_done(&it); 1037 upb_msg_field_next(&it)) { 1038 const upb_fielddef* field = upb_msg_iter_field(&it); 1039 const upb_oneofdef* oneof = upb_fielddef_realcontainingoneof(field); 1040 1041 void* to_memory = slot_memory(layout, to, field); 1042 void* from_memory = slot_memory(layout, from, field); 1043 1044 if (oneof) { 1045 uint32_t* to_oneof_case = slot_oneof_case(layout, to, oneof); 1046 uint32_t* from_oneof_case = slot_oneof_case(layout, from, oneof); 1047 if (slot_read_oneof_case(layout, from, oneof) == 1048 upb_fielddef_number(field)) { 1049 *to_oneof_case = *from_oneof_case; 1050 native_slot_dup(upb_fielddef_type(field), to_memory, from_memory); 1051 } 1052 } else if (is_map_field(field)) { 1053 DEREF(to_memory, VALUE) = Map_dup(DEREF(from_memory, VALUE)); 1054 } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) { 1055 DEREF(to_memory, VALUE) = RepeatedField_dup(DEREF(from_memory, VALUE)); 1056 } else { 1057 if (field_contains_hasbit(layout, field)) { 1058 if (!slot_is_hasbit_set(layout, from, field)) continue; 1059 slot_set_hasbit(layout, to, field); 1060 } 1061 1062 native_slot_dup(upb_fielddef_type(field), to_memory, from_memory); 1063 } 1064 } 1065 } 1066 layout_deep_copy(MessageLayout * layout,void * to,void * from)1067 void layout_deep_copy(MessageLayout* layout, void* to, void* from) { 1068 upb_msg_field_iter it; 1069 for (upb_msg_field_begin(&it, layout->msgdef); 1070 !upb_msg_field_done(&it); 1071 upb_msg_field_next(&it)) { 1072 const upb_fielddef* field = upb_msg_iter_field(&it); 1073 const upb_oneofdef* oneof = upb_fielddef_realcontainingoneof(field); 1074 1075 void* to_memory = slot_memory(layout, to, field); 1076 void* from_memory = slot_memory(layout, from, field); 1077 1078 if (oneof) { 1079 uint32_t* to_oneof_case = slot_oneof_case(layout, to, oneof); 1080 uint32_t* from_oneof_case = slot_oneof_case(layout, from, oneof); 1081 if (slot_read_oneof_case(layout, from, oneof) == 1082 upb_fielddef_number(field)) { 1083 *to_oneof_case = *from_oneof_case; 1084 native_slot_deep_copy(upb_fielddef_type(field), 1085 field_type_class(layout, field), to_memory, 1086 from_memory); 1087 } 1088 } else if (is_map_field(field)) { 1089 DEREF(to_memory, VALUE) = 1090 Map_deep_copy(DEREF(from_memory, VALUE)); 1091 } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) { 1092 DEREF(to_memory, VALUE) = 1093 RepeatedField_deep_copy(DEREF(from_memory, VALUE)); 1094 } else { 1095 if (field_contains_hasbit(layout, field)) { 1096 if (!slot_is_hasbit_set(layout, from, field)) continue; 1097 slot_set_hasbit(layout, to, field); 1098 } 1099 1100 native_slot_deep_copy(upb_fielddef_type(field), 1101 field_type_class(layout, field), to_memory, 1102 from_memory); 1103 } 1104 } 1105 } 1106 layout_eq(MessageLayout * layout,void * msg1,void * msg2)1107 VALUE layout_eq(MessageLayout* layout, void* msg1, void* msg2) { 1108 upb_msg_field_iter it; 1109 for (upb_msg_field_begin(&it, layout->msgdef); 1110 !upb_msg_field_done(&it); 1111 upb_msg_field_next(&it)) { 1112 const upb_fielddef* field = upb_msg_iter_field(&it); 1113 const upb_oneofdef* oneof = upb_fielddef_realcontainingoneof(field); 1114 1115 void* msg1_memory = slot_memory(layout, msg1, field); 1116 void* msg2_memory = slot_memory(layout, msg2, field); 1117 1118 if (oneof) { 1119 uint32_t* msg1_oneof_case = slot_oneof_case(layout, msg1, oneof); 1120 uint32_t* msg2_oneof_case = slot_oneof_case(layout, msg2, oneof); 1121 if (*msg1_oneof_case != *msg2_oneof_case || 1122 (slot_read_oneof_case(layout, msg1, oneof) == 1123 upb_fielddef_number(field) && 1124 !native_slot_eq(upb_fielddef_type(field), 1125 field_type_class(layout, field), msg1_memory, 1126 msg2_memory))) { 1127 return Qfalse; 1128 } 1129 } else if (is_map_field(field)) { 1130 if (!Map_eq(DEREF(msg1_memory, VALUE), 1131 DEREF(msg2_memory, VALUE))) { 1132 return Qfalse; 1133 } 1134 } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) { 1135 if (!RepeatedField_eq(DEREF(msg1_memory, VALUE), 1136 DEREF(msg2_memory, VALUE))) { 1137 return Qfalse; 1138 } 1139 } else { 1140 if (field_contains_hasbit(layout, field) && 1141 slot_is_hasbit_set(layout, msg1, field) != 1142 slot_is_hasbit_set(layout, msg2, field)) { 1143 // TODO(haberman): I don't think we should actually care about hasbits 1144 // here: an unset default should be able to equal a set default. But we 1145 // can address this later (will also have to make sure defaults are 1146 // being properly set when hasbit is clear). 1147 return Qfalse; 1148 } 1149 if (!native_slot_eq(upb_fielddef_type(field), 1150 field_type_class(layout, field), msg1_memory, 1151 msg2_memory)) { 1152 return Qfalse; 1153 } 1154 } 1155 } 1156 return Qtrue; 1157 } 1158 layout_hash(MessageLayout * layout,void * storage)1159 VALUE layout_hash(MessageLayout* layout, void* storage) { 1160 upb_msg_field_iter it; 1161 st_index_t h = rb_hash_start(0); 1162 VALUE hash_sym = rb_intern("hash"); 1163 for (upb_msg_field_begin(&it, layout->msgdef); 1164 !upb_msg_field_done(&it); 1165 upb_msg_field_next(&it)) { 1166 const upb_fielddef* field = upb_msg_iter_field(&it); 1167 VALUE field_val = layout_get(layout, storage, field); 1168 h = rb_hash_uint(h, NUM2LONG(rb_funcall(field_val, hash_sym, 0))); 1169 } 1170 h = rb_hash_end(h); 1171 1172 return INT2FIX(h); 1173 } 1174 layout_inspect(MessageLayout * layout,void * storage)1175 VALUE layout_inspect(MessageLayout* layout, void* storage) { 1176 VALUE str = rb_str_new2(""); 1177 1178 upb_msg_field_iter it; 1179 bool first = true; 1180 for (upb_msg_field_begin(&it, layout->msgdef); 1181 !upb_msg_field_done(&it); 1182 upb_msg_field_next(&it)) { 1183 const upb_fielddef* field = upb_msg_iter_field(&it); 1184 VALUE field_val = layout_get(layout, storage, field); 1185 1186 if (!first) { 1187 str = rb_str_cat2(str, ", "); 1188 } else { 1189 first = false; 1190 } 1191 str = rb_str_cat2(str, upb_fielddef_name(field)); 1192 str = rb_str_cat2(str, ": "); 1193 1194 str = rb_str_append(str, rb_funcall(field_val, rb_intern("inspect"), 0)); 1195 } 1196 1197 return str; 1198 } 1199