• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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