google-protobuf 3.0.0.alpha.1.0 → 3.0.0.alpha.1.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.

@@ -139,7 +139,14 @@ int Message_initialize_kwarg(VALUE key, VALUE val, VALUE _self) {
139
139
  "Unknown field name in initialization map entry.");
140
140
  }
141
141
 
142
- if (upb_fielddef_label(f) == UPB_LABEL_REPEATED) {
142
+ if (is_map_field(f)) {
143
+ if (TYPE(val) != T_HASH) {
144
+ rb_raise(rb_eArgError,
145
+ "Expected Hash object as initializer value for map field.");
146
+ }
147
+ VALUE map = layout_get(self->descriptor->layout, Message_data(self), f);
148
+ Map_merge_into_self(map, val);
149
+ } else if (upb_fielddef_label(f) == UPB_LABEL_REPEATED) {
143
150
  if (TYPE(val) != T_ARRAY) {
144
151
  rb_raise(rb_eArgError,
145
152
  "Expected array as initializer value for repeated field.");
@@ -450,13 +457,15 @@ VALUE build_module_from_enumdesc(EnumDescriptor* enumdesc) {
450
457
  * call-seq:
451
458
  * Google::Protobuf.deep_copy(obj) => copy_of_obj
452
459
  *
453
- * Performs a deep copy of either a RepeatedField instance or a message object,
454
- * recursively copying its members.
460
+ * Performs a deep copy of a RepeatedField instance, a Map instance, or a
461
+ * message object, recursively copying its members.
455
462
  */
456
463
  VALUE Google_Protobuf_deep_copy(VALUE self, VALUE obj) {
457
464
  VALUE klass = CLASS_OF(obj);
458
465
  if (klass == cRepeatedField) {
459
466
  return RepeatedField_deep_copy(obj);
467
+ } else if (klass == cMap) {
468
+ return Map_deep_copy(obj);
460
469
  } else {
461
470
  return Message_deep_copy(obj);
462
471
  }
@@ -82,6 +82,7 @@ void Init_protobuf_c() {
82
82
  EnumBuilderContext_register(internal);
83
83
  Builder_register(internal);
84
84
  RepeatedField_register(protobuf);
85
+ Map_register(protobuf);
85
86
 
86
87
  rb_define_singleton_method(protobuf, "encode", Google_Protobuf_encode, 1);
87
88
  rb_define_singleton_method(protobuf, "decode", Google_Protobuf_decode, 2);
@@ -110,6 +110,10 @@ struct Descriptor {
110
110
  const upb_pbdecodermethod* fill_method;
111
111
  const upb_handlers* pb_serialize_handlers;
112
112
  const upb_handlers* json_serialize_handlers;
113
+ // Handlers hold type class references for sub-message fields directly in some
114
+ // cases. We need to keep these rooted because they might otherwise be
115
+ // collected.
116
+ VALUE typeclass_references;
113
117
  };
114
118
 
115
119
  struct FieldDescriptor {
@@ -123,6 +127,7 @@ struct EnumDescriptor {
123
127
 
124
128
  struct MessageBuilderContext {
125
129
  VALUE descriptor;
130
+ VALUE builder;
126
131
  };
127
132
 
128
133
  struct EnumBuilderContext {
@@ -213,10 +218,13 @@ void MessageBuilderContext_free(void* _self);
213
218
  VALUE MessageBuilderContext_alloc(VALUE klass);
214
219
  void MessageBuilderContext_register(VALUE module);
215
220
  MessageBuilderContext* ruby_to_MessageBuilderContext(VALUE value);
216
- VALUE MessageBuilderContext_initialize(VALUE _self, VALUE descriptor);
221
+ VALUE MessageBuilderContext_initialize(VALUE _self,
222
+ VALUE descriptor,
223
+ VALUE builder);
217
224
  VALUE MessageBuilderContext_optional(int argc, VALUE* argv, VALUE _self);
218
225
  VALUE MessageBuilderContext_required(int argc, VALUE* argv, VALUE _self);
219
226
  VALUE MessageBuilderContext_repeated(int argc, VALUE* argv, VALUE _self);
227
+ VALUE MessageBuilderContext_map(int argc, VALUE* argv, VALUE _self);
220
228
 
221
229
  void EnumBuilderContext_mark(void* _self);
222
230
  void EnumBuilderContext_free(void* _self);
@@ -239,6 +247,8 @@ VALUE Builder_finalize_to_pool(VALUE _self, VALUE pool_rb);
239
247
  // Native slot storage abstraction.
240
248
  // -----------------------------------------------------------------------------
241
249
 
250
+ #define NATIVE_SLOT_MAX_SIZE sizeof(void*)
251
+
242
252
  size_t native_slot_size(upb_fieldtype_t type);
243
253
  void native_slot_set(upb_fieldtype_t type,
244
254
  VALUE type_class,
@@ -246,7 +256,7 @@ void native_slot_set(upb_fieldtype_t type,
246
256
  VALUE value);
247
257
  VALUE native_slot_get(upb_fieldtype_t type,
248
258
  VALUE type_class,
249
- void* memory);
259
+ const void* memory);
250
260
  void native_slot_init(upb_fieldtype_t type, void* memory);
251
261
  void native_slot_mark(upb_fieldtype_t type, void* memory);
252
262
  void native_slot_dup(upb_fieldtype_t type, void* to, void* from);
@@ -254,11 +264,27 @@ void native_slot_deep_copy(upb_fieldtype_t type, void* to, void* from);
254
264
  bool native_slot_eq(upb_fieldtype_t type, void* mem1, void* mem2);
255
265
 
256
266
  void native_slot_validate_string_encoding(upb_fieldtype_t type, VALUE value);
267
+ void native_slot_check_int_range_precision(upb_fieldtype_t type, VALUE value);
257
268
 
258
269
  extern rb_encoding* kRubyStringUtf8Encoding;
259
270
  extern rb_encoding* kRubyStringASCIIEncoding;
260
271
  extern rb_encoding* kRubyString8bitEncoding;
261
272
 
273
+ VALUE field_type_class(const upb_fielddef* field);
274
+
275
+ #define MAP_KEY_FIELD 1
276
+ #define MAP_VALUE_FIELD 2
277
+
278
+ // These operate on a map field (i.e., a repeated field of submessages whose
279
+ // submessage type is a map-entry msgdef).
280
+ bool is_map_field(const upb_fielddef* field);
281
+ const upb_fielddef* map_field_key(const upb_fielddef* field);
282
+ const upb_fielddef* map_field_value(const upb_fielddef* field);
283
+
284
+ // These operate on a map-entry msgdef.
285
+ const upb_fielddef* map_entry_key(const upb_msgdef* msgdef);
286
+ const upb_fielddef* map_entry_value(const upb_msgdef* msgdef);
287
+
262
288
  // -----------------------------------------------------------------------------
263
289
  // Repeated field container type.
264
290
  // -----------------------------------------------------------------------------
@@ -282,7 +308,6 @@ extern VALUE cRepeatedField;
282
308
 
283
309
  RepeatedField* ruby_to_RepeatedField(VALUE value);
284
310
 
285
- void RepeatedField_register(VALUE module);
286
311
  VALUE RepeatedField_each(VALUE _self);
287
312
  VALUE RepeatedField_index(VALUE _self, VALUE _index);
288
313
  void* RepeatedField_index_native(VALUE _self, int index);
@@ -302,6 +327,59 @@ VALUE RepeatedField_hash(VALUE _self);
302
327
  VALUE RepeatedField_inspect(VALUE _self);
303
328
  VALUE RepeatedField_plus(VALUE _self, VALUE list);
304
329
 
330
+ // Defined in repeated_field.c; also used by Map.
331
+ void validate_type_class(upb_fieldtype_t type, VALUE klass);
332
+
333
+ // -----------------------------------------------------------------------------
334
+ // Map container type.
335
+ // -----------------------------------------------------------------------------
336
+
337
+ typedef struct {
338
+ upb_fieldtype_t key_type;
339
+ upb_fieldtype_t value_type;
340
+ VALUE value_type_class;
341
+ upb_strtable table;
342
+ } Map;
343
+
344
+ void Map_mark(void* self);
345
+ void Map_free(void* self);
346
+ VALUE Map_alloc(VALUE klass);
347
+ VALUE Map_init(int argc, VALUE* argv, VALUE self);
348
+ void Map_register(VALUE module);
349
+
350
+ extern const rb_data_type_t Map_type;
351
+ extern VALUE cMap;
352
+
353
+ Map* ruby_to_Map(VALUE value);
354
+
355
+ VALUE Map_each(VALUE _self);
356
+ VALUE Map_keys(VALUE _self);
357
+ VALUE Map_values(VALUE _self);
358
+ VALUE Map_index(VALUE _self, VALUE key);
359
+ VALUE Map_index_set(VALUE _self, VALUE key, VALUE value);
360
+ VALUE Map_has_key(VALUE _self, VALUE key);
361
+ VALUE Map_delete(VALUE _self, VALUE key);
362
+ VALUE Map_clear(VALUE _self);
363
+ VALUE Map_length(VALUE _self);
364
+ VALUE Map_dup(VALUE _self);
365
+ VALUE Map_deep_copy(VALUE _self);
366
+ VALUE Map_eq(VALUE _self, VALUE _other);
367
+ VALUE Map_hash(VALUE _self);
368
+ VALUE Map_inspect(VALUE _self);
369
+ VALUE Map_merge(VALUE _self, VALUE hashmap);
370
+ VALUE Map_merge_into_self(VALUE _self, VALUE hashmap);
371
+
372
+ typedef struct {
373
+ Map* self;
374
+ upb_strtable_iter it;
375
+ } Map_iter;
376
+
377
+ void Map_begin(VALUE _self, Map_iter* iter);
378
+ void Map_next(Map_iter* iter);
379
+ bool Map_done(Map_iter* iter);
380
+ VALUE Map_iter_key(Map_iter* iter);
381
+ VALUE Map_iter_value(Map_iter* iter);
382
+
305
383
  // -----------------------------------------------------------------------------
306
384
  // Message layout / storage.
307
385
  // -----------------------------------------------------------------------------
@@ -315,7 +393,7 @@ struct MessageLayout {
315
393
  MessageLayout* create_layout(const upb_msgdef* msgdef);
316
394
  void free_layout(MessageLayout* layout);
317
395
  VALUE layout_get(MessageLayout* layout,
318
- void* storage,
396
+ const void* storage,
319
397
  const upb_fielddef* field);
320
398
  void layout_set(MessageLayout* layout,
321
399
  void* storage,
@@ -324,6 +324,10 @@ VALUE RepeatedField_deep_copy(VALUE _self) {
324
324
  * element types are equal, their lengths are equal, and each element is equal.
325
325
  * Elements are compared as per normal Ruby semantics, by calling their :==
326
326
  * methods (or performing a more efficient comparison for primitive types).
327
+ *
328
+ * Repeated fields with dissimilar element types are never equal, even if value
329
+ * comparison (for example, between integers and floats) would have otherwise
330
+ * indicated that every element has equal value.
327
331
  */
328
332
  VALUE RepeatedField_eq(VALUE _self, VALUE _other) {
329
333
  if (_self == _other) {
@@ -458,7 +462,7 @@ VALUE RepeatedField_plus(VALUE _self, VALUE list) {
458
462
  return dupped;
459
463
  }
460
464
 
461
- static void validate_type_class(upb_fieldtype_t type, VALUE klass) {
465
+ void validate_type_class(upb_fieldtype_t type, VALUE klass) {
462
466
  if (rb_iv_get(klass, kDescriptorInstanceVar) == Qnil) {
463
467
  rb_raise(rb_eArgError,
464
468
  "Type class has no descriptor. Please pass a "
@@ -57,7 +57,17 @@ size_t native_slot_size(upb_fieldtype_t type) {
57
57
  }
58
58
  }
59
59
 
60
- static void check_int_range_precision(upb_fieldtype_t type, VALUE val) {
60
+ static bool is_ruby_num(VALUE value) {
61
+ return (TYPE(value) == T_FLOAT ||
62
+ TYPE(value) == T_FIXNUM ||
63
+ TYPE(value) == T_BIGNUM);
64
+ }
65
+
66
+ void native_slot_check_int_range_precision(upb_fieldtype_t type, VALUE val) {
67
+ if (!is_ruby_num(val)) {
68
+ rb_raise(rb_eTypeError, "Expected number type for integral field.");
69
+ }
70
+
61
71
  // NUM2{INT,UINT,LL,ULL} macros do the appropriate range checks on upper
62
72
  // bound; we just need to do precision checks (i.e., disallow rounding) and
63
73
  // check for < 0 on unsigned types.
@@ -76,12 +86,6 @@ static void check_int_range_precision(upb_fieldtype_t type, VALUE val) {
76
86
  }
77
87
  }
78
88
 
79
- static bool is_ruby_num(VALUE value) {
80
- return (TYPE(value) == T_FLOAT ||
81
- TYPE(value) == T_FIXNUM ||
82
- TYPE(value) == T_BIGNUM);
83
- }
84
-
85
89
  void native_slot_validate_string_encoding(upb_fieldtype_t type, VALUE value) {
86
90
  bool bad_encoding = false;
87
91
  rb_encoding* string_encoding = rb_enc_from_index(ENCODING_GET(value));
@@ -156,14 +160,14 @@ void native_slot_set(upb_fieldtype_t type, VALUE type_class,
156
160
  int32_t int_val = 0;
157
161
  if (TYPE(value) == T_SYMBOL) {
158
162
  // Ensure that the given symbol exists in the enum module.
159
- VALUE lookup = rb_const_get(type_class, SYM2ID(value));
163
+ VALUE lookup = rb_funcall(type_class, rb_intern("resolve"), 1, value);
160
164
  if (lookup == Qnil) {
161
165
  rb_raise(rb_eRangeError, "Unknown symbol value for enum field.");
162
166
  } else {
163
167
  int_val = NUM2INT(lookup);
164
168
  }
165
169
  } else {
166
- check_int_range_precision(UPB_TYPE_INT32, value);
170
+ native_slot_check_int_range_precision(UPB_TYPE_INT32, value);
167
171
  int_val = NUM2INT(value);
168
172
  }
169
173
  DEREF(memory, int32_t) = int_val;
@@ -173,10 +177,7 @@ void native_slot_set(upb_fieldtype_t type, VALUE type_class,
173
177
  case UPB_TYPE_INT64:
174
178
  case UPB_TYPE_UINT32:
175
179
  case UPB_TYPE_UINT64:
176
- if (!is_ruby_num(value)) {
177
- rb_raise(rb_eTypeError, "Expected number type for integral field.");
178
- }
179
- check_int_range_precision(type, value);
180
+ native_slot_check_int_range_precision(type, value);
180
181
  switch (type) {
181
182
  case UPB_TYPE_INT32:
182
183
  DEREF(memory, int32_t) = NUM2INT(value);
@@ -199,7 +200,9 @@ void native_slot_set(upb_fieldtype_t type, VALUE type_class,
199
200
  }
200
201
  }
201
202
 
202
- VALUE native_slot_get(upb_fieldtype_t type, VALUE type_class, void* memory) {
203
+ VALUE native_slot_get(upb_fieldtype_t type,
204
+ VALUE type_class,
205
+ const void* memory) {
203
206
  switch (type) {
204
207
  case UPB_TYPE_FLOAT:
205
208
  return DBL2NUM(DEREF(memory, float));
@@ -210,7 +213,7 @@ VALUE native_slot_get(upb_fieldtype_t type, VALUE type_class, void* memory) {
210
213
  case UPB_TYPE_STRING:
211
214
  case UPB_TYPE_BYTES:
212
215
  case UPB_TYPE_MESSAGE:
213
- return *((VALUE *)memory);
216
+ return DEREF(memory, VALUE);
214
217
  case UPB_TYPE_ENUM: {
215
218
  int32_t val = DEREF(memory, int32_t);
216
219
  VALUE symbol = enum_lookup(type_class, INT2NUM(val));
@@ -246,8 +249,9 @@ void native_slot_init(upb_fieldtype_t type, void* memory) {
246
249
  break;
247
250
  case UPB_TYPE_STRING:
248
251
  case UPB_TYPE_BYTES:
249
- // TODO(cfallin): set encoding appropriately
250
252
  DEREF(memory, VALUE) = rb_str_new2("");
253
+ rb_enc_associate(DEREF(memory, VALUE), (type == UPB_TYPE_BYTES) ?
254
+ kRubyString8bitEncoding : kRubyStringUtf8Encoding);
251
255
  break;
252
256
  case UPB_TYPE_MESSAGE:
253
257
  DEREF(memory, VALUE) = Qnil;
@@ -321,6 +325,43 @@ bool native_slot_eq(upb_fieldtype_t type, void* mem1, void* mem2) {
321
325
  }
322
326
  }
323
327
 
328
+ // -----------------------------------------------------------------------------
329
+ // Map field utilities.
330
+ // -----------------------------------------------------------------------------
331
+
332
+ bool is_map_field(const upb_fielddef* field) {
333
+ if (upb_fielddef_label(field) != UPB_LABEL_REPEATED ||
334
+ upb_fielddef_type(field) != UPB_TYPE_MESSAGE) {
335
+ return false;
336
+ }
337
+ const upb_msgdef* subdef = upb_fielddef_msgsubdef(field);
338
+ return upb_msgdef_mapentry(subdef);
339
+ }
340
+
341
+ const upb_fielddef* map_field_key(const upb_fielddef* field) {
342
+ assert(is_map_field(field));
343
+ const upb_msgdef* subdef = upb_fielddef_msgsubdef(field);
344
+ return map_entry_key(subdef);
345
+ }
346
+
347
+ const upb_fielddef* map_field_value(const upb_fielddef* field) {
348
+ assert(is_map_field(field));
349
+ const upb_msgdef* subdef = upb_fielddef_msgsubdef(field);
350
+ return map_entry_value(subdef);
351
+ }
352
+
353
+ const upb_fielddef* map_entry_key(const upb_msgdef* msgdef) {
354
+ const upb_fielddef* key_field = upb_msgdef_itof(msgdef, MAP_KEY_FIELD);
355
+ assert(key_field != NULL);
356
+ return key_field;
357
+ }
358
+
359
+ const upb_fielddef* map_entry_value(const upb_msgdef* msgdef) {
360
+ const upb_fielddef* value_field = upb_msgdef_itof(msgdef, MAP_VALUE_FIELD);
361
+ assert(value_field != NULL);
362
+ return value_field;
363
+ }
364
+
324
365
  // -----------------------------------------------------------------------------
325
366
  // Memory layout management.
326
367
  // -----------------------------------------------------------------------------
@@ -334,9 +375,12 @@ MessageLayout* create_layout(const upb_msgdef* msgdef) {
334
375
  size_t off = 0;
335
376
  for (upb_msg_begin(&it, msgdef); !upb_msg_done(&it); upb_msg_next(&it)) {
336
377
  const upb_fielddef* field = upb_msg_iter_field(&it);
337
- size_t field_size =
338
- (upb_fielddef_label(field) == UPB_LABEL_REPEATED) ?
339
- sizeof(VALUE) : native_slot_size(upb_fielddef_type(field));
378
+ size_t field_size = 0;
379
+ if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
380
+ field_size = sizeof(VALUE);
381
+ } else {
382
+ field_size = native_slot_size(upb_fielddef_type(field));
383
+ }
340
384
  // align current offset
341
385
  off = (off + field_size - 1) & ~(field_size - 1);
342
386
  layout->offsets[upb_fielddef_index(field)] = off;
@@ -357,7 +401,7 @@ void free_layout(MessageLayout* layout) {
357
401
  xfree(layout);
358
402
  }
359
403
 
360
- static VALUE get_type_class(const upb_fielddef* field) {
404
+ VALUE field_type_class(const upb_fielddef* field) {
361
405
  VALUE type_class = Qnil;
362
406
  if (upb_fielddef_type(field) == UPB_TYPE_MESSAGE) {
363
407
  VALUE submsgdesc =
@@ -372,7 +416,7 @@ static VALUE get_type_class(const upb_fielddef* field) {
372
416
  }
373
417
 
374
418
  VALUE layout_get(MessageLayout* layout,
375
- void* storage,
419
+ const void* storage,
376
420
  const upb_fielddef* field) {
377
421
  void* memory = ((uint8_t *)storage) +
378
422
  layout->offsets[upb_fielddef_index(field)];
@@ -380,7 +424,7 @@ VALUE layout_get(MessageLayout* layout,
380
424
  return *((VALUE *)memory);
381
425
  } else {
382
426
  return native_slot_get(upb_fielddef_type(field),
383
- get_type_class(field),
427
+ field_type_class(field),
384
428
  memory);
385
429
  }
386
430
  }
@@ -398,9 +442,8 @@ static void check_repeated_field_type(VALUE val, const upb_fielddef* field) {
398
442
  rb_raise(rb_eTypeError, "Repeated field array has wrong element type");
399
443
  }
400
444
 
401
- if (upb_fielddef_type(field) == UPB_TYPE_MESSAGE ||
402
- upb_fielddef_type(field) == UPB_TYPE_ENUM) {
403
- RepeatedField* self = ruby_to_RepeatedField(val);
445
+ if (self->field_type == UPB_TYPE_MESSAGE ||
446
+ self->field_type == UPB_TYPE_ENUM) {
404
447
  if (self->field_type_class !=
405
448
  get_def_obj(upb_fielddef_subdef(field))) {
406
449
  rb_raise(rb_eTypeError,
@@ -409,17 +452,48 @@ static void check_repeated_field_type(VALUE val, const upb_fielddef* field) {
409
452
  }
410
453
  }
411
454
 
455
+ static void check_map_field_type(VALUE val, const upb_fielddef* field) {
456
+ assert(is_map_field(field));
457
+ const upb_fielddef* key_field = map_field_key(field);
458
+ const upb_fielddef* value_field = map_field_value(field);
459
+
460
+ if (!RB_TYPE_P(val, T_DATA) || !RTYPEDDATA_P(val) ||
461
+ RTYPEDDATA_TYPE(val) != &Map_type) {
462
+ rb_raise(rb_eTypeError, "Expected Map instance");
463
+ }
464
+
465
+ Map* self = ruby_to_Map(val);
466
+ if (self->key_type != upb_fielddef_type(key_field)) {
467
+ rb_raise(rb_eTypeError, "Map key type does not match field's key type");
468
+ }
469
+ if (self->value_type != upb_fielddef_type(value_field)) {
470
+ rb_raise(rb_eTypeError, "Map value type does not match field's value type");
471
+ }
472
+ if (upb_fielddef_type(value_field) == UPB_TYPE_MESSAGE ||
473
+ upb_fielddef_type(value_field) == UPB_TYPE_ENUM) {
474
+ if (self->value_type_class !=
475
+ get_def_obj(upb_fielddef_subdef(value_field))) {
476
+ rb_raise(rb_eTypeError,
477
+ "Map value type has wrong message/enum class");
478
+ }
479
+ }
480
+ }
481
+
482
+
412
483
  void layout_set(MessageLayout* layout,
413
484
  void* storage,
414
485
  const upb_fielddef* field,
415
486
  VALUE val) {
416
487
  void* memory = ((uint8_t *)storage) +
417
488
  layout->offsets[upb_fielddef_index(field)];
418
- if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
489
+ if (is_map_field(field)) {
490
+ check_map_field_type(val, field);
491
+ DEREF(memory, VALUE) = val;
492
+ } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
419
493
  check_repeated_field_type(val, field);
420
- *((VALUE *)memory) = val;
494
+ DEREF(memory, VALUE) = val;
421
495
  } else {
422
- native_slot_set(upb_fielddef_type(field), get_type_class(field),
496
+ native_slot_set(upb_fielddef_type(field), field_type_class(field),
423
497
  memory, val);
424
498
  }
425
499
  }
@@ -434,9 +508,34 @@ void layout_init(MessageLayout* layout,
434
508
  void* memory = ((uint8_t *)storage) +
435
509
  layout->offsets[upb_fielddef_index(field)];
436
510
 
437
- if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
511
+ if (is_map_field(field)) {
512
+ VALUE map = Qnil;
513
+
514
+ const upb_fielddef* key_field = map_field_key(field);
515
+ const upb_fielddef* value_field = map_field_value(field);
516
+ VALUE type_class = field_type_class(value_field);
517
+
518
+ if (type_class != Qnil) {
519
+ VALUE args[3] = {
520
+ fieldtype_to_ruby(upb_fielddef_type(key_field)),
521
+ fieldtype_to_ruby(upb_fielddef_type(value_field)),
522
+ type_class,
523
+ };
524
+ map = rb_class_new_instance(3, args, cMap);
525
+ } else {
526
+ VALUE args[2] = {
527
+ fieldtype_to_ruby(upb_fielddef_type(key_field)),
528
+ fieldtype_to_ruby(upb_fielddef_type(value_field)),
529
+ };
530
+ map = rb_class_new_instance(2, args, cMap);
531
+ }
532
+
533
+ DEREF(memory, VALUE) = map;
534
+ } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
438
535
  VALUE ary = Qnil;
439
- VALUE type_class = get_type_class(field);
536
+
537
+ VALUE type_class = field_type_class(field);
538
+
440
539
  if (type_class != Qnil) {
441
540
  VALUE args[2] = {
442
541
  fieldtype_to_ruby(upb_fielddef_type(field)),
@@ -447,7 +546,8 @@ void layout_init(MessageLayout* layout,
447
546
  VALUE args[1] = { fieldtype_to_ruby(upb_fielddef_type(field)) };
448
547
  ary = rb_class_new_instance(1, args, cRepeatedField);
449
548
  }
450
- *((VALUE *)memory) = ary;
549
+
550
+ DEREF(memory, VALUE) = ary;
451
551
  } else {
452
552
  native_slot_init(upb_fielddef_type(field), memory);
453
553
  }
@@ -464,7 +564,7 @@ void layout_mark(MessageLayout* layout, void* storage) {
464
564
  layout->offsets[upb_fielddef_index(field)];
465
565
 
466
566
  if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
467
- rb_gc_mark(*((VALUE *)memory));
567
+ rb_gc_mark(DEREF(memory, VALUE));
468
568
  } else {
469
569
  native_slot_mark(upb_fielddef_type(field), memory);
470
570
  }
@@ -482,8 +582,10 @@ void layout_dup(MessageLayout* layout, void* to, void* from) {
482
582
  void* from_memory = ((uint8_t *)from) +
483
583
  layout->offsets[upb_fielddef_index(field)];
484
584
 
485
- if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
486
- *((VALUE *)to_memory) = RepeatedField_dup(*((VALUE *)from_memory));
585
+ if (is_map_field(field)) {
586
+ DEREF(to_memory, VALUE) = Map_dup(DEREF(from_memory, VALUE));
587
+ } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
588
+ DEREF(to_memory, VALUE) = RepeatedField_dup(DEREF(from_memory, VALUE));
487
589
  } else {
488
590
  native_slot_dup(upb_fielddef_type(field), to_memory, from_memory);
489
591
  }
@@ -501,8 +603,12 @@ void layout_deep_copy(MessageLayout* layout, void* to, void* from) {
501
603
  void* from_memory = ((uint8_t *)from) +
502
604
  layout->offsets[upb_fielddef_index(field)];
503
605
 
504
- if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
505
- *((VALUE *)to_memory) = RepeatedField_deep_copy(*((VALUE *)from_memory));
606
+ if (is_map_field(field)) {
607
+ DEREF(to_memory, VALUE) =
608
+ Map_deep_copy(DEREF(from_memory, VALUE));
609
+ } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
610
+ DEREF(to_memory, VALUE) =
611
+ RepeatedField_deep_copy(DEREF(from_memory, VALUE));
506
612
  } else {
507
613
  native_slot_deep_copy(upb_fielddef_type(field), to_memory, from_memory);
508
614
  }
@@ -520,11 +626,12 @@ VALUE layout_eq(MessageLayout* layout, void* msg1, void* msg2) {
520
626
  void* msg2_memory = ((uint8_t *)msg2) +
521
627
  layout->offsets[upb_fielddef_index(field)];
522
628
 
523
- if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
524
- if (RepeatedField_eq(*((VALUE *)msg1_memory),
525
- *((VALUE *)msg2_memory)) == Qfalse) {
526
- return Qfalse;
527
- }
629
+ if (is_map_field(field)) {
630
+ return Map_eq(DEREF(msg1_memory, VALUE),
631
+ DEREF(msg2_memory, VALUE));
632
+ } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
633
+ return RepeatedField_eq(DEREF(msg1_memory, VALUE),
634
+ DEREF(msg2_memory, VALUE));
528
635
  } else {
529
636
  if (!native_slot_eq(upb_fielddef_type(field),
530
637
  msg1_memory, msg2_memory)) {