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.

checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- OWE5ZmI5M2U5MjEyNzljNzllZWQ2N2NlZjMyMDg0Y2UyNDk0MWYzMQ==
4
+ ZGYwNjhlZGZjOTE1ZjM4YmE2ZTAzYTZlOTZiZmZmMDFjMmQ4MjJiMw==
5
5
  data.tar.gz: !binary |-
6
- NmRjOWI5YTRhYmJmNjlkN2U5OGViYmNiNzVkNDRhODAxOWFhYzE4OQ==
6
+ YzJhNmY2MjZkNDQzN2E2MTk4MGNjYzIxODAwMTQ1ZThkNjMwZTg3Mg==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- ZWUwYzIzODQwZDdjMzc3M2NmOGVhN2M0NWFlYzczYjRlZDg1OWViMTAzZDkz
10
- M2UzNDg2YTcwYzVlY2ZiNmNkMDMwMjg0YTUzNGM1MGRjOTVjNjVhZDA0NmJi
11
- MjY4NWY1Y2VkYzZiMzFhOWM4ODRiM2EwYTJhZjM1NDEwODVmZGQ=
9
+ MzMwMzVhNjkzNzA0NTc3NTJhNDVlOTNlMTgzZjJkNzA3NGE4ZDk2NjRlYmNi
10
+ OTBhMmQ4M2Y1YWZiYzc0Njc5OThmODliYzQ4YTA5YWM0MTk3MGQyZTA4YWYy
11
+ MjZiNDJmNjA4N2I4MDgzZjM5Y2IwMGViM2U4MjM5ZWE4NDBhZjI=
12
12
  data.tar.gz: !binary |-
13
- N2E3OTFlMDNmYWZkNjQyZjM2ODk4YmE2YmU5MDczYzg2N2I4NTJhNzRjNmIw
14
- MWNhNDU2ZWIwZWMyOTcyMmIzMWQxYjMyM2FlZTU0NDEwYzI3ZDk1Yzk4MzEw
15
- YzUzNmFlZThkODNiNmE3ZTdjNmE2ZDFmMGYzYzg0NTA2NTM3MDQ=
13
+ NDhhZmI5M2IxN2Q5OTc2MWQ5YzY5Mzk3MzU2ODZjYzJiMTA4OTFlYTA3MzBj
14
+ MGE4YTg1NmVlMmViNTUzZDI5ZjQ4ZTE2ZDkxZDI5OGQxMDlmMTgzN2E2M2Qw
15
+ MWY4NGQ3YWVjZTIxY2Y3Y2FlNjMyODFjNDc0NDgyOTljN2E0NWY=
@@ -226,6 +226,7 @@ DEFINE_CLASS(Descriptor, "Google::Protobuf::Descriptor");
226
226
  void Descriptor_mark(void* _self) {
227
227
  Descriptor* self = _self;
228
228
  rb_gc_mark(self->klass);
229
+ rb_gc_mark(self->typeclass_references);
229
230
  }
230
231
 
