Home | History | Annotate | Download | only in protobuf_c
      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