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 +8 -8
- data/ext/google/protobuf_c/defs.c +107 -6
- data/ext/google/protobuf_c/encode_decode.c +327 -90
- data/ext/google/protobuf_c/extconf.rb +1 -1
- data/ext/google/protobuf_c/map.c +805 -0
- data/ext/google/protobuf_c/message.c +12 -3
- data/ext/google/protobuf_c/protobuf.c +1 -0
- data/ext/google/protobuf_c/protobuf.h +82 -4
- data/ext/google/protobuf_c/repeated_field.c +5 -1
- data/ext/google/protobuf_c/storage.c +148 -41
- data/ext/google/protobuf_c/upb.c +810 -453
- data/ext/google/protobuf_c/upb.h +71 -12
- data/tests/basic.rb +262 -3
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
ZGYwNjhlZGZjOTE1ZjM4YmE2ZTAzYTZlOTZiZmZmMDFjMmQ4MjJiMw==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
YzJhNmY2MjZkNDQzN2E2MTk4MGNjYzIxODAwMTQ1ZThkNjMwZTg3Mg==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
MzMwMzVhNjkzNzA0NTc3NTJhNDVlOTNlMTgzZjJkNzA3NGE4ZDk2NjRlYmNi
|
10
|
+
OTBhMmQ4M2Y1YWZiYzc0Njc5OThmODliYzQ4YTA5YWM0MTk3MGQyZTA4YWYy
|
11
|
+
MjZiNDJmNjA4N2I4MDgzZjM5Y2IwMGViM2U4MjM5ZWE4NDBhZjI=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
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,
|
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
|
959
|
-
* is intended to serve as a DSL context to be used
|
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,
|
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
|
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(
|
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(
|
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(
|
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(
|
167
|
-
DEREF(
|
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(
|
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
|
-
|
179
|
-
|
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
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
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 =
|
812
|
+
uint32_t offset =
|
813
|
+
desc->layout->offsets[upb_fielddef_index(f)] + sizeof(MessageHeader);
|
582
814
|
|
583
|
-
if (
|
584
|
-
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(
|
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(
|
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(
|
837
|
+
ctype value = DEREF(msg, offset, ctype); \
|
601
838
|
if (value != default_value) { \
|
602
839
|
upb_sink_put##upbtype(sink, sel, value); \
|
603
840
|
} \
|