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