google-protobuf 3.0.0.alpha.1.0 → 3.0.0.alpha.1.1

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

Potentially problematic release.


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

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
  } \