google-protobuf 3.2.0 → 3.9.1

Sign up to get free protection for your applications and to get access to all the features.

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
  }