google-protobuf 3.2.0 → 3.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of google-protobuf might be problematic. Click here for more details.

@@ -41,6 +41,7 @@ VALUE upb_def_to_ruby_obj_map;
41
41
 
42
42
  VALUE cError;
43
43
  VALUE cParseError;
44
+ VALUE cTypeError;
44
45
 
45
46
  void add_def_obj(const void* def, VALUE value) {
46
47
  rb_hash_aset(upb_def_to_ruby_obj_map, ULL2NUM((intptr_t)def), value);
@@ -90,19 +91,24 @@ void Init_protobuf_c() {
90
91
  descriptor_instancevar_interned = rb_intern(kDescriptorInstanceVar);
91
92
  DescriptorPool_register(protobuf);
92
93
  Descriptor_register(protobuf);
94
+ FileDescriptor_register(protobuf);
93
95
  FieldDescriptor_register(protobuf);
94
96
  OneofDescriptor_register(protobuf);
95
97
  EnumDescriptor_register(protobuf);
96
98
  MessageBuilderContext_register(internal);
97
99
  OneofBuilderContext_register(internal);
98
100
  EnumBuilderContext_register(internal);
101
+ FileBuilderContext_register(internal);
99
102
  Builder_register(internal);
100
103
  RepeatedField_register(protobuf);
101
104
  Map_register(protobuf);
102
105
 
103
106
  cError = rb_const_get(protobuf, rb_intern("Error"));
104
107
  cParseError = rb_const_get(protobuf, rb_intern("ParseError"));
108
+ cTypeError = rb_const_get(protobuf, rb_intern("TypeError"));
105
109
 
110
+ rb_define_singleton_method(protobuf, "discard_unknown",
111
+ Google_Protobuf_discard_unknown, 1);
106
112
  rb_define_singleton_method(protobuf, "deep_copy",
107
113
  Google_Protobuf_deep_copy, 1);
108
114
 
@@ -110,8 +116,6 @@ void Init_protobuf_c() {
110
116
  kRubyStringASCIIEncoding = rb_usascii_encoding();
111
117
  kRubyString8bitEncoding = rb_ascii8bit_encoding();
112
118
 
113
- upb_def_to_ruby_obj_map = rb_hash_new();
114
119
  rb_gc_register_address(&upb_def_to_ruby_obj_map);
115
- map_parse_frames = rb_ary_new();
116
- rb_gc_register_address(&map_parse_frames);
120
+ upb_def_to_ruby_obj_map = rb_hash_new();
117
121
  }
@@ -40,6 +40,7 @@
40
40
  // Forward decls.
41
41
  struct DescriptorPool;
42
42
  struct Descriptor;
43
+ struct FileDescriptor;
43
44
  struct FieldDescriptor;
44
45
  struct EnumDescriptor;
45
46
  struct MessageLayout;
@@ -47,10 +48,12 @@ struct MessageField;
47
48
  struct MessageHeader;
48
49
  struct MessageBuilderContext;
49
50
  struct EnumBuilderContext;
51
+ struct FileBuilderContext;
50
52
  struct Builder;
51
53
 
52
54
  typedef struct DescriptorPool DescriptorPool;
53
55
  typedef struct Descriptor Descriptor;
56
+ typedef struct FileDescriptor FileDescriptor;
54
57
  typedef struct FieldDescriptor FieldDescriptor;
55
58
  typedef struct OneofDescriptor OneofDescriptor;
56
59
  typedef struct EnumDescriptor EnumDescriptor;
@@ -60,6 +63,7 @@ typedef struct MessageHeader MessageHeader;
60
63
  typedef struct MessageBuilderContext MessageBuilderContext;
61
64
  typedef struct OneofBuilderContext OneofBuilderContext;
62
65
  typedef struct EnumBuilderContext EnumBuilderContext;
66
+ typedef struct FileBuilderContext FileBuilderContext;
63
67
  typedef struct Builder Builder;
64
68
 
65
69
  /*
@@ -116,10 +120,10 @@ struct Descriptor {
116
120
  const upb_handlers* pb_serialize_handlers;
117
121
  const upb_handlers* json_serialize_handlers;
118
122
  const upb_handlers* json_serialize_handlers_preserve;
119
- // Handlers hold type class references for sub-message fields directly in some
120
- // cases. We need to keep these rooted because they might otherwise be
121
- // collected.
122
- VALUE typeclass_references;
123
+ };
124
+
125
+ struct FileDescriptor {
126
+ const upb_filedef* filedef;
123
127
  };
124
128
 
125
129
  struct FieldDescriptor {
@@ -149,24 +153,32 @@ struct EnumBuilderContext {
149
153
  VALUE enumdesc;
150
154
  };
151
155
 
156
+ struct FileBuilderContext {
157
+ VALUE pending_list;
158
+ VALUE file_descriptor;
159
+ VALUE builder;
160
+ };
161
+
152
162
  struct Builder {
153
163
  VALUE pending_list;
164
+ VALUE default_file_descriptor;
154
165
  upb_def** defs; // used only while finalizing
155
166
  };
156
167
 
157
168
  extern VALUE cDescriptorPool;
158
169
  extern VALUE cDescriptor;
170
+ extern VALUE cFileDescriptor;
159
171
  extern VALUE cFieldDescriptor;
160
172
  extern VALUE cEnumDescriptor;
161
173
  extern VALUE cMessageBuilderContext;
162
174
  extern VALUE cOneofBuilderContext;
163
175
  extern VALUE cEnumBuilderContext;
176
+ extern VALUE cFileBuilderContext;
164
177
  extern VALUE cBuilder;
165
178
 
166
179
  extern VALUE cError;
167
180
  extern VALUE cParseError;
168
-
169
- extern VALUE map_parse_frames;
181
+ extern VALUE cTypeError;
170
182
 
171
183
  // We forward-declare all of the Ruby method implementations here because we
172
184
  // sometimes call the methods directly across .c files, rather than going
@@ -180,15 +192,18 @@ VALUE DescriptorPool_alloc(VALUE klass);
180
192
  void DescriptorPool_register(VALUE module);
181
193
  DescriptorPool* ruby_to_DescriptorPool(VALUE value);
182
194
  VALUE DescriptorPool_add(VALUE _self, VALUE def);
183
- VALUE DescriptorPool_build(VALUE _self);
195
+ VALUE DescriptorPool_build(int argc, VALUE* argv, VALUE _self);
184
196
  VALUE DescriptorPool_lookup(VALUE _self, VALUE name);
185
197
  VALUE DescriptorPool_generated_pool(VALUE _self);
186
198
 
199
+ extern VALUE generated_pool;
200
+
187
201
  void Descriptor_mark(void* _self);
188
202
  void Descriptor_free(void* _self);
189
203
  VALUE Descriptor_alloc(VALUE klass);
190
204
  void Descriptor_register(VALUE module);
191
205
  Descriptor* ruby_to_Descriptor(VALUE value);
206
+ VALUE Descriptor_initialize(VALUE _self, VALUE file_descriptor_rb);
192
207
  VALUE Descriptor_name(VALUE _self);
193
208
  VALUE Descriptor_name_set(VALUE _self, VALUE str);
194
209
  VALUE Descriptor_each(VALUE _self);
@@ -198,8 +213,19 @@ VALUE Descriptor_add_oneof(VALUE _self, VALUE obj);
198
213
  VALUE Descriptor_each_oneof(VALUE _self);
199
214
  VALUE Descriptor_lookup_oneof(VALUE _self, VALUE name);
200
215
  VALUE Descriptor_msgclass(VALUE _self);
216
+ VALUE Descriptor_file_descriptor(VALUE _self);
201
217
  extern const rb_data_type_t _Descriptor_type;
202
218
 
219
+ void FileDescriptor_mark(void* _self);
220
+ void FileDescriptor_free(void* _self);
221
+ VALUE FileDescriptor_alloc(VALUE klass);
222
+ void FileDescriptor_register(VALUE module);
223
+ FileDescriptor* ruby_to_FileDescriptor(VALUE value);
224
+ VALUE FileDescriptor_initialize(int argc, VALUE* argv, VALUE _self);
225
+ VALUE FileDescriptor_name(VALUE _self);
226
+ VALUE FileDescriptor_syntax(VALUE _self);
227
+ VALUE FileDescriptor_syntax_set(VALUE _self, VALUE syntax);
228
+
203
229
  void FieldDescriptor_mark(void* _self);
204
230
  void FieldDescriptor_free(void* _self);
205
231
  VALUE FieldDescriptor_alloc(VALUE klass);
@@ -209,6 +235,8 @@ VALUE FieldDescriptor_name(VALUE _self);
209
235
  VALUE FieldDescriptor_name_set(VALUE _self, VALUE str);
210
236
  VALUE FieldDescriptor_type(VALUE _self);
211
237
  VALUE FieldDescriptor_type_set(VALUE _self, VALUE type);
238
+ VALUE FieldDescriptor_default(VALUE _self);
239
+ VALUE FieldDescriptor_default_set(VALUE _self, VALUE default_value);
212
240
  VALUE FieldDescriptor_label(VALUE _self);
213
241
  VALUE FieldDescriptor_label_set(VALUE _self, VALUE label);
214
242
  VALUE FieldDescriptor_number(VALUE _self);
@@ -216,6 +244,8 @@ VALUE FieldDescriptor_number_set(VALUE _self, VALUE number);
216
244
  VALUE FieldDescriptor_submsg_name(VALUE _self);
217
245
  VALUE FieldDescriptor_submsg_name_set(VALUE _self, VALUE value);
218
246
  VALUE FieldDescriptor_subtype(VALUE _self);
247
+ VALUE FieldDescriptor_has(VALUE _self, VALUE msg_rb);
248
+ VALUE FieldDescriptor_clear(VALUE _self, VALUE msg_rb);
219
249
  VALUE FieldDescriptor_get(VALUE _self, VALUE msg_rb);
220
250
  VALUE FieldDescriptor_set(VALUE _self, VALUE msg_rb, VALUE value);
221
251
  upb_fieldtype_t ruby_to_fieldtype(VALUE type);
@@ -236,6 +266,8 @@ void EnumDescriptor_free(void* _self);
236
266
  VALUE EnumDescriptor_alloc(VALUE klass);
237
267
  void EnumDescriptor_register(VALUE module);
238
268
  EnumDescriptor* ruby_to_EnumDescriptor(VALUE value);
269
+ VALUE EnumDescriptor_initialize(VALUE _self, VALUE file_descriptor_rb);
270
+ VALUE EnumDescriptor_file_descriptor(VALUE _self);
239
271
  VALUE EnumDescriptor_name(VALUE _self);
240
272
  VALUE EnumDescriptor_name_set(VALUE _self, VALUE str);
241
273
  VALUE EnumDescriptor_add_value(VALUE _self, VALUE name, VALUE number);
@@ -277,11 +309,23 @@ EnumBuilderContext* ruby_to_EnumBuilderContext(VALUE value);
277
309
  VALUE EnumBuilderContext_initialize(VALUE _self, VALUE enumdesc);
278
310
  VALUE EnumBuilderContext_value(VALUE _self, VALUE name, VALUE number);
279
311
 
312
+ void FileBuilderContext_mark(void* _self);
313
+ void FileBuilderContext_free(void* _self);
314
+ VALUE FileBuilderContext_alloc(VALUE klass);
315
+ void FileBuilderContext_register(VALUE module);
316
+ VALUE FileBuilderContext_initialize(VALUE _self, VALUE file_descriptor,
317
+ VALUE builder);
318
+ VALUE FileBuilderContext_add_message(VALUE _self, VALUE name);
319
+ VALUE FileBuilderContext_add_enum(VALUE _self, VALUE name);
320
+ VALUE FileBuilderContext_pending_descriptors(VALUE _self);
321
+
280
322
  void Builder_mark(void* _self);
281
323
  void Builder_free(void* _self);
282
324
  VALUE Builder_alloc(VALUE klass);
283
325
  void Builder_register(VALUE module);
284
326
  Builder* ruby_to_Builder(VALUE value);
327
+ VALUE Builder_initialize(VALUE _self);
328
+ VALUE Builder_add_file(int argc, VALUE *argv, VALUE _self);
285
329
  VALUE Builder_add_message(VALUE _self, VALUE name);
286
330
  VALUE Builder_add_enum(VALUE _self, VALUE name);
287
331
  VALUE Builder_finalize_to_pool(VALUE _self, VALUE pool_rb);
@@ -293,14 +337,16 @@ VALUE Builder_finalize_to_pool(VALUE _self, VALUE pool_rb);
293
337
  #define NATIVE_SLOT_MAX_SIZE sizeof(uint64_t)
294
338
 
295
339
  size_t native_slot_size(upb_fieldtype_t type);
296
- void native_slot_set(upb_fieldtype_t type,
340
+ void native_slot_set(const char* name,
341
+ upb_fieldtype_t type,
297
342
  VALUE type_class,
298
343
  void* memory,
299
344
  VALUE value);
300
345
  // Atomically (with respect to Ruby VM calls) either update the value and set a
301
346
  // oneof case, or do neither. If |case_memory| is null, then no case value is
302
347
  // set.
303
- void native_slot_set_value_and_case(upb_fieldtype_t type,
348
+ void native_slot_set_value_and_case(const char* name,
349
+ upb_fieldtype_t type,
304
350
  VALUE type_class,
305
351
  void* memory,
306
352
  VALUE value,
@@ -316,7 +362,7 @@ void native_slot_deep_copy(upb_fieldtype_t type, void* to, void* from);
316
362
  bool native_slot_eq(upb_fieldtype_t type, void* mem1, void* mem2);
317
363
 
318
364
  VALUE native_slot_encode_and_freeze_string(upb_fieldtype_t type, VALUE value);
319
- void native_slot_check_int_range_precision(upb_fieldtype_t type, VALUE value);
365
+ void native_slot_check_int_range_precision(const char* name, upb_fieldtype_t type, VALUE value);
320
366
 
321
367
  extern rb_encoding* kRubyStringUtf8Encoding;
322
368
  extern rb_encoding* kRubyStringASCIIEncoding;
@@ -397,6 +443,7 @@ typedef struct {
397
443
  upb_fieldtype_t key_type;
398
444
  upb_fieldtype_t value_type;
399
445
  VALUE value_type_class;
446
+ VALUE parse_frame;
400
447
  upb_strtable table;
401
448
  } Map;
402
449
 
@@ -405,6 +452,7 @@ void Map_free(void* self);
405
452
  VALUE Map_alloc(VALUE klass);
406
453
  VALUE Map_init(int argc, VALUE* argv, VALUE self);
407
454
  void Map_register(VALUE module);
455
+ VALUE Map_set_frame(VALUE self, VALUE val);
408
456
 
409
457
  extern const rb_data_type_t Map_type;
410
458
  extern VALUE cMap;
@@ -424,6 +472,7 @@ VALUE Map_dup(VALUE _self);
424
472
  VALUE Map_deep_copy(VALUE _self);
425
473
  VALUE Map_eq(VALUE _self, VALUE _other);
426
474
  VALUE Map_hash(VALUE _self);
475
+ VALUE Map_to_h(VALUE _self);
427
476
  VALUE Map_inspect(VALUE _self);
428
477
  VALUE Map_merge(VALUE _self, VALUE hashmap);
429
478
  VALUE Map_merge_into_self(VALUE _self, VALUE hashmap);
@@ -444,10 +493,12 @@ VALUE Map_iter_value(Map_iter* iter);
444
493
  // -----------------------------------------------------------------------------
445
494
 
446
495
  #define MESSAGE_FIELD_NO_CASE ((size_t)-1)
496
+ #define MESSAGE_FIELD_NO_HASBIT ((size_t)-1)
447
497
 
448
498
  struct MessageField {
449
499
  size_t offset;
450
500
  size_t case_offset; // for oneofs, a uint32. Else, MESSAGE_FIELD_NO_CASE.
501
+ size_t hasbit;
451
502
  };
452
503
 
453
504
  struct MessageLayout {
@@ -458,6 +509,9 @@ struct MessageLayout {
458
509
 
459
510
  MessageLayout* create_layout(const upb_msgdef* msgdef);
460
511
  void free_layout(MessageLayout* layout);
512
+ bool field_contains_hasbit(MessageLayout* layout,
513
+ const upb_fielddef* field);
514
+ VALUE layout_get_default(const upb_fielddef* field);
461
515
  VALUE layout_get(MessageLayout* layout,
462
516
  const void* storage,
463
517
  const upb_fielddef* field);
@@ -465,6 +519,12 @@ void layout_set(MessageLayout* layout,
465
519
  void* storage,
466
520
  const upb_fielddef* field,
467
521
  VALUE val);
522
+ VALUE layout_has(MessageLayout* layout,
523
+ const void* storage,
524
+ const upb_fielddef* field);
525
+ void layout_clear(MessageLayout* layout,
526
+ const void* storage,
527
+ const upb_fielddef* field);
468
528
  void layout_init(MessageLayout* layout, void* storage);
469
529
  void layout_mark(MessageLayout* layout, void* storage);
470
530
  void layout_dup(MessageLayout* layout, void* to, void* from);
@@ -477,8 +537,20 @@ VALUE layout_inspect(MessageLayout* layout, void* storage);
477
537
  // Message class creation.
478
538
  // -----------------------------------------------------------------------------
479
539
 
540
+ // This should probably be factored into a common upb component.
541
+
542
+ typedef struct {
543
+ upb_byteshandler handler;
544
+ upb_bytessink sink;
545
+ char *ptr;
546
+ size_t len, size;
547
+ } stringsink;
548
+
549
+ void stringsink_uninit(stringsink *sink);
550
+
480
551
  struct MessageHeader {
481
- Descriptor* descriptor; // kept alive by self.class.descriptor reference.
552
+ Descriptor* descriptor; // kept alive by self.class.descriptor reference.
553
+ stringsink* unknown_fields; // store unknown fields in decoding.
482
554
  // Data comes after this.
483
555
  };
484
556
 
@@ -496,14 +568,16 @@ VALUE Message_deep_copy(VALUE _self);
496
568
  VALUE Message_eq(VALUE _self, VALUE _other);
497
569
  VALUE Message_hash(VALUE _self);
498
570
  VALUE Message_inspect(VALUE _self);
571
+ VALUE Message_to_h(VALUE _self);
499
572
  VALUE Message_index(VALUE _self, VALUE field_name);
500
573
  VALUE Message_index_set(VALUE _self, VALUE field_name, VALUE value);
501
574
  VALUE Message_descriptor(VALUE klass);
502
575
  VALUE Message_decode(VALUE klass, VALUE data);
503
576
  VALUE Message_encode(VALUE klass, VALUE msg_rb);
504
- VALUE Message_decode_json(VALUE klass, VALUE data);
577
+ VALUE Message_decode_json(int argc, VALUE* argv, VALUE klass);
505
578
  VALUE Message_encode_json(int argc, VALUE* argv, VALUE klass);
506
579
 
580
+ VALUE Google_Protobuf_discard_unknown(VALUE self, VALUE msg_rb);
507
581
  VALUE Google_Protobuf_deep_copy(VALUE self, VALUE obj);
508
582
 
509
583
  VALUE build_module_from_enumdesc(EnumDescriptor* enumdef);
@@ -178,7 +178,7 @@ VALUE RepeatedField_index_set(VALUE _self, VALUE _index, VALUE val) {
178
178
  }
179
179
 
180
180
  memory = RepeatedField_memoryat(self, index, element_size);
181
- native_slot_set(field_type, field_type_class, memory, val);
181
+ native_slot_set("", field_type, field_type_class, memory, val);
182
182
  return Qnil;
183
183
  }
184
184
 
@@ -217,12 +217,18 @@ VALUE RepeatedField_push(VALUE _self, VALUE val) {
217
217
 
218
218
  RepeatedField_reserve(self, self->size + 1);
219
219
  memory = (void *) (((uint8_t *)self->elements) + self->size * element_size);
220
- native_slot_set(field_type, self->field_type_class, memory, val);
220
+ native_slot_set("", field_type, self->field_type_class, memory, val);
221
221
  // native_slot_set may raise an error; bump size only after set.
222
222
  self->size++;
223
223
  return _self;
224
224
  }
225
225
 
226
+ VALUE RepeatedField_push_vararg(VALUE _self, VALUE args) {
227
+ for (int i = 0; i < RARRAY_LEN(args); i++) {
228
+ RepeatedField_push(_self, rb_ary_entry(args, i));
229
+ }
230
+ return _self;
231
+ }
226
232
 
227
233
  // Used by parsing handlers.
228
234
  void RepeatedField_push_native(VALUE _self, void* data) {
@@ -626,8 +632,8 @@ void RepeatedField_register(VALUE module) {
626
632
  VALUE klass = rb_define_class_under(
627
633
  module, "RepeatedField", rb_cObject);
628
634
  rb_define_alloc_func(klass, RepeatedField_alloc);
629
- cRepeatedField = klass;
630
635
  rb_gc_register_address(&cRepeatedField);
636
+ cRepeatedField = klass;
631
637
 
632
638
  rb_define_method(klass, "initialize",
633
639
  RepeatedField_init, -1);
@@ -635,7 +641,7 @@ void RepeatedField_register(VALUE module) {
635
641
  rb_define_method(klass, "[]", RepeatedField_index, -1);
636
642
  rb_define_method(klass, "at", RepeatedField_index, -1);
637
643
  rb_define_method(klass, "[]=", RepeatedField_index_set, 2);
638
- rb_define_method(klass, "push", RepeatedField_push, 1);
644
+ rb_define_method(klass, "push", RepeatedField_push_vararg, -2);
639
645
  rb_define_method(klass, "<<", RepeatedField_push, 1);
640
646
  rb_define_private_method(klass, "pop_one", RepeatedField_pop_one, 0);
641
647
  rb_define_method(klass, "replace", RepeatedField_replace, 1);
@@ -38,6 +38,8 @@
38
38
  // Ruby <-> native slot management.
39
39
  // -----------------------------------------------------------------------------
40
40
 
41
+ #define CHARPTR_AT(msg, ofs) ((char*)msg + ofs)
42
+ #define DEREF_OFFSET(msg, ofs, type) *(type*)CHARPTR_AT(msg, ofs)
41
43
  #define DEREF(memory, type) *(type*)(memory)
42
44
 
43
45
  size_t native_slot_size(upb_fieldtype_t type) {
@@ -57,46 +59,16 @@ size_t native_slot_size(upb_fieldtype_t type) {
57
59
  }
58
60
  }
59
61
 
60
- static VALUE value_from_default(const upb_fielddef *field) {
61
- switch (upb_fielddef_type(field)) {
62
- case UPB_TYPE_FLOAT: return DBL2NUM(upb_fielddef_defaultfloat(field));
63
- case UPB_TYPE_DOUBLE: return DBL2NUM(upb_fielddef_defaultdouble(field));
64
- case UPB_TYPE_BOOL:
65
- return upb_fielddef_defaultbool(field) ? Qtrue : Qfalse;
66
- case UPB_TYPE_MESSAGE: return Qnil;
67
- case UPB_TYPE_ENUM: {
68
- const upb_enumdef *enumdef = upb_fielddef_enumsubdef(field);
69
- int32_t num = upb_fielddef_defaultint32(field);
70
- const char *label = upb_enumdef_iton(enumdef, num);
71
- if (label) {
72
- return ID2SYM(rb_intern(label));
73
- } else {
74
- return INT2NUM(num);
75
- }
76
- }
77
- case UPB_TYPE_INT32: return INT2NUM(upb_fielddef_defaultint32(field));
78
- case UPB_TYPE_INT64: return LL2NUM(upb_fielddef_defaultint64(field));;
79
- case UPB_TYPE_UINT32: return UINT2NUM(upb_fielddef_defaultuint32(field));
80
- case UPB_TYPE_UINT64: return ULL2NUM(upb_fielddef_defaultuint64(field));
81
- case UPB_TYPE_STRING:
82
- case UPB_TYPE_BYTES: {
83
- size_t size;
84
- const char *str = upb_fielddef_defaultstr(field, &size);
85
- return rb_str_new(str, size);
86
- }
87
- default: return Qnil;
88
- }
89
- }
90
-
91
62
  static bool is_ruby_num(VALUE value) {
92
63
  return (TYPE(value) == T_FLOAT ||
93
64
  TYPE(value) == T_FIXNUM ||
94
65
  TYPE(value) == T_BIGNUM);
95
66
  }
96
67
 
97
- void native_slot_check_int_range_precision(upb_fieldtype_t type, VALUE val) {
68
+ void native_slot_check_int_range_precision(const char* name, upb_fieldtype_t type, VALUE val) {
98
69
  if (!is_ruby_num(val)) {
99
- rb_raise(rb_eTypeError, "Expected number type for integral field.");
70
+ rb_raise(cTypeError, "Expected number type for integral field '%s' (given %s).",
71
+ name, rb_class2name(CLASS_OF(val)));
100
72
  }
101
73
 
102
74
  // NUM2{INT,UINT,LL,ULL} macros do the appropriate range checks on upper
@@ -106,13 +78,15 @@ void native_slot_check_int_range_precision(upb_fieldtype_t type, VALUE val) {
106
78
  double dbl_val = NUM2DBL(val);
107
79
  if (floor(dbl_val) != dbl_val) {
108
80
  rb_raise(rb_eRangeError,
109
- "Non-integral floating point value assigned to integer field.");
81
+ "Non-integral floating point value assigned to integer field '%s' (given %s).",
82
+ name, rb_class2name(CLASS_OF(val)));
110
83
  }
111
84
  }
112
85
  if (type == UPB_TYPE_UINT32 || type == UPB_TYPE_UINT64) {
113
86
  if (NUM2DBL(val) < 0) {
114
87
  rb_raise(rb_eRangeError,
115
- "Assigning negative value to unsigned integer field.");
88
+ "Assigning negative value to unsigned integer field '%s' (given %s).",
89
+ name, rb_class2name(CLASS_OF(val)));
116
90
  }
117
91
  }
118
92
  }
@@ -137,12 +111,14 @@ VALUE native_slot_encode_and_freeze_string(upb_fieldtype_t type, VALUE value) {
137
111
  return value;
138
112
  }
139
113
 
140
- void native_slot_set(upb_fieldtype_t type, VALUE type_class,
114
+ void native_slot_set(const char* name,
115
+ upb_fieldtype_t type, VALUE type_class,
141
116
  void* memory, VALUE value) {
142
- native_slot_set_value_and_case(type, type_class, memory, value, NULL, 0);
117
+ native_slot_set_value_and_case(name, type, type_class, memory, value, NULL, 0);
143
118
  }
144
119
 
145
- void native_slot_set_value_and_case(upb_fieldtype_t type, VALUE type_class,
120
+ void native_slot_set_value_and_case(const char* name,
121
+ upb_fieldtype_t type, VALUE type_class,
146
122
  void* memory, VALUE value,
147
123
  uint32_t* case_memory,
148
124
  uint32_t case_number) {
@@ -153,13 +129,15 @@ void native_slot_set_value_and_case(upb_fieldtype_t type, VALUE type_class,
153
129
  switch (type) {
154
130
  case UPB_TYPE_FLOAT:
155
131
  if (!is_ruby_num(value)) {
156
- rb_raise(rb_eTypeError, "Expected number type for float field.");
132
+ rb_raise(cTypeError, "Expected number type for float field '%s' (given %s).",
133
+ name, rb_class2name(CLASS_OF(value)));
157
134
  }
158
135
  DEREF(memory, float) = NUM2DBL(value);
159
136
  break;
160
137
  case UPB_TYPE_DOUBLE:
161
138
  if (!is_ruby_num(value)) {
162
- rb_raise(rb_eTypeError, "Expected number type for double field.");
139
+ rb_raise(cTypeError, "Expected number type for double field '%s' (given %s).",
140
+ name, rb_class2name(CLASS_OF(value)));
163
141
  }
164
142
  DEREF(memory, double) = NUM2DBL(value);
165
143
  break;
@@ -170,15 +148,27 @@ void native_slot_set_value_and_case(upb_fieldtype_t type, VALUE type_class,
170
148
  } else if (value == Qfalse) {
171
149
  val = 0;
172
150
  } else {
173
- rb_raise(rb_eTypeError, "Invalid argument for boolean field.");
151
+ rb_raise(cTypeError, "Invalid argument for boolean field '%s' (given %s).",
152
+ name, rb_class2name(CLASS_OF(value)));
174
153
  }
175
154
  DEREF(memory, int8_t) = val;
176
155
  break;
177
156
  }
178
157
  case UPB_TYPE_STRING:
158
+ if (CLASS_OF(value) == rb_cSymbol) {
159
+ value = rb_funcall(value, rb_intern("to_s"), 0);
160
+ } else if (CLASS_OF(value) != rb_cString) {
161
+ rb_raise(cTypeError, "Invalid argument for string field '%s' (given %s).",
162
+ name, rb_class2name(CLASS_OF(value)));
163
+ }
164
+
165
+ DEREF(memory, VALUE) = native_slot_encode_and_freeze_string(type, value);
166
+ break;
167
+
179
168
  case UPB_TYPE_BYTES: {
180
169
  if (CLASS_OF(value) != rb_cString) {
181
- rb_raise(rb_eTypeError, "Invalid argument for string field.");
170
+ rb_raise(cTypeError, "Invalid argument for bytes field '%s' (given %s).",
171
+ name, rb_class2name(CLASS_OF(value)));
182
172
  }
183
173
 
184
174
  DEREF(memory, VALUE) = native_slot_encode_and_freeze_string(type, value);
@@ -188,29 +178,61 @@ void native_slot_set_value_and_case(upb_fieldtype_t type, VALUE type_class,
188
178
  if (CLASS_OF(value) == CLASS_OF(Qnil)) {
189
179
  value = Qnil;
190
180
  } else if (CLASS_OF(value) != type_class) {
191
- rb_raise(rb_eTypeError,
192
- "Invalid type %s to assign to submessage field.",
193
- rb_class2name(CLASS_OF(value)));
181
+ // check for possible implicit conversions
182
+ VALUE converted_value = NULL;
183
+ char* field_type_name = rb_class2name(type_class);
184
+
185
+ if (strcmp(field_type_name, "Google::Protobuf::Timestamp") == 0 &&
186
+ rb_obj_is_kind_of(value, rb_cTime)) {
187
+ // Time -> Google::Protobuf::Timestamp
188
+ VALUE hash = rb_hash_new();
189
+ rb_hash_aset(hash, rb_str_new2("seconds"), rb_funcall(value, rb_intern("to_i"), 0));
190
+ rb_hash_aset(hash, rb_str_new2("nanos"), rb_funcall(value, rb_intern("nsec"), 0));
191
+ VALUE args[1] = { hash };
192
+ converted_value = rb_class_new_instance(1, args, type_class);
193
+ } else if (strcmp(field_type_name, "Google::Protobuf::Duration") == 0 &&
194
+ rb_obj_is_kind_of(value, rb_cNumeric)) {
195
+ // Numeric -> Google::Protobuf::Duration
196
+ VALUE hash = rb_hash_new();
197
+ rb_hash_aset(hash, rb_str_new2("seconds"), rb_funcall(value, rb_intern("to_i"), 0));
198
+ VALUE n_value = rb_funcall(value, rb_intern("remainder"), 1, INT2NUM(1));
199
+ n_value = rb_funcall(n_value, rb_intern("*"), 1, INT2NUM(1000000000));
200
+ n_value = rb_funcall(n_value, rb_intern("round"), 0);
201
+ rb_hash_aset(hash, rb_str_new2("nanos"), n_value);
202
+ VALUE args[1] = { hash };
203
+ converted_value = rb_class_new_instance(1, args, type_class);
204
+ }
205
+
206
+ // raise if no suitable conversaion could be found
207
+ if (converted_value == NULL) {
208
+ rb_raise(cTypeError,
209
+ "Invalid type %s to assign to submessage field '%s'.",
210
+ rb_class2name(CLASS_OF(value)), name);
211
+ } else {
212
+ value = converted_value;
213
+ }
194
214
  }
195
215
  DEREF(memory, VALUE) = value;
196
216
  break;
197
217
  }
198
218
  case UPB_TYPE_ENUM: {
199
219
  int32_t int_val = 0;
200
- if (!is_ruby_num(value) && TYPE(value) != T_SYMBOL) {
201
- rb_raise(rb_eTypeError,
202
- "Expected number or symbol type for enum field.");
220
+ if (TYPE(value) == T_STRING) {
221
+ value = rb_funcall(value, rb_intern("to_sym"), 0);
222
+ } else if (!is_ruby_num(value) && TYPE(value) != T_SYMBOL) {
223
+ rb_raise(cTypeError,
224
+ "Expected number or symbol type for enum field '%s'.", name);
203
225
  }
204
226
  if (TYPE(value) == T_SYMBOL) {
205
227
  // Ensure that the given symbol exists in the enum module.
206
228
  VALUE lookup = rb_funcall(type_class, rb_intern("resolve"), 1, value);
207
229
  if (lookup == Qnil) {
208
- rb_raise(rb_eRangeError, "Unknown symbol value for enum field.");
230
+ rb_raise(rb_eRangeError, "Unknown symbol value for enum field '%s'.", name);
209
231
  } else {
210
232
  int_val = NUM2INT(lookup);
211
233
  }
212
234
  } else {
213
- native_slot_check_int_range_precision(UPB_TYPE_INT32, value);
235
+ native_slot_check_int_range_precision(name, UPB_TYPE_INT32, value);
214
236
  int_val = NUM2INT(value);
215
237
  }
216
238
  DEREF(memory, int32_t) = int_val;
@@ -220,7 +242,7 @@ void native_slot_set_value_and_case(upb_fieldtype_t type, VALUE type_class,
220
242
  case UPB_TYPE_INT64:
221
243
  case UPB_TYPE_UINT32:
222
244
  case UPB_TYPE_UINT64:
223
- native_slot_check_int_range_precision(type, value);
245
+ native_slot_check_int_range_precision(name, type, value);
224
246
  switch (type) {
225
247
  case UPB_TYPE_INT32:
226
248
  DEREF(memory, int32_t) = NUM2INT(value);
@@ -393,7 +415,12 @@ const upb_msgdef *map_entry_msgdef(const upb_fielddef* field) {
393
415
  }
394
416
 
395
417
  bool is_map_field(const upb_fielddef *field) {
396
- return tryget_map_entry_msgdef(field) != NULL;
418
+ const upb_msgdef* subdef = tryget_map_entry_msgdef(field);
419
+ if (subdef == NULL) return false;
420
+
421
+ // Map fields are a proto3 feature.
422
+ // If we're using proto2 syntax we need to fallback to the repeated field.
423
+ return upb_msgdef_syntax(subdef) == UPB_SYNTAX_PROTO3;
397
424
  }
398
425
 
399
426
  const upb_fielddef* map_field_key(const upb_fielddef* field) {
@@ -422,6 +449,12 @@ const upb_fielddef* map_entry_value(const upb_msgdef* msgdef) {
422
449
  // Memory layout management.
423
450
  // -----------------------------------------------------------------------------
424
451
 
452
+ bool field_contains_hasbit(MessageLayout* layout,
453
+ const upb_fielddef* field) {
454
+ return layout->fields[upb_fielddef_index(field)].hasbit !=
455
+ MESSAGE_FIELD_NO_HASBIT;
456
+ }
457
+
425
458
  static size_t align_up_to(size_t offset, size_t granularity) {
426
459
  // Granularity must be a power of two.
427
460
  return (offset + granularity - 1) & ~(granularity - 1);
@@ -436,6 +469,23 @@ MessageLayout* create_layout(const upb_msgdef* msgdef) {
436
469
 
437
470
  layout->fields = ALLOC_N(MessageField, nfields);
438
471
 
472
+ size_t hasbit = 0;
473
+ for (upb_msg_field_begin(&it, msgdef);
474
+ !upb_msg_field_done(&it);
475
+ upb_msg_field_next(&it)) {
476
+ const upb_fielddef* field = upb_msg_iter_field(&it);
477
+ if (upb_fielddef_haspresence(field)) {
478
+ layout->fields[upb_fielddef_index(field)].hasbit = hasbit++;
479
+ } else {
480
+ layout->fields[upb_fielddef_index(field)].hasbit =
481
+ MESSAGE_FIELD_NO_HASBIT;
482
+ }
483
+ }
484
+
485
+ if (hasbit != 0) {
486
+ off += (hasbit + 8 - 1) / 8;
487
+ }
488
+
439
489
  for (upb_msg_field_begin(&it, msgdef);
440
490
  !upb_msg_field_done(&it);
441
491
  upb_msg_field_next(&it)) {
@@ -558,6 +608,137 @@ static uint32_t* slot_oneof_case(MessageLayout* layout,
558
608
  layout->fields[upb_fielddef_index(field)].case_offset);
559
609
  }
560
610
 
611
+ static void slot_set_hasbit(MessageLayout* layout,
612
+ const void* storage,
613
+ const upb_fielddef* field) {
614
+ size_t hasbit = layout->fields[upb_fielddef_index(field)].hasbit;
615
+ assert(hasbit != MESSAGE_FIELD_NO_HASBIT);
616
+
617
+ ((uint8_t*)storage)[hasbit / 8] |= 1 << (hasbit % 8);
618
+ }
619
+
620
+ static void slot_clear_hasbit(MessageLayout* layout,
621
+ const void* storage,
622
+ const upb_fielddef* field) {
623
+ size_t hasbit = layout->fields[upb_fielddef_index(field)].hasbit;
624
+ assert(hasbit != MESSAGE_FIELD_NO_HASBIT);
625
+ ((uint8_t*)storage)[hasbit / 8] &= ~(1 << (hasbit % 8));
626
+ }
627
+
628
+ static bool slot_is_hasbit_set(MessageLayout* layout,
629
+ const void* storage,
630
+ const upb_fielddef* field) {
631
+ size_t hasbit = layout->fields[upb_fielddef_index(field)].hasbit;
632
+ if (hasbit == MESSAGE_FIELD_NO_HASBIT) {
633
+ return false;
634
+ }
635
+
636
+ return DEREF_OFFSET(
637
+ (uint8_t*)storage, hasbit / 8, char) & (1 << (hasbit % 8));
638
+ }
639
+
640
+ VALUE layout_has(MessageLayout* layout,
641
+ const void* storage,
642
+ const upb_fielddef* field) {
643
+ assert(field_contains_hasbit(layout, field));
644
+ return slot_is_hasbit_set(layout, storage, field) ? Qtrue : Qfalse;
645
+ }
646
+
647
+ void layout_clear(MessageLayout* layout,
648
+ const void* storage,
649
+ const upb_fielddef* field) {
650
+ void* memory = slot_memory(layout, storage, field);
651
+ uint32_t* oneof_case = slot_oneof_case(layout, storage, field);
652
+
653
+ if (field_contains_hasbit(layout, field)) {
654
+ slot_clear_hasbit(layout, storage, field);
655
+ }
656
+
657
+ if (upb_fielddef_containingoneof(field)) {
658
+ memset(memory, 0, NATIVE_SLOT_MAX_SIZE);
659
+ *oneof_case = ONEOF_CASE_NONE;
660
+ } else if (is_map_field(field)) {
661
+ VALUE map = Qnil;
662
+
663
+ const upb_fielddef* key_field = map_field_key(field);
664
+ const upb_fielddef* value_field = map_field_value(field);
665
+ VALUE type_class = field_type_class(value_field);
666
+
667
+ if (type_class != Qnil) {
668
+ VALUE args[3] = {
669
+ fieldtype_to_ruby(upb_fielddef_type(key_field)),
670
+ fieldtype_to_ruby(upb_fielddef_type(value_field)),
671
+ type_class,
672
+ };
673
+ map = rb_class_new_instance(3, args, cMap);
674
+ } else {
675
+ VALUE args[2] = {
676
+ fieldtype_to_ruby(upb_fielddef_type(key_field)),
677
+ fieldtype_to_ruby(upb_fielddef_type(value_field)),
678
+ };
679
+ map = rb_class_new_instance(2, args, cMap);
680
+ }
681
+
682
+ DEREF(memory, VALUE) = map;
683
+ } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
684
+ VALUE ary = Qnil;
685
+
686
+ VALUE type_class = field_type_class(field);
687
+
688
+ if (type_class != Qnil) {
689
+ VALUE args[2] = {
690
+ fieldtype_to_ruby(upb_fielddef_type(field)),
691
+ type_class,
692
+ };
693
+ ary = rb_class_new_instance(2, args, cRepeatedField);
694
+ } else {
695
+ VALUE args[1] = { fieldtype_to_ruby(upb_fielddef_type(field)) };
696
+ ary = rb_class_new_instance(1, args, cRepeatedField);
697
+ }
698
+
699
+ DEREF(memory, VALUE) = ary;
700
+ } else {
701
+ native_slot_set(upb_fielddef_name(field),
702
+ upb_fielddef_type(field), field_type_class(field),
703
+ memory, layout_get_default(field));
704
+ }
705
+ }
706
+
707
+ VALUE layout_get_default(const upb_fielddef *field) {
708
+ switch (upb_fielddef_type(field)) {
709
+ case UPB_TYPE_FLOAT: return DBL2NUM(upb_fielddef_defaultfloat(field));
710
+ case UPB_TYPE_DOUBLE: return DBL2NUM(upb_fielddef_defaultdouble(field));
711
+ case UPB_TYPE_BOOL:
712
+ return upb_fielddef_defaultbool(field) ? Qtrue : Qfalse;
713
+ case UPB_TYPE_MESSAGE: return Qnil;
714
+ case UPB_TYPE_ENUM: {
715
+ const upb_enumdef *enumdef = upb_fielddef_enumsubdef(field);
716
+ int32_t num = upb_fielddef_defaultint32(field);
717
+ const char *label = upb_enumdef_iton(enumdef, num);
718
+ if (label) {
719
+ return ID2SYM(rb_intern(label));
720
+ } else {
721
+ return INT2NUM(num);
722
+ }
723
+ }
724
+ case UPB_TYPE_INT32: return INT2NUM(upb_fielddef_defaultint32(field));
725
+ case UPB_TYPE_INT64: return LL2NUM(upb_fielddef_defaultint64(field));;
726
+ case UPB_TYPE_UINT32: return UINT2NUM(upb_fielddef_defaultuint32(field));
727
+ case UPB_TYPE_UINT64: return ULL2NUM(upb_fielddef_defaultuint64(field));
728
+ case UPB_TYPE_STRING:
729
+ case UPB_TYPE_BYTES: {
730
+ size_t size;
731
+ const char *str = upb_fielddef_defaultstr(field, &size);
732
+ VALUE str_rb = rb_str_new(str, size);
733
+
734
+ rb_enc_associate(str_rb, (upb_fielddef_type(field) == UPB_TYPE_BYTES) ?
735
+ kRubyString8bitEncoding : kRubyStringUtf8Encoding);
736
+ rb_obj_freeze(str_rb);
737
+ return str_rb;
738
+ }
739
+ default: return Qnil;
740
+ }
741
+ }
561
742
 
562
743
  VALUE layout_get(MessageLayout* layout,
563
744
  const void* storage,
@@ -565,15 +746,24 @@ VALUE layout_get(MessageLayout* layout,
565
746
  void* memory = slot_memory(layout, storage, field);
566
747
  uint32_t* oneof_case = slot_oneof_case(layout, storage, field);
567
748
 
749
+ bool field_set;
750
+ if (field_contains_hasbit(layout, field)) {
751
+ field_set = slot_is_hasbit_set(layout, storage, field);
752
+ } else {
753
+ field_set = true;
754
+ }
755
+
568
756
  if (upb_fielddef_containingoneof(field)) {
569
757
  if (*oneof_case != upb_fielddef_number(field)) {
570
- return value_from_default(field);
758
+ return layout_get_default(field);
571
759
  }
572
760
  return native_slot_get(upb_fielddef_type(field),
573
761
  field_type_class(field),
574
762
  memory);
575
763
  } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
576
764
  return *((VALUE *)memory);
765
+ } else if (!field_set) {
766
+ return layout_get_default(field);
577
767
  } else {
578
768
  return native_slot_get(upb_fielddef_type(field),
579
769
  field_type_class(field),
@@ -587,20 +777,28 @@ static void check_repeated_field_type(VALUE val, const upb_fielddef* field) {
587
777
 
588
778
  if (!RB_TYPE_P(val, T_DATA) || !RTYPEDDATA_P(val) ||
589
779
  RTYPEDDATA_TYPE(val) != &RepeatedField_type) {
590
- rb_raise(rb_eTypeError, "Expected repeated field array");
780
+ rb_raise(cTypeError, "Expected repeated field array");
591
781
  }
592
782
 
593
783
  self = ruby_to_RepeatedField(val);
594
784
  if (self->field_type != upb_fielddef_type(field)) {
595
- rb_raise(rb_eTypeError, "Repeated field array has wrong element type");
785
+ rb_raise(cTypeError, "Repeated field array has wrong element type");
596
786
  }
597
787
 
598
- if (self->field_type == UPB_TYPE_MESSAGE ||
599
- self->field_type == UPB_TYPE_ENUM) {
788
+ if (self->field_type == UPB_TYPE_MESSAGE) {
600
789
  if (self->field_type_class !=
601
- get_def_obj(upb_fielddef_subdef(field))) {
602
- rb_raise(rb_eTypeError,
603
- "Repeated field array has wrong message/enum class");
790
+ Descriptor_msgclass(get_def_obj(upb_fielddef_subdef(field)))) {
791
+ rb_raise(cTypeError,
792
+ "Repeated field array has wrong message class");
793
+ }
794
+ }
795
+
796
+
797
+ if (self->field_type == UPB_TYPE_ENUM) {
798
+ if (self->field_type_class !=
799
+ EnumDescriptor_enummodule(get_def_obj(upb_fielddef_subdef(field)))) {
800
+ rb_raise(cTypeError,
801
+ "Repeated field array has wrong enum class");
604
802
  }
605
803
  }
606
804
  }
@@ -612,21 +810,21 @@ static void check_map_field_type(VALUE val, const upb_fielddef* field) {
612
810
 
613
811
  if (!RB_TYPE_P(val, T_DATA) || !RTYPEDDATA_P(val) ||
614
812
  RTYPEDDATA_TYPE(val) != &Map_type) {
615
- rb_raise(rb_eTypeError, "Expected Map instance");
813
+ rb_raise(cTypeError, "Expected Map instance");
616
814
  }
617
815
 
618
816
  self = ruby_to_Map(val);
619
817
  if (self->key_type != upb_fielddef_type(key_field)) {
620
- rb_raise(rb_eTypeError, "Map key type does not match field's key type");
818
+ rb_raise(cTypeError, "Map key type does not match field's key type");
621
819
  }
622
820
  if (self->value_type != upb_fielddef_type(value_field)) {
623
- rb_raise(rb_eTypeError, "Map value type does not match field's value type");
821
+ rb_raise(cTypeError, "Map value type does not match field's value type");
624
822
  }
625
823
  if (upb_fielddef_type(value_field) == UPB_TYPE_MESSAGE ||
626
824
  upb_fielddef_type(value_field) == UPB_TYPE_ENUM) {
627
825
  if (self->value_type_class !=
628
826
  get_def_obj(upb_fielddef_subdef(value_field))) {
629
- rb_raise(rb_eTypeError,
827
+ rb_raise(cTypeError,
630
828
  "Map value type has wrong message/enum class");
631
829
  }
632
830
  }
@@ -659,6 +857,7 @@ void layout_set(MessageLayout* layout,
659
857
  // use native_slot_set_value_and_case(), which ensures that both the value
660
858
  // and case number are altered atomically (w.r.t. the Ruby VM).
661
859
  native_slot_set_value_and_case(
860
+ upb_fielddef_name(field),
662
861
  upb_fielddef_type(field), field_type_class(field),
663
862
  memory, val,
664
863
  oneof_case, upb_fielddef_number(field));
@@ -670,67 +869,25 @@ void layout_set(MessageLayout* layout,
670
869
  check_repeated_field_type(val, field);
671
870
  DEREF(memory, VALUE) = val;
672
871
  } else {
673
- native_slot_set(upb_fielddef_type(field), field_type_class(field),
872
+ native_slot_set(upb_fielddef_name(field),
873
+ upb_fielddef_type(field), field_type_class(field),
674
874
  memory, val);
675
875
  }
876
+
877
+ if (layout->fields[upb_fielddef_index(field)].hasbit !=
878
+ MESSAGE_FIELD_NO_HASBIT) {
879
+ slot_set_hasbit(layout, storage, field);
880
+ }
676
881
  }
677
882
 
678
883
  void layout_init(MessageLayout* layout,
679
884
  void* storage) {
885
+
680
886
  upb_msg_field_iter it;
681
887
  for (upb_msg_field_begin(&it, layout->msgdef);
682
888
  !upb_msg_field_done(&it);
683
889
  upb_msg_field_next(&it)) {
684
- const upb_fielddef* field = upb_msg_iter_field(&it);
685
- void* memory = slot_memory(layout, storage, field);
686
- uint32_t* oneof_case = slot_oneof_case(layout, storage, field);
687
-
688
- if (upb_fielddef_containingoneof(field)) {
689
- memset(memory, 0, NATIVE_SLOT_MAX_SIZE);
690
- *oneof_case = ONEOF_CASE_NONE;
691
- } else if (is_map_field(field)) {
692
- VALUE map = Qnil;
693
-
694
- const upb_fielddef* key_field = map_field_key(field);
695
- const upb_fielddef* value_field = map_field_value(field);
696
- VALUE type_class = field_type_class(value_field);
697
-
698
- if (type_class != Qnil) {
699
- VALUE args[3] = {
700
- fieldtype_to_ruby(upb_fielddef_type(key_field)),
701
- fieldtype_to_ruby(upb_fielddef_type(value_field)),
702
- type_class,
703
- };
704
- map = rb_class_new_instance(3, args, cMap);
705
- } else {
706
- VALUE args[2] = {
707
- fieldtype_to_ruby(upb_fielddef_type(key_field)),
708
- fieldtype_to_ruby(upb_fielddef_type(value_field)),
709
- };
710
- map = rb_class_new_instance(2, args, cMap);
711
- }
712
-
713
- DEREF(memory, VALUE) = map;
714
- } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
715
- VALUE ary = Qnil;
716
-
717
- VALUE type_class = field_type_class(field);
718
-
719
- if (type_class != Qnil) {
720
- VALUE args[2] = {
721
- fieldtype_to_ruby(upb_fielddef_type(field)),
722
- type_class,
723
- };
724
- ary = rb_class_new_instance(2, args, cRepeatedField);
725
- } else {
726
- VALUE args[1] = { fieldtype_to_ruby(upb_fielddef_type(field)) };
727
- ary = rb_class_new_instance(1, args, cRepeatedField);
728
- }
729
-
730
- DEREF(memory, VALUE) = ary;
731
- } else {
732
- native_slot_init(upb_fielddef_type(field), memory);
733
- }
890
+ layout_clear(layout, storage, upb_msg_iter_field(&it));
734
891
  }
735
892
  }
736
893
 
@@ -777,6 +934,11 @@ void layout_dup(MessageLayout* layout, void* to, void* from) {
777
934
  } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
778
935
  DEREF(to_memory, VALUE) = RepeatedField_dup(DEREF(from_memory, VALUE));
779
936
  } else {
937
+ if (field_contains_hasbit(layout, field)) {
938
+ if (!slot_is_hasbit_set(layout, from, field)) continue;
939
+ slot_set_hasbit(layout, to, field);
940
+ }
941
+
780
942
  native_slot_dup(upb_fielddef_type(field), to_memory, from_memory);
781
943
  }
782
944
  }
@@ -806,6 +968,11 @@ void layout_deep_copy(MessageLayout* layout, void* to, void* from) {
806
968
  DEREF(to_memory, VALUE) =
807
969
  RepeatedField_deep_copy(DEREF(from_memory, VALUE));
808
970
  } else {
971
+ if (field_contains_hasbit(layout, field)) {
972
+ if (!slot_is_hasbit_set(layout, from, field)) continue;
973
+ slot_set_hasbit(layout, to, field);
974
+ }
975
+
809
976
  native_slot_deep_copy(upb_fielddef_type(field), to_memory, from_memory);
810
977
  }
811
978
  }
@@ -842,8 +1009,10 @@ VALUE layout_eq(MessageLayout* layout, void* msg1, void* msg2) {
842
1009
  return Qfalse;
843
1010
  }
844
1011
  } else {
845
- if (!native_slot_eq(upb_fielddef_type(field),
846
- msg1_memory, msg2_memory)) {
1012
+ if (slot_is_hasbit_set(layout, msg1, field) !=
1013
+ slot_is_hasbit_set(layout, msg2, field) ||
1014
+ !native_slot_eq(upb_fielddef_type(field),
1015
+ msg1_memory, msg2_memory)) {
847
1016
  return Qfalse;
848
1017
  }
849
1018
  }