• 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