google-protobuf 3.0.0.alpha.1.1 → 3.0.0.alpha.2.0
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 +5 -13
- data/ext/google/protobuf_c/defs.c +298 -9
- data/ext/google/protobuf_c/encode_decode.c +204 -29
- data/ext/google/protobuf_c/map.c +1 -1
- data/ext/google/protobuf_c/message.c +44 -0
- data/ext/google/protobuf_c/protobuf.c +2 -0
- data/ext/google/protobuf_c/protobuf.h +61 -2
- data/ext/google/protobuf_c/repeated_field.c +28 -31
- data/ext/google/protobuf_c/storage.c +230 -66
- data/ext/google/protobuf_c/upb.c +938 -153
- data/ext/google/protobuf_c/upb.h +607 -55
- data/tests/basic.rb +114 -2
- data/tests/generated_code_test.rb +17 -0
- metadata +7 -5
checksums.yaml
CHANGED
@@ -1,15 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
5
|
-
data.tar.gz: !binary |-
|
6
|
-
YzJhNmY2MjZkNDQzN2E2MTk4MGNjYzIxODAwMTQ1ZThkNjMwZTg3Mg==
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 63730161da9f93c004fac333b54735b3d4ab2bb0
|
4
|
+
data.tar.gz: f5f01388a467ba1d0c92679563debbe2f2f24760
|
7
5
|
SHA512:
|
8
|
-
metadata.gz:
|
9
|
-
|
10
|
-
OTBhMmQ4M2Y1YWZiYzc0Njc5OThmODliYzQ4YTA5YWM0MTk3MGQyZTA4YWYy
|
11
|
-
MjZiNDJmNjA4N2I4MDgzZjM5Y2IwMGViM2U4MjM5ZWE4NDBhZjI=
|
12
|
-
data.tar.gz: !binary |-
|
13
|
-
NDhhZmI5M2IxN2Q5OTc2MWQ5YzY5Mzk3MzU2ODZjYzJiMTA4OTFlYTA3MzBj
|
14
|
-
MGE4YTg1NmVlMmViNTUzZDI5ZjQ4ZTE2ZDkxZDI5OGQxMDlmMTgzN2E2M2Qw
|
15
|
-
MWY4NGQ3YWVjZTIxY2Y3Y2FlNjMyODFjNDc0NDgyOTljN2E0NWY=
|
6
|
+
metadata.gz: 17c66e414b0317d5f7afad344cf4c45f830856bc60c4cb78bf775934a26472a65bd6b539ddb0412d8ba409c951d8c6b3dd0d97d06cb9a50cbf2fbba43e70ca60
|
7
|
+
data.tar.gz: 6c381c080addcc25725e8102497456cdf8a74df582d6f5f9efc43bd77d0fc0cbcffd407c2861f7aa2b9866c7dd575ce17e158df7e0bf3cfc6cd15f9047e882d8
|
@@ -58,11 +58,15 @@ static upb_def* check_notfrozen(const upb_def* def) {
|
|
58
58
|
}
|
59
59
|
|
60
60
|
static upb_msgdef* check_msg_notfrozen(const upb_msgdef* def) {
|
61
|
-
return (
|
61
|
+
return upb_downcast_msgdef_mutable(check_notfrozen((const upb_def*)def));
|
62
62
|
}
|
63
63
|
|
64
64
|
static upb_fielddef* check_field_notfrozen(const upb_fielddef* def) {
|
65
|
-
return (
|
65
|
+
return upb_downcast_fielddef_mutable(check_notfrozen((const upb_def*)def));
|
66
|
+
}
|
67
|
+
|
68
|
+
static upb_oneofdef* check_oneof_notfrozen(const upb_oneofdef* def) {
|
69
|
+
return (upb_oneofdef*)check_notfrozen((const upb_def*)def);
|
66
70
|
}
|
67
71
|
|
68
72
|
static upb_enumdef* check_enum_notfrozen(const upb_enumdef* def) {
|
@@ -282,6 +286,9 @@ void Descriptor_register(VALUE module) {
|
|
282
286
|
rb_define_method(klass, "each", Descriptor_each, 0);
|
283
287
|
rb_define_method(klass, "lookup", Descriptor_lookup, 1);
|
284
288
|
rb_define_method(klass, "add_field", Descriptor_add_field, 1);
|
289
|
+
rb_define_method(klass, "add_oneof", Descriptor_add_oneof, 1);
|
290
|
+
rb_define_method(klass, "each_oneof", Descriptor_each_oneof, 0);
|
291
|
+
rb_define_method(klass, "lookup_oneof", Descriptor_lookup_oneof, 1);
|
285
292
|
rb_define_method(klass, "msgclass", Descriptor_msgclass, 0);
|
286
293
|
rb_define_method(klass, "name", Descriptor_name, 0);
|
287
294
|
rb_define_method(klass, "name=", Descriptor_name_set, 1);
|
@@ -328,10 +335,10 @@ VALUE Descriptor_name_set(VALUE _self, VALUE str) {
|
|
328
335
|
VALUE Descriptor_each(VALUE _self) {
|
329
336
|
DEFINE_SELF(Descriptor, self, _self);
|
330
337
|
|
331
|
-
|
332
|
-
for (
|
333
|
-
!
|
334
|
-
|
338
|
+
upb_msg_field_iter it;
|
339
|
+
for (upb_msg_field_begin(&it, self->msgdef);
|
340
|
+
!upb_msg_field_done(&it);
|
341
|
+
upb_msg_field_next(&it)) {
|
335
342
|
const upb_fielddef* field = upb_msg_iter_field(&it);
|
336
343
|
VALUE obj = get_def_obj(field);
|
337
344
|
rb_yield(obj);
|
@@ -360,7 +367,7 @@ VALUE Descriptor_lookup(VALUE _self, VALUE name) {
|
|
360
367
|
* call-seq:
|
361
368
|
* Descriptor.add_field(field) => nil
|
362
369
|
*
|
363
|
-
* Adds the given FieldDescriptor to this message type.
|
370
|
+
* Adds the given FieldDescriptor to this message type. This descriptor must not
|
364
371
|
* have been added to a pool yet. Raises an exception if a field with the same
|
365
372
|
* name or number already exists. Sub-type references (e.g. for fields of type
|
366
373
|
* message) are not resolved at this point.
|
@@ -377,6 +384,67 @@ VALUE Descriptor_add_field(VALUE _self, VALUE obj) {
|
|
377
384
|
return Qnil;
|
378
385
|
}
|
379
386
|
|
387
|
+
/*
|
388
|
+
* call-seq:
|
389
|
+
* Descriptor.add_oneof(oneof) => nil
|
390
|
+
*
|
391
|
+
* Adds the given OneofDescriptor to this message type. This descriptor must not
|
392
|
+
* have been added to a pool yet. Raises an exception if a oneof with the same
|
393
|
+
* name already exists, or if any of the oneof's fields' names or numbers
|
394
|
+
* conflict with an existing field in this message type. All fields in the oneof
|
395
|
+
* are added to the message descriptor. Sub-type references (e.g. for fields of
|
396
|
+
* type message) are not resolved at this point.
|
397
|
+
*/
|
398
|
+
VALUE Descriptor_add_oneof(VALUE _self, VALUE obj) {
|
399
|
+
DEFINE_SELF(Descriptor, self, _self);
|
400
|
+
upb_msgdef* mut_def = check_msg_notfrozen(self->msgdef);
|
401
|
+
OneofDescriptor* def = ruby_to_OneofDescriptor(obj);
|
402
|
+
upb_oneofdef* mut_oneof_def = check_oneof_notfrozen(def->oneofdef);
|
403
|
+
CHECK_UPB(
|
404
|
+
upb_msgdef_addoneof(mut_def, mut_oneof_def, NULL, &status),
|
405
|
+
"Adding oneof to Descriptor failed");
|
406
|
+
add_def_obj(def->oneofdef, obj);
|
407
|
+
return Qnil;
|
408
|
+
}
|
409
|
+
|
410
|
+
/*
|
411
|
+
* call-seq:
|
412
|
+
* Descriptor.each_oneof(&block) => nil
|
413
|
+
*
|
414
|
+
* Invokes the given block for each oneof in this message type, passing the
|
415
|
+
* corresponding OneofDescriptor.
|
416
|
+
*/
|
417
|
+
VALUE Descriptor_each_oneof(VALUE _self) {
|
418
|
+
DEFINE_SELF(Descriptor, self, _self);
|
419
|
+
|
420
|
+
upb_msg_oneof_iter it;
|
421
|
+
for (upb_msg_oneof_begin(&it, self->msgdef);
|
422
|
+
!upb_msg_oneof_done(&it);
|
423
|
+
upb_msg_oneof_next(&it)) {
|
424
|
+
const upb_oneofdef* oneof = upb_msg_iter_oneof(&it);
|
425
|
+
VALUE obj = get_def_obj(oneof);
|
426
|
+
rb_yield(obj);
|
427
|
+
}
|
428
|
+
return Qnil;
|
429
|
+
}
|
430
|
+
|
431
|
+
/*
|
432
|
+
* call-seq:
|
433
|
+
* Descriptor.lookup_oneof(name) => OneofDescriptor
|
434
|
+
*
|
435
|
+
* Returns the oneof descriptor for the oneof with the given name, if present,
|
436
|
+
* or nil if none.
|
437
|
+
*/
|
438
|
+
VALUE Descriptor_lookup_oneof(VALUE _self, VALUE name) {
|
439
|
+
DEFINE_SELF(Descriptor, self, _self);
|
440
|
+
const char* s = get_str(name);
|
441
|
+
const upb_oneofdef* oneof = upb_msgdef_ntooz(self->msgdef, s);
|
442
|
+
if (oneof == NULL) {
|
443
|
+
return Qnil;
|
444
|
+
}
|
445
|
+
return get_def_obj(oneof);
|
446
|
+
}
|
447
|
+
|
380
448
|
/*
|
381
449
|
* call-seq:
|
382
450
|
* Descriptor.msgclass => message_klass
|
@@ -743,6 +811,120 @@ VALUE FieldDescriptor_set(VALUE _self, VALUE msg_rb, VALUE value) {
|
|
743
811
|
return Qnil;
|
744
812
|
}
|
745
813
|
|
814
|
+
// -----------------------------------------------------------------------------
|
815
|
+
// OneofDescriptor.
|
816
|
+
// -----------------------------------------------------------------------------
|
817
|
+
|
818
|
+
DEFINE_CLASS(OneofDescriptor, "Google::Protobuf::OneofDescriptor");
|
819
|
+
|
820
|
+
void OneofDescriptor_mark(void* _self) {
|
821
|
+
}
|
822
|
+
|
823
|
+
void OneofDescriptor_free(void* _self) {
|
824
|
+
OneofDescriptor* self = _self;
|
825
|
+
upb_oneofdef_unref(self->oneofdef, &self->oneofdef);
|
826
|
+
xfree(self);
|
827
|
+
}
|
828
|
+
|
829
|
+
/*
|
830
|
+
* call-seq:
|
831
|
+
* OneofDescriptor.new => oneof_descriptor
|
832
|
+
*
|
833
|
+
* Creates a new, empty, oneof descriptor. The oneof may only be modified prior
|
834
|
+
* to being added to a message descriptor which is subsequently added to a pool.
|
835
|
+
*/
|
836
|
+
VALUE OneofDescriptor_alloc(VALUE klass) {
|
837
|
+
OneofDescriptor* self = ALLOC(OneofDescriptor);
|
838
|
+
VALUE ret = TypedData_Wrap_Struct(klass, &_OneofDescriptor_type, self);
|
839
|
+
self->oneofdef = upb_oneofdef_new(&self->oneofdef);
|
840
|
+
return ret;
|
841
|
+
}
|
842
|
+
|
843
|
+
void OneofDescriptor_register(VALUE module) {
|
844
|
+
VALUE klass = rb_define_class_under(
|
845
|
+
module, "OneofDescriptor", rb_cObject);
|
846
|
+
rb_define_alloc_func(klass, OneofDescriptor_alloc);
|
847
|
+
rb_define_method(klass, "name", OneofDescriptor_name, 0);
|
848
|
+
rb_define_method(klass, "name=", OneofDescriptor_name_set, 1);
|
849
|
+
rb_define_method(klass, "add_field", OneofDescriptor_add_field, 1);
|
850
|
+
rb_define_method(klass, "each", OneofDescriptor_each, 0);
|
851
|
+
rb_include_module(klass, rb_mEnumerable);
|
852
|
+
cOneofDescriptor = klass;
|
853
|
+
rb_gc_register_address(&cOneofDescriptor);
|
854
|
+
}
|
855
|
+
|
856
|
+
/*
|
857
|
+
* call-seq:
|
858
|
+
* OneofDescriptor.name => name
|
859
|
+
*
|
860
|
+
* Returns the name of this oneof.
|
861
|
+
*/
|
862
|
+
VALUE OneofDescriptor_name(VALUE _self) {
|
863
|
+
DEFINE_SELF(OneofDescriptor, self, _self);
|
864
|
+
return rb_str_maybe_null(upb_oneofdef_name(self->oneofdef));
|
865
|
+
}
|
866
|
+
|
867
|
+
/*
|
868
|
+
* call-seq:
|
869
|
+
* OneofDescriptor.name = name
|
870
|
+
*
|
871
|
+
* Sets a new name for this oneof. The oneof must not have been added to a
|
872
|
+
* message descriptor yet.
|
873
|
+
*/
|
874
|
+
VALUE OneofDescriptor_name_set(VALUE _self, VALUE value) {
|
875
|
+
DEFINE_SELF(OneofDescriptor, self, _self);
|
876
|
+
upb_oneofdef* mut_def = check_oneof_notfrozen(self->oneofdef);
|
877
|
+
const char* str = get_str(value);
|
878
|
+
CHECK_UPB(upb_oneofdef_setname(mut_def, str, &status),
|
879
|
+
"Error setting oneof name");
|
880
|
+
return Qnil;
|
881
|
+
}
|
882
|
+
|
883
|
+
/*
|
884
|
+
* call-seq:
|
885
|
+
* OneofDescriptor.add_field(field) => nil
|
886
|
+
*
|
887
|
+
* Adds a field to this oneof. The field may have been added to this oneof in
|
888
|
+
* the past, or the message to which this oneof belongs (if any), but may not
|
889
|
+
* have already been added to any other oneof or message. Otherwise, an
|
890
|
+
* exception is raised.
|
891
|
+
*
|
892
|
+
* All fields added to the oneof via this method will be automatically added to
|
893
|
+
* the message to which this oneof belongs, if it belongs to one currently, or
|
894
|
+
* else will be added to any message to which the oneof is later added at the
|
895
|
+
* time that it is added.
|
896
|
+
*/
|
897
|
+
VALUE OneofDescriptor_add_field(VALUE _self, VALUE obj) {
|
898
|
+
DEFINE_SELF(OneofDescriptor, self, _self);
|
899
|
+
upb_oneofdef* mut_def = check_oneof_notfrozen(self->oneofdef);
|
900
|
+
FieldDescriptor* def = ruby_to_FieldDescriptor(obj);
|
901
|
+
upb_fielddef* mut_field_def = check_field_notfrozen(def->fielddef);
|
902
|
+
CHECK_UPB(
|
903
|
+
upb_oneofdef_addfield(mut_def, mut_field_def, NULL, &status),
|
904
|
+
"Adding field to OneofDescriptor failed");
|
905
|
+
add_def_obj(def->fielddef, obj);
|
906
|
+
return Qnil;
|
907
|
+
}
|
908
|
+
|
909
|
+
/*
|
910
|
+
* call-seq:
|
911
|
+
* OneofDescriptor.each(&block) => nil
|
912
|
+
*
|
913
|
+
* Iterates through fields in this oneof, yielding to the block on each one.
|
914
|
+
*/
|
915
|
+
VALUE OneofDescriptor_each(VALUE _self, VALUE field) {
|
916
|
+
DEFINE_SELF(OneofDescriptor, self, _self);
|
917
|
+
upb_oneof_iter it;
|
918
|
+
for (upb_oneof_begin(&it, self->oneofdef);
|
919
|
+
!upb_oneof_done(&it);
|
920
|
+
upb_oneof_next(&it)) {
|
921
|
+
const upb_fielddef* f = upb_oneof_iter_field(&it);
|
922
|
+
VALUE obj = get_def_obj(f);
|
923
|
+
rb_yield(obj);
|
924
|
+
}
|
925
|
+
return Qnil;
|
926
|
+
}
|
927
|
+
|
746
928
|
// -----------------------------------------------------------------------------
|
747
929
|
// EnumDescriptor.
|
748
930
|
// -----------------------------------------------------------------------------
|
@@ -952,6 +1134,7 @@ void MessageBuilderContext_register(VALUE module) {
|
|
952
1134
|
rb_define_method(klass, "required", MessageBuilderContext_required, -1);
|
953
1135
|
rb_define_method(klass, "repeated", MessageBuilderContext_repeated, -1);
|
954
1136
|
rb_define_method(klass, "map", MessageBuilderContext_map, -1);
|
1137
|
+
rb_define_method(klass, "oneof", MessageBuilderContext_oneof, 1);
|
955
1138
|
cMessageBuilderContext = klass;
|
956
1139
|
rb_gc_register_address(&cMessageBuilderContext);
|
957
1140
|
}
|
@@ -1165,6 +1348,110 @@ VALUE MessageBuilderContext_map(int argc, VALUE* argv, VALUE _self) {
|
|
1165
1348
|
return Qnil;
|
1166
1349
|
}
|
1167
1350
|
|
1351
|
+
/*
|
1352
|
+
* call-seq:
|
1353
|
+
* MessageBuilderContext.oneof(name, &block) => nil
|
1354
|
+
*
|
1355
|
+
* Creates a new OneofDescriptor with the given name, creates a
|
1356
|
+
* OneofBuilderContext attached to that OneofDescriptor, evaluates the given
|
1357
|
+
* block in the context of that OneofBuilderContext with #instance_eval, and
|
1358
|
+
* then adds the oneof to the message.
|
1359
|
+
*
|
1360
|
+
* This is the recommended, idiomatic way to build oneof definitions.
|
1361
|
+
*/
|
1362
|
+
VALUE MessageBuilderContext_oneof(VALUE _self, VALUE name) {
|
1363
|
+
DEFINE_SELF(MessageBuilderContext, self, _self);
|
1364
|
+
VALUE oneofdef = rb_class_new_instance(0, NULL, cOneofDescriptor);
|
1365
|
+
VALUE args[2] = { oneofdef, self->builder };
|
1366
|
+
VALUE ctx = rb_class_new_instance(2, args, cOneofBuilderContext);
|
1367
|
+
VALUE block = rb_block_proc();
|
1368
|
+
VALUE name_str = rb_str_new2(rb_id2name(SYM2ID(name)));
|
1369
|
+
rb_funcall(oneofdef, rb_intern("name="), 1, name_str);
|
1370
|
+
rb_funcall_with_block(ctx, rb_intern("instance_eval"), 0, NULL, block);
|
1371
|
+
Descriptor_add_oneof(self->descriptor, oneofdef);
|
1372
|
+
|
1373
|
+
return Qnil;
|
1374
|
+
}
|
1375
|
+
|
1376
|
+
// -----------------------------------------------------------------------------
|
1377
|
+
// OneofBuilderContext.
|
1378
|
+
// -----------------------------------------------------------------------------
|
1379
|
+
|
1380
|
+
DEFINE_CLASS(OneofBuilderContext,
|
1381
|
+
"Google::Protobuf::Internal::OneofBuilderContext");
|
1382
|
+
|
1383
|
+
void OneofBuilderContext_mark(void* _self) {
|
1384
|
+
OneofBuilderContext* self = _self;
|
1385
|
+
rb_gc_mark(self->descriptor);
|
1386
|
+
rb_gc_mark(self->builder);
|
1387
|
+
}
|
1388
|
+
|
1389
|
+
void OneofBuilderContext_free(void* _self) {
|
1390
|
+
OneofBuilderContext* self = _self;
|
1391
|
+
xfree(self);
|
1392
|
+
}
|
1393
|
+
|
1394
|
+
VALUE OneofBuilderContext_alloc(VALUE klass) {
|
1395
|
+
OneofBuilderContext* self = ALLOC(OneofBuilderContext);
|
1396
|
+
VALUE ret = TypedData_Wrap_Struct(
|
1397
|
+
klass, &_OneofBuilderContext_type, self);
|
1398
|
+
self->descriptor = Qnil;
|
1399
|
+
self->builder = Qnil;
|
1400
|
+
return ret;
|
1401
|
+
}
|
1402
|
+
|
1403
|
+
void OneofBuilderContext_register(VALUE module) {
|
1404
|
+
VALUE klass = rb_define_class_under(
|
1405
|
+
module, "OneofBuilderContext", rb_cObject);
|
1406
|
+
rb_define_alloc_func(klass, OneofBuilderContext_alloc);
|
1407
|
+
rb_define_method(klass, "initialize",
|
1408
|
+
OneofBuilderContext_initialize, 2);
|
1409
|
+
rb_define_method(klass, "optional", OneofBuilderContext_optional, -1);
|
1410
|
+
cOneofBuilderContext = klass;
|
1411
|
+
rb_gc_register_address(&cOneofBuilderContext);
|
1412
|
+
}
|
1413
|
+
|
1414
|
+
/*
|
1415
|
+
* call-seq:
|
1416
|
+
* OneofBuilderContext.new(desc, builder) => context
|
1417
|
+
*
|
1418
|
+
* Create a new oneof builder context around the given oneof descriptor and
|
1419
|
+
* builder context. This class is intended to serve as a DSL context to be used
|
1420
|
+
* with #instance_eval.
|
1421
|
+
*/
|
1422
|
+
VALUE OneofBuilderContext_initialize(VALUE _self,
|
1423
|
+
VALUE oneofdef,
|
1424
|
+
VALUE builder) {
|
1425
|
+
DEFINE_SELF(OneofBuilderContext, self, _self);
|
1426
|
+
self->descriptor = oneofdef;
|
1427
|
+
self->builder = builder;
|
1428
|
+
return Qnil;
|
1429
|
+
}
|
1430
|
+
|
1431
|
+
/*
|
1432
|
+
* call-seq:
|
1433
|
+
* OneofBuilderContext.optional(name, type, number, type_class = nil)
|
1434
|
+
*
|
1435
|
+
* Defines a new optional field in this oneof with the given type, tag number,
|
1436
|
+
* and type class (for message and enum fields). The type must be a Ruby symbol
|
1437
|
+
* (as accepted by FieldDescriptor#type=) and the type_class must be a string,
|
1438
|
+
* if present (as accepted by FieldDescriptor#submsg_name=).
|
1439
|
+
*/
|
1440
|
+
VALUE OneofBuilderContext_optional(int argc, VALUE* argv, VALUE _self) {
|
1441
|
+
DEFINE_SELF(OneofBuilderContext, self, _self);
|
1442
|
+
|
1443
|
+
if (argc < 3) {
|
1444
|
+
rb_raise(rb_eArgError, "Expected at least 3 arguments.");
|
1445
|
+
}
|
1446
|
+
VALUE name = argv[0];
|
1447
|
+
VALUE type = argv[1];
|
1448
|
+
VALUE number = argv[2];
|
1449
|
+
VALUE type_class = (argc > 3) ? argv[3] : Qnil;
|
1450
|
+
|
1451
|
+
return msgdef_add_field(self->descriptor, "optional",
|
1452
|
+
name, type, number, type_class);
|
1453
|
+
}
|
1454
|
+
|
1168
1455
|
// -----------------------------------------------------------------------------
|
1169
1456
|
// EnumBuilderContext.
|
1170
1457
|
// -----------------------------------------------------------------------------
|
@@ -1322,8 +1609,10 @@ VALUE Builder_add_enum(VALUE _self, VALUE name) {
|
|
1322
1609
|
|
1323
1610
|
static void validate_msgdef(const upb_msgdef* msgdef) {
|
1324
1611
|
// Verify that no required fields exist. proto3 does not support these.
|
1325
|
-
|
1326
|
-
for (
|
1612
|
+
upb_msg_field_iter it;
|
1613
|
+
for (upb_msg_field_begin(&it, msgdef);
|
1614
|
+
!upb_msg_field_done(&it);
|
1615
|
+
upb_msg_field_next(&it)) {
|
1327
1616
|
const upb_fielddef* field = upb_msg_iter_field(&it);
|
1328
1617
|
if (upb_fielddef_label(field) == UPB_LABEL_REQUIRED) {
|
1329
1618
|
rb_raise(rb_eTypeError, "Required fields are unsupported in proto3.");
|
@@ -59,6 +59,36 @@ static const void *newsubmsghandlerdata(upb_handlers* h, uint32_t ofs,
|
|
59
59
|
return hd;
|
60
60
|
}
|
61
61
|
|
62
|
+
typedef struct {
|
63
|
+
size_t ofs; // union data slot
|
64
|
+
size_t case_ofs; // oneof_case field
|
65
|
+
uint32_t oneof_case_num; // oneof-case number to place in oneof_case field
|
66
|
+
const upb_msgdef *md; // msgdef, for oneof submessage handler
|
67
|
+
} oneof_handlerdata_t;
|
68
|
+
|
69
|
+
static const void *newoneofhandlerdata(upb_handlers *h,
|
70
|
+
uint32_t ofs,
|
71
|
+
uint32_t case_ofs,
|
72
|
+
const upb_fielddef *f) {
|
73
|
+
oneof_handlerdata_t *hd = ALLOC(oneof_handlerdata_t);
|
74
|
+
hd->ofs = ofs;
|
75
|
+
hd->case_ofs = case_ofs;
|
76
|
+
// We reuse the field tag number as a oneof union discriminant tag. Note that
|
77
|
+
// we don't expose these numbers to the user, so the only requirement is that
|
78
|
+
// we have some unique ID for each union case/possibility. The field tag
|
79
|
+
// numbers are already present and are easy to use so there's no reason to
|
80
|
+
// create a separate ID space. In addition, using the field tag number here
|
81
|
+
// lets us easily look up the field in the oneof accessor.
|
82
|
+
hd->oneof_case_num = upb_fielddef_number(f);
|
83
|
+
if (upb_fielddef_type(f) == UPB_TYPE_MESSAGE) {
|
84
|
+
hd->md = upb_fielddef_msgsubdef(f);
|
85
|
+
} else {
|
86
|
+
hd->md = NULL;
|
87
|
+
}
|
88
|
+
upb_handlers_addcleanup(h, hd, free);
|
89
|
+
return hd;
|
90
|
+
}
|
91
|
+
|
62
92
|
// A handler that starts a repeated field. Gets the Repeated*Field instance for
|
63
93
|
// this field (such an instance always exists even in an empty message).
|
64
94
|
static void *startseq_handler(void* closure, const void* hd) {
|
@@ -67,8 +97,7 @@ static void *startseq_handler(void* closure, const void* hd) {
|
|
67
97
|
return (void*)DEREF(msg, *ofs, VALUE);
|
68
98
|
}
|
69
99
|
|
70
|
-
// Handlers that append primitive values to a repeated field
|
71
|
-
// array for now).
|
100
|
+
// Handlers that append primitive values to a repeated field.
|
72
101
|
#define DEFINE_APPEND_HANDLER(type, ctype) \
|
73
102
|
static bool append##type##_handler(void *closure, const void *hd, \
|
74
103
|
ctype val) { \
|
@@ -85,7 +114,7 @@ DEFINE_APPEND_HANDLER(int64, int64_t)
|
|
85
114
|
DEFINE_APPEND_HANDLER(uint64, uint64_t)
|
86
115
|
DEFINE_APPEND_HANDLER(double, double)
|
87
116
|
|
88
|
-
// Appends a string to a repeated field
|
117
|
+
// Appends a string to a repeated field.
|
89
118
|
static void* appendstr_handler(void *closure,
|
90
119
|
const void *hd,
|
91
120
|
size_t size_hint) {
|
@@ -96,7 +125,7 @@ static void* appendstr_handler(void *closure,
|
|
96
125
|
return (void*)str;
|
97
126
|
}
|
98
127
|
|
99
|
-
// Appends a 'bytes' string to a repeated field
|
128
|
+
// Appends a 'bytes' string to a repeated field.
|
100
129
|
static void* appendbytes_handler(void *closure,
|
101
130
|
const void *hd,
|
102
131
|
size_t size_hint) {
|
@@ -179,7 +208,11 @@ typedef struct {
|
|
179
208
|
size_t ofs;
|
180
209
|
upb_fieldtype_t key_field_type;
|
181
210
|
upb_fieldtype_t value_field_type;
|
182
|
-
|
211
|
+
|
212
|
+
// We know that we can hold this reference because the handlerdata has the
|
213
|
+
// same lifetime as the upb_handlers struct, and the upb_handlers struct holds
|
214
|
+
// a reference to the upb_msgdef, which in turn has references to its subdefs.
|
215
|
+
const upb_def* value_field_subdef;
|
183
216
|
} map_handlerdata_t;
|
184
217
|
|
185
218
|
// Temporary frame for map parsing: at the beginning of a map entry message, a
|
@@ -219,8 +252,15 @@ static bool endmap_handler(void *closure, const void *hd, upb_status* s) {
|
|
219
252
|
VALUE key = native_slot_get(
|
220
253
|
mapdata->key_field_type, Qnil,
|
221
254
|
&frame->key_storage);
|
255
|
+
|
256
|
+
VALUE value_field_typeclass = Qnil;
|
257
|
+
if (mapdata->value_field_type == UPB_TYPE_MESSAGE ||
|
258
|
+
mapdata->value_field_type == UPB_TYPE_ENUM) {
|
259
|
+
value_field_typeclass = get_def_obj(mapdata->value_field_subdef);
|
260
|
+
}
|
261
|
+
|
222
262
|
VALUE value = native_slot_get(
|
223
|
-
mapdata->value_field_type,
|
263
|
+
mapdata->value_field_type, value_field_typeclass,
|
224
264
|
&frame->value_storage);
|
225
265
|
|
226
266
|
Map_index_set(frame->map, key, value);
|
@@ -251,21 +291,90 @@ static map_handlerdata_t* new_map_handlerdata(
|
|
251
291
|
MAP_VALUE_FIELD);
|
252
292
|
assert(value_field != NULL);
|
253
293
|
hd->value_field_type = upb_fielddef_type(value_field);
|
254
|
-
hd->
|
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
|
-
}
|
294
|
+
hd->value_field_subdef = upb_fielddef_subdef(value_field);
|
265
295
|
|
266
296
|
return hd;
|
267
297
|
}
|
268
298
|
|
299
|
+
// Handlers that set primitive values in oneofs.
|
300
|
+
#define DEFINE_ONEOF_HANDLER(type, ctype) \
|
301
|
+
static bool oneof##type##_handler(void *closure, const void *hd, \
|
302
|
+
ctype val) { \
|
303
|
+
const oneof_handlerdata_t *oneofdata = hd; \
|
304
|
+
DEREF(closure, oneofdata->case_ofs, uint32_t) = \
|
305
|
+
oneofdata->oneof_case_num; \
|
306
|
+
DEREF(closure, oneofdata->ofs, ctype) = val; \
|
307
|
+
return true; \
|
308
|
+
}
|
309
|
+
|
310
|
+
DEFINE_ONEOF_HANDLER(bool, bool)
|
311
|
+
DEFINE_ONEOF_HANDLER(int32, int32_t)
|
312
|
+
DEFINE_ONEOF_HANDLER(uint32, uint32_t)
|
313
|
+
DEFINE_ONEOF_HANDLER(float, float)
|
314
|
+
DEFINE_ONEOF_HANDLER(int64, int64_t)
|
315
|
+
DEFINE_ONEOF_HANDLER(uint64, uint64_t)
|
316
|
+
DEFINE_ONEOF_HANDLER(double, double)
|
317
|
+
|
318
|
+
#undef DEFINE_ONEOF_HANDLER
|
319
|
+
|
320
|
+
// Handlers for strings in a oneof.
|
321
|
+
static void *oneofstr_handler(void *closure,
|
322
|
+
const void *hd,
|
323
|
+
size_t size_hint) {
|
324
|
+
MessageHeader* msg = closure;
|
325
|
+
const oneof_handlerdata_t *oneofdata = hd;
|
326
|
+
VALUE str = rb_str_new2("");
|
327
|
+
rb_enc_associate(str, kRubyStringUtf8Encoding);
|
328
|
+
DEREF(msg, oneofdata->case_ofs, uint32_t) =
|
329
|
+
oneofdata->oneof_case_num;
|
330
|
+
DEREF(msg, oneofdata->ofs, VALUE) = str;
|
331
|
+
return (void*)str;
|
332
|
+
}
|
333
|
+
|
334
|
+
static void *oneofbytes_handler(void *closure,
|
335
|
+
const void *hd,
|
336
|
+
size_t size_hint) {
|
337
|
+
MessageHeader* msg = closure;
|
338
|
+
const oneof_handlerdata_t *oneofdata = hd;
|
339
|
+
VALUE str = rb_str_new2("");
|
340
|
+
rb_enc_associate(str, kRubyString8bitEncoding);
|
341
|
+
DEREF(msg, oneofdata->case_ofs, uint32_t) =
|
342
|
+
oneofdata->oneof_case_num;
|
343
|
+
DEREF(msg, oneofdata->ofs, VALUE) = str;
|
344
|
+
return (void*)str;
|
345
|
+
}
|
346
|
+
|
347
|
+
// Handler for a submessage field in a oneof.
|
348
|
+
static void *oneofsubmsg_handler(void *closure,
|
349
|
+
const void *hd) {
|
350
|
+
MessageHeader* msg = closure;
|
351
|
+
const oneof_handlerdata_t *oneofdata = hd;
|
352
|
+
uint32_t oldcase = DEREF(msg, oneofdata->case_ofs, uint32_t);
|
353
|
+
|
354
|
+
VALUE subdesc =
|
355
|
+
get_def_obj((void*)oneofdata->md);
|
356
|
+
VALUE subklass = Descriptor_msgclass(subdesc);
|
357
|
+
|
358
|
+
if (oldcase != oneofdata->oneof_case_num ||
|
359
|
+
DEREF(msg, oneofdata->ofs, VALUE) == Qnil) {
|
360
|
+
DEREF(msg, oneofdata->ofs, VALUE) =
|
361
|
+
rb_class_new_instance(0, NULL, subklass);
|
362
|
+
}
|
363
|
+
// Set the oneof case *after* allocating the new class instance -- otherwise,
|
364
|
+
// if the Ruby GC is invoked as part of a call into the VM, it might invoke
|
365
|
+
// our mark routines, and our mark routines might see the case value
|
366
|
+
// indicating a VALUE is present and expect a valid VALUE. See comment in
|
367
|
+
// layout_set() for more detail: basically, the change to the value and the
|
368
|
+
// case must be atomic w.r.t. the Ruby VM.
|
369
|
+
DEREF(msg, oneofdata->case_ofs, uint32_t) =
|
370
|
+
oneofdata->oneof_case_num;
|
371
|
+
|
372
|
+
VALUE submsg_rb = DEREF(msg, oneofdata->ofs, VALUE);
|
373
|
+
MessageHeader* submsg;
|
374
|
+
TypedData_Get_Struct(submsg_rb, MessageHeader, &Message_type, submsg);
|
375
|
+
return submsg;
|
376
|
+
}
|
377
|
+
|
269
378
|
// Set up handlers for a repeated field.
|
270
379
|
static void add_handlers_for_repeated_field(upb_handlers *h,
|
271
380
|
const upb_fielddef *f,
|
@@ -383,6 +492,53 @@ static void add_handlers_for_mapentry(const upb_msgdef* msgdef,
|
|
383
492
|
offsetof(map_parse_frame_t, value_storage));
|
384
493
|
}
|
385
494
|
|
495
|
+
// Set up handlers for a oneof field.
|
496
|
+
static void add_handlers_for_oneof_field(upb_handlers *h,
|
497
|
+
const upb_fielddef *f,
|
498
|
+
size_t offset,
|
499
|
+
size_t oneof_case_offset) {
|
500
|
+
|
501
|
+
upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER;
|
502
|
+
upb_handlerattr_sethandlerdata(
|
503
|
+
&attr, newoneofhandlerdata(h, offset, oneof_case_offset, f));
|
504
|
+
|
505
|
+
switch (upb_fielddef_type(f)) {
|
506
|
+
|
507
|
+
#define SET_HANDLER(utype, ltype) \
|
508
|
+
case utype: \
|
509
|
+
upb_handlers_set##ltype(h, f, oneof##ltype##_handler, &attr); \
|
510
|
+
break;
|
511
|
+
|
512
|
+
SET_HANDLER(UPB_TYPE_BOOL, bool);
|
513
|
+
SET_HANDLER(UPB_TYPE_INT32, int32);
|
514
|
+
SET_HANDLER(UPB_TYPE_UINT32, uint32);
|
515
|
+
SET_HANDLER(UPB_TYPE_ENUM, int32);
|
516
|
+
SET_HANDLER(UPB_TYPE_FLOAT, float);
|
517
|
+
SET_HANDLER(UPB_TYPE_INT64, int64);
|
518
|
+
SET_HANDLER(UPB_TYPE_UINT64, uint64);
|
519
|
+
SET_HANDLER(UPB_TYPE_DOUBLE, double);
|
520
|
+
|
521
|
+
#undef SET_HANDLER
|
522
|
+
|
523
|
+
case UPB_TYPE_STRING:
|
524
|
+
case UPB_TYPE_BYTES: {
|
525
|
+
bool is_bytes = upb_fielddef_type(f) == UPB_TYPE_BYTES;
|
526
|
+
upb_handlers_setstartstr(h, f, is_bytes ?
|
527
|
+
oneofbytes_handler : oneofstr_handler,
|
528
|
+
&attr);
|
529
|
+
upb_handlers_setstring(h, f, stringdata_handler, NULL);
|
530
|
+
break;
|
531
|
+
}
|
532
|
+
case UPB_TYPE_MESSAGE: {
|
533
|
+
upb_handlers_setstartsubmsg(h, f, oneofsubmsg_handler, &attr);
|
534
|
+
break;
|
535
|
+
}
|
536
|
+
}
|
537
|
+
|
538
|
+
upb_handlerattr_uninit(&attr);
|
539
|
+
}
|
540
|
+
|
541
|
+
|
386
542
|
static void add_handlers_for_message(const void *closure, upb_handlers *h) {
|
387
543
|
const upb_msgdef* msgdef = upb_handlers_msgdef(h);
|
388
544
|
Descriptor* desc = ruby_to_Descriptor(get_def_obj((void*)msgdef));
|
@@ -402,16 +558,20 @@ static void add_handlers_for_message(const void *closure, upb_handlers *h) {
|
|
402
558
|
desc->layout = create_layout(desc->msgdef);
|
403
559
|
}
|
404
560
|
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
upb_msg_next(&i)) {
|
561
|
+
upb_msg_field_iter i;
|
562
|
+
for (upb_msg_field_begin(&i, desc->msgdef);
|
563
|
+
!upb_msg_field_done(&i);
|
564
|
+
upb_msg_field_next(&i)) {
|
410
565
|
const upb_fielddef *f = upb_msg_iter_field(&i);
|
411
|
-
size_t offset = desc->layout->
|
566
|
+
size_t offset = desc->layout->fields[upb_fielddef_index(f)].offset +
|
412
567
|
sizeof(MessageHeader);
|
413
568
|
|
414
|
-
if (
|
569
|
+
if (upb_fielddef_containingoneof(f)) {
|
570
|
+
size_t oneof_case_offset =
|
571
|
+
desc->layout->fields[upb_fielddef_index(f)].case_offset +
|
572
|
+
sizeof(MessageHeader);
|
573
|
+
add_handlers_for_oneof_field(h, f, offset, oneof_case_offset);
|
574
|
+
} else if (is_map_field(f)) {
|
415
575
|
add_handlers_for_mapfield(h, f, offset, desc);
|
416
576
|
} else if (upb_fielddef_isseq(f)) {
|
417
577
|
add_handlers_for_repeated_field(h, f, offset);
|
@@ -804,13 +964,28 @@ static void putmsg(VALUE msg_rb, const Descriptor* desc,
|
|
804
964
|
MessageHeader* msg;
|
805
965
|
TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg);
|
806
966
|
|
807
|
-
|
808
|
-
for (
|
809
|
-
!
|
810
|
-
|
967
|
+
upb_msg_field_iter i;
|
968
|
+
for (upb_msg_field_begin(&i, desc->msgdef);
|
969
|
+
!upb_msg_field_done(&i);
|
970
|
+
upb_msg_field_next(&i)) {
|
811
971
|
upb_fielddef *f = upb_msg_iter_field(&i);
|
812
972
|
uint32_t offset =
|
813
|
-
desc->layout->
|
973
|
+
desc->layout->fields[upb_fielddef_index(f)].offset +
|
974
|
+
sizeof(MessageHeader);
|
975
|
+
|
976
|
+
if (upb_fielddef_containingoneof(f)) {
|
977
|
+
uint32_t oneof_case_offset =
|
978
|
+
desc->layout->fields[upb_fielddef_index(f)].case_offset +
|
979
|
+
sizeof(MessageHeader);
|
980
|
+
// For a oneof, check that this field is actually present -- skip all the
|
981
|
+
// below if not.
|
982
|
+
if (DEREF(msg, oneof_case_offset, uint32_t) !=
|
983
|
+
upb_fielddef_number(f)) {
|
984
|
+
continue;
|
985
|
+
}
|
986
|
+
// Otherwise, fall through to the appropriate singular-field handler
|
987
|
+
// below.
|
988
|
+
}
|
814
989
|
|
815
990
|
if (is_map_field(f)) {
|
816
991
|
VALUE map = DEREF(msg, offset, VALUE);
|