231
232
  void Descriptor_free(void* _self) {
@@ -270,6 +271,7 @@ VALUE Descriptor_alloc(VALUE klass) {
270
271
  self->fill_method = NULL;
271
272
  self->pb_serialize_handlers = NULL;
272
273
  self->json_serialize_handlers = NULL;
274
+ self->typeclass_references = rb_ary_new();
273
275
  return ret;
274
276
  }
275
277
 
@@ -923,6 +925,7 @@ DEFINE_CLASS(MessageBuilderContext,
923
925
  void MessageBuilderContext_mark(void* _self) {
924
926
  MessageBuilderContext* self = _self;
925
927
  rb_gc_mark(self->descriptor);
928
+ rb_gc_mark(self->builder);
926
929
  }
927
930
 
928
931
  void MessageBuilderContext_free(void* _self) {
@@ -935,6 +938,7 @@ VALUE MessageBuilderContext_alloc(VALUE klass) {
935
938
  VALUE ret = TypedData_Wrap_Struct(
936
939
  klass, &_MessageBuilderContext_type, self);
937
940
  self->descriptor = Qnil;
941
+ self->builder = Qnil;
938
942
  return ret;
939
943
  }
940
944
 
@@ -943,24 +947,29 @@ void MessageBuilderContext_register(VALUE module) {
943
947
  module, "MessageBuilderContext", rb_cObject);
944
948
  rb_define_alloc_func(klass, MessageBuilderContext_alloc);
945
949
  rb_define_method(klass, "initialize",
946
- MessageBuilderContext_initialize, 1);
950
+ MessageBuilderContext_initialize, 2);
947
951
  rb_define_method(klass, "optional", MessageBuilderContext_optional, -1);
948
952
  rb_define_method(klass, "required", MessageBuilderContext_required, -1);
949
953
  rb_define_method(klass, "repeated", MessageBuilderContext_repeated, -1);
954
+ rb_define_method(klass, "map", MessageBuilderContext_map, -1);
950
955
  cMessageBuilderContext = klass;
951
956
  rb_gc_register_address(&cMessageBuilderContext);
952
957
  }
953
958
 
954
959
  /*
955
960
  * call-seq:
956
- * MessageBuilderContext.new(desc) => context
961
+ * MessageBuilderContext.new(desc, builder) => context
957
962
  *
958
- * Create a new builder context around the given message descriptor. This class
959
- * is intended to serve as a DSL context to be used with #instance_eval.
963
+ * Create a new message builder context around the given message descriptor and
964
+ * builder context. This class is intended to serve as a DSL context to be used
965
+ * with #instance_eval.
960
966
  */
961
- VALUE MessageBuilderContext_initialize(VALUE _self, VALUE msgdef) {
967
+ VALUE MessageBuilderContext_initialize(VALUE _self,
968
+ VALUE msgdef,
969
+ VALUE builder) {
962
970
  DEFINE_SELF(MessageBuilderContext, self, _self);
963
971
  self->descriptor = msgdef;
972
+ self->builder = builder;
964
973
  return Qnil;
965
974
  }
966
975
 
@@ -1065,6 +1074,97 @@ VALUE MessageBuilderContext_repeated(int argc, VALUE* argv, VALUE _self) {
1065
1074
  name, type, number, type_class);
1066
1075
  }
1067
1076
 
1077
+ /*
1078
+ * call-seq:
1079
+ * MessageBuilderContext.map(name, key_type, value_type, number,
1080
+ * value_type_class = nil)
1081
+ *
1082
+ * Defines a new map field on this message type with the given key and value
1083
+ * types, tag number, and type class (for message and enum value types). The key
1084
+ * type must be :int32/:uint32/:int64/:uint64, :bool, or :string. The value type
1085
+ * type must be a Ruby symbol (as accepted by FieldDescriptor#type=) and the
1086
+ * type_class must be a string, if present (as accepted by
1087
+ * FieldDescriptor#submsg_name=).
1088
+ */
1089
+ VALUE MessageBuilderContext_map(int argc, VALUE* argv, VALUE _self) {
1090
+ DEFINE_SELF(MessageBuilderContext, self, _self);
1091
+
1092
+ if (argc < 4) {
1093
+ rb_raise(rb_eArgError, "Expected at least 4 arguments.");
1094
+ }
1095
+ VALUE name = argv[0];
1096
+ VALUE key_type = argv[1];
1097
+ VALUE value_type = argv[2];
1098
+ VALUE number = argv[3];
1099
+ VALUE type_class = (argc > 4) ? argv[4] : Qnil;
1100
+
1101
+ // Validate the key type. We can't accept enums, messages, or floats/doubles
1102
+ // as map keys. (We exclude these explicitly, and the field-descriptor setter
1103
+ // below then ensures that the type is one of the remaining valid options.)
1104
+ if (SYM2ID(key_type) == rb_intern("float") ||
1105
+ SYM2ID(key_type) == rb_intern("double") ||
1106
+ SYM2ID(key_type) == rb_intern("enum") ||
1107
+ SYM2ID(key_type) == rb_intern("message")) {
1108
+ rb_raise(rb_eArgError,
1109
+ "Cannot add a map field with a float, double, enum, or message "
1110
+ "type.");
1111
+ }
1112
+
1113
+ // Create a new message descriptor for the map entry message, and create a
1114
+ // repeated submessage field here with that type.
1115
+ VALUE mapentry_desc = rb_class_new_instance(0, NULL, cDescriptor);
1116
+ VALUE mapentry_desc_name = rb_funcall(self->descriptor, rb_intern("name"), 0);
1117
+ mapentry_desc_name = rb_str_cat2(mapentry_desc_name, "_MapEntry_");
1118
+ mapentry_desc_name = rb_str_cat2(mapentry_desc_name,
1119
+ rb_id2name(SYM2ID(name)));
1120
+ Descriptor_name_set(mapentry_desc, mapentry_desc_name);
1121
+
1122
+ // The 'mapentry' attribute has no Ruby setter because we do not want the user
1123
+ // attempting to DIY the setup below; we want to ensure that the fields are
1124
+ // correct. So we reach into the msgdef here to set the bit manually.
1125
+ Descriptor* mapentry_desc_self = ruby_to_Descriptor(mapentry_desc);
1126
+ upb_msgdef_setmapentry((upb_msgdef*)mapentry_desc_self->msgdef, true);
1127
+
1128
+ // optional <type> key = 1;
1129
+ VALUE key_field = rb_class_new_instance(0, NULL, cFieldDescriptor);
1130
+ FieldDescriptor_name_set(key_field, rb_str_new2("key"));
1131
+ FieldDescriptor_label_set(key_field, ID2SYM(rb_intern("optional")));
1132
+ FieldDescriptor_number_set(key_field, INT2NUM(1));
1133
+ FieldDescriptor_type_set(key_field, key_type);
1134
+ Descriptor_add_field(mapentry_desc, key_field);
1135
+
1136
+ // optional <type> value = 2;
1137
+ VALUE value_field = rb_class_new_instance(0, NULL, cFieldDescriptor);
1138
+ FieldDescriptor_name_set(value_field, rb_str_new2("value"));
1139
+ FieldDescriptor_label_set(value_field, ID2SYM(rb_intern("optional")));
1140
+ FieldDescriptor_number_set(value_field, INT2NUM(2));
1141
+ FieldDescriptor_type_set(value_field, value_type);
1142
+ if (type_class != Qnil) {
1143
+ VALUE submsg_name = rb_str_new2("."); // prepend '.' to make name absolute.
1144
+ submsg_name = rb_str_append(submsg_name, type_class);
1145
+ FieldDescriptor_submsg_name_set(value_field, submsg_name);
1146
+ }
1147
+ Descriptor_add_field(mapentry_desc, value_field);
1148
+
1149
+ // Add the map-entry message type to the current builder, and use the type to
1150
+ // create the map field itself.
1151
+ Builder* builder_self = ruby_to_Builder(self->builder);
1152
+ rb_ary_push(builder_self->pending_list, mapentry_desc);
1153
+
1154
+ VALUE map_field = rb_class_new_instance(0, NULL, cFieldDescriptor);
1155
+ VALUE name_str = rb_str_new2(rb_id2name(SYM2ID(name)));
1156
+ FieldDescriptor_name_set(map_field, name_str);
1157
+ FieldDescriptor_number_set(map_field, number);
1158
+ FieldDescriptor_label_set(map_field, ID2SYM(rb_intern("repeated")));
1159
+ FieldDescriptor_type_set(map_field, ID2SYM(rb_intern("message")));
1160
+ VALUE submsg_name = rb_str_new2("."); // prepend '.' to make name absolute.
1161
+ submsg_name = rb_str_append(submsg_name, mapentry_desc_name);
1162
+ FieldDescriptor_submsg_name_set(map_field, submsg_name);
1163
+ Descriptor_add_field(self->descriptor, map_field);
1164
+
1165
+ return Qnil;
1166
+ }
1167
+
1068
1168
  // -----------------------------------------------------------------------------
1069
1169
  // EnumBuilderContext.
1070
1170
  // -----------------------------------------------------------------------------
@@ -1190,7 +1290,8 @@ void Builder_register(VALUE module) {
1190
1290
  VALUE Builder_add_message(VALUE _self, VALUE name) {
1191
1291
  DEFINE_SELF(Builder, self, _self);
1192
1292
  VALUE msgdef = rb_class_new_instance(0, NULL, cDescriptor);
1193
- VALUE ctx = rb_class_new_instance(1, &msgdef, cMessageBuilderContext);
1293
+ VALUE args[2] = { msgdef, _self };
1294
+ VALUE ctx = rb_class_new_instance(2, args, cMessageBuilderContext);
1194
1295
  VALUE block = rb_block_proc();
1195
1296
  rb_funcall(msgdef, rb_intern("name="), 1, name);
1196
1297
  rb_funcall_with_block(ctx, rb_intern("instance_eval"), 0, NULL, block);
@@ -64,7 +64,7 @@ static const void *newsubmsghandlerdata(upb_handlers* h, uint32_t ofs,
64
64
  static void *startseq_handler(void* closure, const void* hd) {
65
65
  MessageHeader* msg = closure;
66
66
  const size_t *ofs = hd;
67
- return (void*)DEREF(Message_data(msg), *ofs, VALUE);
67
+ return (void*)DEREF(msg, *ofs, VALUE);
68
68
  }
69
69
 
70
70
  // Handlers that append primitive values to a repeated field (a regular Ruby
@@ -115,7 +115,7 @@ static void* str_handler(void *closure,
115
115
  const size_t *ofs = hd;
116
116
  VALUE str = rb_str_new2("");
117
117
  rb_enc_associate(str, kRubyStringUtf8Encoding);
118
- DEREF(Message_data(msg), *ofs, VALUE) = str;
118
+ DEREF(msg, *ofs, VALUE) = str;
119
119
  return (void*)str;
120
120
  }
121
121
 
@@ -127,7 +127,7 @@ static void* bytes_handler(void *closure,
127
127
  const size_t *ofs = hd;
128
128
  VALUE str = rb_str_new2("");
129
129
  rb_enc_associate(str, kRubyString8bitEncoding);
130
- DEREF(Message_data(msg), *ofs, VALUE) = str;
130
+ DEREF(msg, *ofs, VALUE) = str;
131
131
  return (void*)str;
132
132
  }
133
133
 
@@ -163,20 +163,237 @@ static void *submsg_handler(void *closure, const void *hd) {
163
163
  get_def_obj((void*)submsgdata->md);
164
164
  VALUE subklass = Descriptor_msgclass(subdesc);
165
165
 
166
- if (DEREF(Message_data(msg), submsgdata->ofs, VALUE) == Qnil) {
167
- DEREF(Message_data(msg), submsgdata->ofs, VALUE) =
166
+ if (DEREF(msg, submsgdata->ofs, VALUE) == Qnil) {
167
+ DEREF(msg, submsgdata->ofs, VALUE) =
168
168
  rb_class_new_instance(0, NULL, subklass);
169
169
  }
170
170
 
171
- VALUE submsg_rb = DEREF(Message_data(msg), submsgdata->ofs, VALUE);
171
+ VALUE submsg_rb = DEREF(msg, submsgdata->ofs, VALUE);
172
172
  MessageHeader* submsg;
173
173
  TypedData_Get_Struct(submsg_rb, MessageHeader, &Message_type, submsg);
174
174
  return submsg;
175
175
  }
176
176
 
177
+ // Handler data for startmap/endmap handlers.
178
+ typedef struct {
179
+ size_t ofs;
180
+ upb_fieldtype_t key_field_type;
181
+ upb_fieldtype_t value_field_type;
182
+ VALUE value_field_typeclass;
183
+ } map_handlerdata_t;
184
+
185
+ // Temporary frame for map parsing: at the beginning of a map entry message, a
186
+ // submsg handler allocates a frame to hold (i) a reference to the Map object
187
+ // into which this message will be inserted and (ii) storage slots to
188
+ // temporarily hold the key and value for this map entry until the end of the
189
+ // submessage. When the submessage ends, another handler is called to insert the
190
+ // value into the map.
191
+ typedef struct {
192
+ VALUE map;
193
+ char key_storage[NATIVE_SLOT_MAX_SIZE];
194
+ char value_storage[NATIVE_SLOT_MAX_SIZE];
195
+ } map_parse_frame_t;
196
+
197
+ // Handler to begin a map entry: allocates a temporary frame. This is the
198
+ // 'startsubmsg' handler on the msgdef that contains the map field.
199
+ static void *startmapentry_handler(void *closure, const void *hd) {
200
+ MessageHeader* msg = closure;
201
+ const map_handlerdata_t* mapdata = hd;
202
+ VALUE map_rb = DEREF(msg, mapdata->ofs, VALUE);
203
+
204
+ map_parse_frame_t* frame = ALLOC(map_parse_frame_t);
205
+ frame->map = map_rb;
206
+
207
+ native_slot_init(mapdata->key_field_type, &frame->key_storage);
208
+ native_slot_init(mapdata->value_field_type, &frame->value_storage);
209
+
210
+ return frame;
211
+ }
212
+
213
+ // Handler to end a map entry: inserts the value defined during the message into
214
+ // the map. This is the 'endmsg' handler on the map entry msgdef.
215
+ static bool endmap_handler(void *closure, const void *hd, upb_status* s) {
216
+ map_parse_frame_t* frame = closure;
217
+ const map_handlerdata_t* mapdata = hd;
218
+
219
+ VALUE key = native_slot_get(
220
+ mapdata->key_field_type, Qnil,
221
+ &frame->key_storage);
222
+ VALUE value = native_slot_get(
223
+ mapdata->value_field_type, mapdata->value_field_typeclass,
224
+ &frame->value_storage);
225
+
226
+ Map_index_set(frame->map, key, value);
227
+ free(frame);
228
+
229
+ return true;
230
+ }
231
+
232
+ // Allocates a new map_handlerdata_t given the map entry message definition. If
233
+ // the offset of the field within the parent message is also given, that is
234
+ // added to the handler data as well. Note that this is called *twice* per map
235
+ // field: once in the parent message handler setup when setting the startsubmsg
236
+ // handler and once in the map entry message handler setup when setting the
237
+ // key/value and endmsg handlers. The reason is that there is no easy way to
238
+ // pass the handlerdata down to the sub-message handler setup.
239
+ static map_handlerdata_t* new_map_handlerdata(
240
+ size_t ofs,
241
+ const upb_msgdef* mapentry_def,
242
+ Descriptor* desc) {
243
+
244
+ map_handlerdata_t* hd = ALLOC(map_handlerdata_t);
245
+ hd->ofs = ofs;
246
+ const upb_fielddef* key_field = upb_msgdef_itof(mapentry_def,
247
+ MAP_KEY_FIELD);
248
+ assert(key_field != NULL);
249
+ hd->key_field_type = upb_fielddef_type(key_field);
250
+ const upb_fielddef* value_field = upb_msgdef_itof(mapentry_def,
251
+ MAP_VALUE_FIELD);
252
+ assert(value_field != NULL);
253
+ hd->value_field_type = upb_fielddef_type(value_field);
254
+ hd->value_field_typeclass = field_type_class(value_field);
255
+
256
+ // Ensure that value_field_typeclass is properly GC-rooted. We must do this
257
+ // because we hold a reference to the Ruby class in the handlerdata, which is
258
+ // owned by the handlers. The handlers are owned by *this* message's Ruby
259
+ // object, but each Ruby object is rooted independently at the def -> Ruby
260
+ // object map. So we have to ensure that the Ruby objects we depend on will
261
+ // stick around as long as we're around.
262
+ if (hd->value_field_typeclass != Qnil) {
263
+ rb_ary_push(desc->typeclass_references, hd->value_field_typeclass);
264
+ }
265
+
266
+ return hd;
267
+ }
268
+
269
+ // Set up handlers for a repeated field.
270
+ static void add_handlers_for_repeated_field(upb_handlers *h,
271
+ const upb_fielddef *f,
272
+ size_t offset) {
273
+ upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER;
274
+ upb_handlerattr_sethandlerdata(&attr, newhandlerdata(h, offset));
275
+ upb_handlers_setstartseq(h, f, startseq_handler, &attr);
276
+ upb_handlerattr_uninit(&attr);
277
+
278
+ switch (upb_fielddef_type(f)) {
279
+
280
+ #define SET_HANDLER(utype, ltype) \
281
+ case utype: \
282
+ upb_handlers_set##ltype(h, f, append##ltype##_handler, NULL); \
283
+ break;
284
+
285
+ SET_HANDLER(UPB_TYPE_BOOL, bool);
286
+ SET_HANDLER(UPB_TYPE_INT32, int32);
287
+ SET_HANDLER(UPB_TYPE_UINT32, uint32);
288
+ SET_HANDLER(UPB_TYPE_ENUM, int32);
289
+ SET_HANDLER(UPB_TYPE_FLOAT, float);
290
+ SET_HANDLER(UPB_TYPE_INT64, int64);
291
+ SET_HANDLER(UPB_TYPE_UINT64, uint64);
292
+ SET_HANDLER(UPB_TYPE_DOUBLE, double);
293
+
294
+ #undef SET_HANDLER
295
+
296
+ case UPB_TYPE_STRING:
297
+ case UPB_TYPE_BYTES: {
298
+ bool is_bytes = upb_fielddef_type(f) == UPB_TYPE_BYTES;
299
+ upb_handlers_setstartstr(h, f, is_bytes ?
300
+ appendbytes_handler : appendstr_handler,
301
+ NULL);
302
+ upb_handlers_setstring(h, f, stringdata_handler, NULL);
303
+ break;
304
+ }
305
+ case UPB_TYPE_MESSAGE: {
306
+ upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER;
307
+ upb_handlerattr_sethandlerdata(&attr, newsubmsghandlerdata(h, 0, f));
308
+ upb_handlers_setstartsubmsg(h, f, appendsubmsg_handler, &attr);
309
+ upb_handlerattr_uninit(&attr);
310
+ break;
311
+ }
312
+ }
313
+ }
314
+
315
+ // Set up handlers for a singular field.
316
+ static void add_handlers_for_singular_field(upb_handlers *h,
317
+ const upb_fielddef *f,
318
+ size_t offset) {
319
+ switch (upb_fielddef_type(f)) {
320
+ case UPB_TYPE_BOOL:
321
+ case UPB_TYPE_INT32:
322
+ case UPB_TYPE_UINT32:
323
+ case UPB_TYPE_ENUM:
324
+ case UPB_TYPE_FLOAT:
325
+ case UPB_TYPE_INT64:
326
+ case UPB_TYPE_UINT64:
327
+ case UPB_TYPE_DOUBLE:
328
+ upb_shim_set(h, f, offset, -1);
329
+ break;
330
+ case UPB_TYPE_STRING:
331
+ case UPB_TYPE_BYTES: {
332
+ bool is_bytes = upb_fielddef_type(f) == UPB_TYPE_BYTES;
333
+ upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER;
334
+ upb_handlerattr_sethandlerdata(&attr, newhandlerdata(h, offset));
335
+ upb_handlers_setstartstr(h, f,
336
+ is_bytes ? bytes_handler : str_handler,
337
+ &attr);
338
+ upb_handlers_setstring(h, f, stringdata_handler, &attr);
339
+ upb_handlerattr_uninit(&attr);
340
+ break;
341
+ }
342
+ case UPB_TYPE_MESSAGE: {
343
+ upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER;
344
+ upb_handlerattr_sethandlerdata(&attr, newsubmsghandlerdata(h, offset, f));
345
+ upb_handlers_setstartsubmsg(h, f, submsg_handler, &attr);
346
+ upb_handlerattr_uninit(&attr);
347
+ break;
348
+ }
349
+ }
350
+ }
351
+
352
+ // Adds handlers to a map field.
353
+ static void add_handlers_for_mapfield(upb_handlers* h,
354
+ const upb_fielddef* fielddef,
355
+ size_t offset,
356
+ Descriptor* desc) {
357
+ const upb_msgdef* map_msgdef = upb_fielddef_msgsubdef(fielddef);
358
+ map_handlerdata_t* hd = new_map_handlerdata(offset, map_msgdef, desc);
359
+ upb_handlers_addcleanup(h, hd, free);
360
+ upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER;
361
+ upb_handlerattr_sethandlerdata(&attr, hd);
362
+ upb_handlers_setstartsubmsg(h, fielddef, startmapentry_handler, &attr);
363
+ upb_handlerattr_uninit(&attr);
364
+ }
365
+
366
+ // Adds handlers to a map-entry msgdef.
367
+ static void add_handlers_for_mapentry(const upb_msgdef* msgdef,
368
+ upb_handlers* h,
369
+ Descriptor* desc) {
370
+ const upb_fielddef* key_field = map_entry_key(msgdef);
371
+ const upb_fielddef* value_field = map_entry_value(msgdef);
372
+ map_handlerdata_t* hd = new_map_handlerdata(0, msgdef, desc);
373
+ upb_handlers_addcleanup(h, hd, free);
374
+ upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER;
375
+ upb_handlerattr_sethandlerdata(&attr, hd);
376
+ upb_handlers_setendmsg(h, endmap_handler, &attr);
377
+
378
+ add_handlers_for_singular_field(
379
+ h, key_field,
380
+ offsetof(map_parse_frame_t, key_storage));
381
+ add_handlers_for_singular_field(
382
+ h, value_field,
383
+ offsetof(map_parse_frame_t, value_storage));
384
+ }
385
+
177
386
  static void add_handlers_for_message(const void *closure, upb_handlers *h) {
178
- Descriptor* desc = ruby_to_Descriptor(
179
- get_def_obj((void*)upb_handlers_msgdef(h)));
387
+ const upb_msgdef* msgdef = upb_handlers_msgdef(h);
388
+ Descriptor* desc = ruby_to_Descriptor(get_def_obj((void*)msgdef));
389
+
390
+ // If this is a mapentry message type, set up a special set of handlers and
391
+ // bail out of the normal (user-defined) message type handling.
392
+ if (upb_msgdef_mapentry(msgdef)) {
393
+ add_handlers_for_mapentry(msgdef, h, desc);
394
+ return;
395
+ }
396
+
180
397
  // Ensure layout exists. We may be invoked to create handlers for a given
181
398
  // message if we are included as a submsg of another message type before our
182
399
  // class is actually built, so to work around this, we just create the layout
@@ -191,82 +408,15 @@ static void add_handlers_for_message(const void *closure, upb_handlers *h) {
191
408
  !upb_msg_done(&i);
192
409
  upb_msg_next(&i)) {
193
410
  const upb_fielddef *f = upb_msg_iter_field(&i);
194
- size_t offset = desc->layout->offsets[upb_fielddef_index(f)];
195
-
196
- if (upb_fielddef_isseq(f)) {
197
- upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER;
198
- upb_handlerattr_sethandlerdata(&attr, newhandlerdata(h, offset));
199
- upb_handlers_setstartseq(h, f, startseq_handler, &attr);
200
- upb_handlerattr_uninit(&attr);
201
-
202
- switch (upb_fielddef_type(f)) {
411
+ size_t offset = desc->layout->offsets[upb_fielddef_index(f)] +
412
+ sizeof(MessageHeader);
203
413
 
204
- #define SET_HANDLER(utype, ltype) \
205
- case utype: \
206
- upb_handlers_set##ltype(h, f, append##ltype##_handler, NULL); \
207
- break;
208
-
209
- SET_HANDLER(UPB_TYPE_BOOL, bool);
210
- SET_HANDLER(UPB_TYPE_INT32, int32);
211
- SET_HANDLER(UPB_TYPE_UINT32, uint32);
212
- SET_HANDLER(UPB_TYPE_ENUM, int32);
213
- SET_HANDLER(UPB_TYPE_FLOAT, float);
214
- SET_HANDLER(UPB_TYPE_INT64, int64);
215
- SET_HANDLER(UPB_TYPE_UINT64, uint64);
216
- SET_HANDLER(UPB_TYPE_DOUBLE, double);
217
-
218
- #undef SET_HANDLER
219
-
220
- case UPB_TYPE_STRING:
221
- case UPB_TYPE_BYTES: {
222
- bool is_bytes = upb_fielddef_type(f) == UPB_TYPE_BYTES;
223
- upb_handlers_setstartstr(h, f, is_bytes ?
224
- appendbytes_handler : appendstr_handler,
225
- NULL);
226
- upb_handlers_setstring(h, f, stringdata_handler, NULL);
227
- }
228
- case UPB_TYPE_MESSAGE: {
229
- upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER;
230
- upb_handlerattr_sethandlerdata(&attr, newsubmsghandlerdata(h, 0, f));
231
- upb_handlers_setstartsubmsg(h, f, appendsubmsg_handler, &attr);
232
- upb_handlerattr_uninit(&attr);
233
- break;
234
- }
235
- }
236
- }
237
-
238
- switch (upb_fielddef_type(f)) {
239
- case UPB_TYPE_BOOL:
240
- case UPB_TYPE_INT32:
241
- case UPB_TYPE_UINT32:
242
- case UPB_TYPE_ENUM:
243
- case UPB_TYPE_FLOAT:
244
- case UPB_TYPE_INT64:
245
- case UPB_TYPE_UINT64:
246
- case UPB_TYPE_DOUBLE:
247
- // The shim writes directly at the given offset (instead of using
248
- // DEREF()) so we need to add the msg overhead.
249
- upb_shim_set(h, f, offset + sizeof(MessageHeader), -1);
250
- break;
251
- case UPB_TYPE_STRING:
252
- case UPB_TYPE_BYTES: {
253
- bool is_bytes = upb_fielddef_type(f) == UPB_TYPE_BYTES;
254
- upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER;
255
- upb_handlerattr_sethandlerdata(&attr, newhandlerdata(h, offset));
256
- upb_handlers_setstartstr(h, f,
257
- is_bytes ? bytes_handler : str_handler,
258
- &attr);
259
- upb_handlers_setstring(h, f, stringdata_handler, &attr);
260
- upb_handlerattr_uninit(&attr);
261
- break;
262
- }
263
- case UPB_TYPE_MESSAGE: {
264
- upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER;
265
- upb_handlerattr_sethandlerdata(&attr, newsubmsghandlerdata(h, offset, f));
266
- upb_handlers_setstartsubmsg(h, f, submsg_handler, &attr);
267
- upb_handlerattr_uninit(&attr);
268
- break;
269
- }
414
+ if (is_map_field(f)) {
415
+ add_handlers_for_mapfield(h, f, offset, desc);
416
+ } else if (upb_fielddef_isseq(f)) {
417
+ add_handlers_for_repeated_field(h, f, offset);
418
+ } else {
419
+ add_handlers_for_singular_field(h, f, offset);
270
420
  }
271
421
  }
272
422
  }
@@ -558,6 +708,88 @@ static void putary(VALUE ary, const upb_fielddef *f, upb_sink *sink,
558
708
  upb_sink_endseq(sink, getsel(f, UPB_HANDLER_ENDSEQ));
559
709
  }
560
710
 
711
+ static void put_ruby_value(VALUE value,
712
+ const upb_fielddef *f,
713
+ VALUE type_class,
714
+ int depth,
715
+ upb_sink *sink) {
716
+ upb_selector_t sel = 0;
717
+ if (upb_fielddef_isprimitive(f)) {
718
+ sel = getsel(f, upb_handlers_getprimitivehandlertype(f));
719
+ }
720
+
721
+ switch (upb_fielddef_type(f)) {
722
+ case UPB_TYPE_INT32:
723
+ upb_sink_putint32(sink, sel, NUM2INT(value));
724
+ break;
725
+ case UPB_TYPE_INT64:
726
+ upb_sink_putint64(sink, sel, NUM2LL(value));
727
+ break;
728
+ case UPB_TYPE_UINT32:
729
+ upb_sink_putuint32(sink, sel, NUM2UINT(value));
730
+ break;
731
+ case UPB_TYPE_UINT64:
732
+ upb_sink_putuint64(sink, sel, NUM2ULL(value));
733
+ break;
734
+ case UPB_TYPE_FLOAT:
735
+ upb_sink_putfloat(sink, sel, NUM2DBL(value));
736
+ break;
737
+ case UPB_TYPE_DOUBLE:
738
+ upb_sink_putdouble(sink, sel, NUM2DBL(value));
739
+ break;
740
+ case UPB_TYPE_ENUM: {
741
+ if (TYPE(value) == T_SYMBOL) {
742
+ value = rb_funcall(type_class, rb_intern("resolve"), 1, value);
743
+ }
744
+ upb_sink_putint32(sink, sel, NUM2INT(value));
745
+ break;
746
+ }
747
+ case UPB_TYPE_BOOL:
748
+ upb_sink_putbool(sink, sel, value == Qtrue);
749
+ break;
750
+ case UPB_TYPE_STRING:
751
+ case UPB_TYPE_BYTES:
752
+ putstr(value, f, sink);
753
+ break;
754
+ case UPB_TYPE_MESSAGE:
755
+ putsubmsg(value, f, sink, depth);
756
+ }
757
+ }
758
+
759
+ static void putmap(VALUE map, const upb_fielddef *f, upb_sink *sink,
760
+ int depth) {
761
+ if (map == Qnil) return;
762
+ Map* self = ruby_to_Map(map);
763
+
764
+ upb_sink subsink;
765
+
766
+ upb_sink_startseq(sink, getsel(f, UPB_HANDLER_STARTSEQ), &subsink);
767
+
768
+ assert(upb_fielddef_type(f) == UPB_TYPE_MESSAGE);
769
+ const upb_fielddef* key_field = map_field_key(f);
770
+ const upb_fielddef* value_field = map_field_value(f);
771
+
772
+ Map_iter it;
773
+ for (Map_begin(map, &it); !Map_done(&it); Map_next(&it)) {
774
+ VALUE key = Map_iter_key(&it);
775
+ VALUE value = Map_iter_value(&it);
776
+
777
+ upb_sink entry_sink;
778
+ upb_sink_startsubmsg(&subsink, getsel(f, UPB_HANDLER_STARTSUBMSG), &entry_sink);
779
+ upb_sink_startmsg(&entry_sink);
780
+
781
+ put_ruby_value(key, key_field, Qnil, depth + 1, &entry_sink);
782
+ put_ruby_value(value, value_field, self->value_type_class, depth + 1,
783
+ &entry_sink);
784
+
785
+ upb_status status;
786
+ upb_sink_endmsg(&entry_sink, &status);
787
+ upb_sink_endsubmsg(&subsink, getsel(f, UPB_HANDLER_ENDSUBMSG));
788
+ }
789
+
790
+ upb_sink_endseq(sink, getsel(f, UPB_HANDLER_ENDSEQ));
791
+ }
792
+
561
793
  static void putmsg(VALUE msg_rb, const Descriptor* desc,
562
794
  upb_sink *sink, int depth) {
563
795
  upb_sink_startmsg(sink);
@@ -571,33 +803,38 @@ static void putmsg(VALUE msg_rb, const Descriptor* desc,
571
803
 
572
804
  MessageHeader* msg;
573
805
  TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg);
574
- void* msg_data = Message_data(msg);
575
806
 
576
807
  upb_msg_iter i;
577
808
  for (upb_msg_begin(&i, desc->msgdef);
578
809
  !upb_msg_done(&i);
579
810
  upb_msg_next(&i)) {
580
811
  upb_fielddef *f = upb_msg_iter_field(&i);
581
- uint32_t offset = desc->layout->offsets[upb_fielddef_index(f)];
812
+ uint32_t offset =
813
+ desc->layout->offsets[upb_fielddef_index(f)] + sizeof(MessageHeader);
582
814
 
583
- if (upb_fielddef_isseq(f)) {
584
- VALUE ary = DEREF(msg_data, offset, VALUE);
815
+ if (is_map_field(f)) {
816
+ VALUE map = DEREF(msg, offset, VALUE);
817
+ if (map != Qnil) {
818
+ putmap(map, f, sink, depth);
819
+ }
820
+ } else if (upb_fielddef_isseq(f)) {
821
+ VALUE ary = DEREF(msg, offset, VALUE);
585
822
  if (ary != Qnil) {
586
823
  putary(ary, f, sink, depth);
587
824
  }
588
825
  } else if (upb_fielddef_isstring(f)) {
589
- VALUE str = DEREF(msg_data, offset, VALUE);
826
+ VALUE str = DEREF(msg, offset, VALUE);
590
827
  if (RSTRING_LEN(str) > 0) {
591
828
  putstr(str, f, sink);
592
829
  }
593
830
  } else if (upb_fielddef_issubmsg(f)) {
594
- putsubmsg(DEREF(msg_data, offset, VALUE), f, sink, depth);
831
+ putsubmsg(DEREF(msg, offset, VALUE), f, sink, depth);
595
832
  } else {
596
833
  upb_selector_t sel = getsel(f, upb_handlers_getprimitivehandlertype(f));
597
834
 
598
835
  #define T(upbtypeconst, upbtype, ctype, default_value) \
599
836
  case upbtypeconst: { \
600
- ctype value = DEREF(msg_data, offset, ctype); \
837
+ ctype value = DEREF(msg, offset, ctype); \
601
838
  if (value != default_value) { \
602
839
  upb_sink_put##upbtype(sink, sel, value); \
603
840
  } \