google-protobuf 3.2.0 → 3.9.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 +5 -5
- data/ext/google/protobuf_c/defs.c +575 -81
- data/ext/google/protobuf_c/encode_decode.c +456 -149
- data/ext/google/protobuf_c/extconf.rb +15 -2
- data/ext/google/protobuf_c/map.c +47 -3
- data/ext/google/protobuf_c/message.c +308 -82
- data/ext/google/protobuf_c/protobuf.c +7 -3
- data/ext/google/protobuf_c/protobuf.h +86 -12
- data/ext/google/protobuf_c/repeated_field.c +10 -4
- data/ext/google/protobuf_c/storage.c +286 -117
- data/ext/google/protobuf_c/upb.c +14482 -10935
- data/ext/google/protobuf_c/upb.h +2401 -613
- data/ext/google/protobuf_c/wrap_memcpy.c +51 -0
- data/lib/google/protobuf.rb +5 -4
- data/lib/google/protobuf/any_pb.rb +5 -3
- data/lib/google/protobuf/api_pb.rb +23 -21
- data/lib/google/protobuf/duration_pb.rb +5 -3
- data/lib/google/protobuf/empty_pb.rb +3 -1
- data/lib/google/protobuf/field_mask_pb.rb +4 -2
- data/lib/google/protobuf/message_exts.rb +2 -2
- data/lib/google/protobuf/repeated_field.rb +3 -3
- data/lib/google/protobuf/source_context_pb.rb +4 -2
- data/lib/google/protobuf/struct_pb.rb +19 -17
- data/lib/google/protobuf/timestamp_pb.rb +5 -3
- data/lib/google/protobuf/type_pb.rb +68 -66
- data/lib/google/protobuf/well_known_types.rb +13 -1
- data/lib/google/protobuf/wrappers_pb.rb +28 -26
- data/tests/basic.rb +206 -1023
- data/tests/generated_code_test.rb +6 -2
- metadata +5 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 4ce844d5328ba745c874ed5fa1c9f8f4047889d1975bcedec6506ed40acc42db
|
4
|
+
data.tar.gz: b87cbb4655c6e699eea3ca49fceacf6e2c430d97bf1e4929b5246ab716cea9ed
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 62c110973d025bac4502414fd8aeb03a1c63136f2b87970f976c27fdb891ccf621c12448ef9cd74ce58d97b3e60861d4a635f795d06ea8b9ec033e34a0378708
|
7
|
+
data.tar.gz: 4040bafd4439c62c50e06471e66e9c2ccb52220620d285e0961da85ad1abc7944bab77d51b9ec140cd733e732adf762ad1dee5886758a755c166804ade5e29e1
|
@@ -76,7 +76,7 @@ static upb_enumdef* check_enum_notfrozen(const upb_enumdef* def) {
|
|
76
76
|
// -----------------------------------------------------------------------------
|
77
77
|
|
78
78
|
#define DEFINE_CLASS(name, string_name) \
|
79
|
-
VALUE c ## name;
|
79
|
+
VALUE c ## name = Qnil; \
|
80
80
|
const rb_data_type_t _ ## name ## _type = { \
|
81
81
|
string_name, \
|
82
82
|
{ name ## _mark, name ## _free, NULL }, \
|
@@ -122,15 +122,15 @@ void DescriptorPool_register(VALUE module) {
|
|
122
122
|
module, "DescriptorPool", rb_cObject);
|
123
123
|
rb_define_alloc_func(klass, DescriptorPool_alloc);
|
124
124
|
rb_define_method(klass, "add", DescriptorPool_add, 1);
|
125
|
-
rb_define_method(klass, "build", DescriptorPool_build,
|
125
|
+
rb_define_method(klass, "build", DescriptorPool_build, -1);
|
126
126
|
rb_define_method(klass, "lookup", DescriptorPool_lookup, 1);
|
127
127
|
rb_define_singleton_method(klass, "generated_pool",
|
128
128
|
DescriptorPool_generated_pool, 0);
|
129
|
-
cDescriptorPool = klass;
|
130
129
|
rb_gc_register_address(&cDescriptorPool);
|
130
|
+
cDescriptorPool = klass;
|
131
131
|
|
132
|
-
generated_pool = rb_class_new_instance(0, NULL, klass);
|
133
132
|
rb_gc_register_address(&generated_pool);
|
133
|
+
generated_pool = rb_class_new_instance(0, NULL, klass);
|
134
134
|
}
|
135
135
|
|
136
136
|
static void add_descriptor_to_pool(DescriptorPool* self,
|
@@ -181,7 +181,7 @@ VALUE DescriptorPool_add(VALUE _self, VALUE def) {
|
|
181
181
|
* Builder#add_enum within the block as appropriate. This is the recommended,
|
182
182
|
* idiomatic way to define new message and enum types.
|
183
183
|
*/
|
184
|
-
VALUE DescriptorPool_build(VALUE _self) {
|
184
|
+
VALUE DescriptorPool_build(int argc, VALUE* argv, VALUE _self) {
|
185
185
|
VALUE ctx = rb_class_new_instance(0, NULL, cBuilder);
|
186
186
|
VALUE block = rb_block_proc();
|
187
187
|
rb_funcall_with_block(ctx, rb_intern("instance_eval"), 0, NULL, block);
|
@@ -228,7 +228,6 @@ DEFINE_CLASS(Descriptor, "Google::Protobuf::Descriptor");
|
|
228
228
|
void Descriptor_mark(void* _self) {
|
229
229
|
Descriptor* self = _self;
|
230
230
|
rb_gc_mark(self->klass);
|
231
|
-
rb_gc_mark(self->typeclass_references);
|
232
231
|
}
|
233
232
|
|
234
233
|
void Descriptor_free(void* _self) {
|
@@ -283,7 +282,6 @@ VALUE Descriptor_alloc(VALUE klass) {
|
|
283
282
|
self->pb_serialize_handlers = NULL;
|
284
283
|
self->json_serialize_handlers = NULL;
|
285
284
|
self->json_serialize_handlers_preserve = NULL;
|
286
|
-
self->typeclass_references = rb_ary_new();
|
287
285
|
return ret;
|
288
286
|
}
|
289
287
|
|
@@ -291,6 +289,7 @@ void Descriptor_register(VALUE module) {
|
|
291
289
|
VALUE klass = rb_define_class_under(
|
292
290
|
module, "Descriptor", rb_cObject);
|
293
291
|
rb_define_alloc_func(klass, Descriptor_alloc);
|
292
|
+
rb_define_method(klass, "initialize", Descriptor_initialize, 1);
|
294
293
|
rb_define_method(klass, "each", Descriptor_each, 0);
|
295
294
|
rb_define_method(klass, "lookup", Descriptor_lookup, 1);
|
296
295
|
rb_define_method(klass, "add_field", Descriptor_add_field, 1);
|
@@ -300,9 +299,40 @@ void Descriptor_register(VALUE module) {
|
|
300
299
|
rb_define_method(klass, "msgclass", Descriptor_msgclass, 0);
|
301
300
|
rb_define_method(klass, "name", Descriptor_name, 0);
|
302
301
|
rb_define_method(klass, "name=", Descriptor_name_set, 1);
|
302
|
+
rb_define_method(klass, "file_descriptor", Descriptor_file_descriptor, 0);
|
303
303
|
rb_include_module(klass, rb_mEnumerable);
|
304
|
-
cDescriptor = klass;
|
305
304
|
rb_gc_register_address(&cDescriptor);
|
305
|
+
cDescriptor = klass;
|
306
|
+
}
|
307
|
+
|
308
|
+
/*
|
309
|
+
* call-seq:
|
310
|
+
* Descriptor.new(file_descriptor)
|
311
|
+
*
|
312
|
+
* Initializes a new descriptor and assigns a file descriptor to it.
|
313
|
+
*/
|
314
|
+
VALUE Descriptor_initialize(VALUE _self, VALUE file_descriptor_rb) {
|
315
|
+
DEFINE_SELF(Descriptor, self, _self);
|
316
|
+
|
317
|
+
FileDescriptor* file_descriptor = ruby_to_FileDescriptor(file_descriptor_rb);
|
318
|
+
|
319
|
+
CHECK_UPB(
|
320
|
+
upb_filedef_addmsg(file_descriptor->filedef, self->msgdef, NULL, &status),
|
321
|
+
"Failed to associate message to file descriptor.");
|
322
|
+
add_def_obj(file_descriptor->filedef, file_descriptor_rb);
|
323
|
+
|
324
|
+
return Qnil;
|
325
|
+
}
|
326
|
+
|
327
|
+
/*
|
328
|
+
* call-seq:
|
329
|
+
* Descriptor.file_descriptor
|
330
|
+
*
|
331
|
+
* Returns the FileDescriptor object this message belongs to.
|
332
|
+
*/
|
333
|
+
VALUE Descriptor_file_descriptor(VALUE _self) {
|
334
|
+
DEFINE_SELF(Descriptor, self, _self);
|
335
|
+
return get_def_obj(upb_def_file(self->msgdef));
|
306
336
|
}
|
307
337
|
|
308
338
|
/*
|
@@ -472,6 +502,142 @@ VALUE Descriptor_msgclass(VALUE _self) {
|
|
472
502
|
return self->klass;
|
473
503
|
}
|
474
504
|
|
505
|
+
// -----------------------------------------------------------------------------
|
506
|
+
// FileDescriptor.
|
507
|
+
// -----------------------------------------------------------------------------
|
508
|
+
|
509
|
+
DEFINE_CLASS(FileDescriptor, "Google::Protobuf::FileDescriptor");
|
510
|
+
|
511
|
+
void FileDescriptor_mark(void* _self) {
|
512
|
+
}
|
513
|
+
|
514
|
+
void FileDescriptor_free(void* _self) {
|
515
|
+
FileDescriptor* self = _self;
|
516
|
+
upb_filedef_unref(self->filedef, &self->filedef);
|
517
|
+
xfree(self);
|
518
|
+
}
|
519
|
+
|
520
|
+
/*
|
521
|
+
* call-seq:
|
522
|
+
* FileDescriptor.new => file
|
523
|
+
*
|
524
|
+
* Returns a new file descriptor. The syntax must be set before it's passed
|
525
|
+
* to a builder.
|
526
|
+
*/
|
527
|
+
VALUE FileDescriptor_alloc(VALUE klass) {
|
528
|
+
FileDescriptor* self = ALLOC(FileDescriptor);
|
529
|
+
VALUE ret = TypedData_Wrap_Struct(klass, &_FileDescriptor_type, self);
|
530
|
+
upb_filedef* filedef = upb_filedef_new(&self->filedef);
|
531
|
+
self->filedef = filedef;
|
532
|
+
return ret;
|
533
|
+
}
|
534
|
+
|
535
|
+
void FileDescriptor_register(VALUE module) {
|
536
|
+
VALUE klass = rb_define_class_under(
|
537
|
+
module, "FileDescriptor", rb_cObject);
|
538
|
+
rb_define_alloc_func(klass, FileDescriptor_alloc);
|
539
|
+
rb_define_method(klass, "initialize", FileDescriptor_initialize, -1);
|
540
|
+
rb_define_method(klass, "name", FileDescriptor_name, 0);
|
541
|
+
rb_define_method(klass, "syntax", FileDescriptor_syntax, 0);
|
542
|
+
rb_define_method(klass, "syntax=", FileDescriptor_syntax_set, 1);
|
543
|
+
rb_gc_register_address(&cFileDescriptor);
|
544
|
+
cFileDescriptor = klass;
|
545
|
+
}
|
546
|
+
|
547
|
+
/*
|
548
|
+
* call-seq:
|
549
|
+
* FileDescriptor.new(name, options = nil) => file
|
550
|
+
*
|
551
|
+
* Initializes a new file descriptor with the given file name.
|
552
|
+
* Also accepts an optional "options" hash, specifying other optional
|
553
|
+
* metadata about the file. The options hash currently accepts the following
|
554
|
+
* * "syntax": :proto2 or :proto3 (default: :proto3)
|
555
|
+
*/
|
556
|
+
VALUE FileDescriptor_initialize(int argc, VALUE* argv, VALUE _self) {
|
557
|
+
DEFINE_SELF(FileDescriptor, self, _self);
|
558
|
+
|
559
|
+
VALUE name_rb;
|
560
|
+
VALUE options = Qnil;
|
561
|
+
rb_scan_args(argc, argv, "11", &name_rb, &options);
|
562
|
+
|
563
|
+
if (name_rb != Qnil) {
|
564
|
+
Check_Type(name_rb, T_STRING);
|
565
|
+
const char* name = get_str(name_rb);
|
566
|
+
CHECK_UPB(upb_filedef_setname(self->filedef, name, &status),
|
567
|
+
"Error setting file name");
|
568
|
+
}
|
569
|
+
|
570
|
+
// Default syntax is proto3.
|
571
|
+
VALUE syntax = ID2SYM(rb_intern("proto3"));
|
572
|
+
if (options != Qnil) {
|
573
|
+
Check_Type(options, T_HASH);
|
574
|
+
|
575
|
+
if (rb_funcall(options, rb_intern("key?"), 1,
|
576
|
+
ID2SYM(rb_intern("syntax"))) == Qtrue) {
|
577
|
+
syntax = rb_hash_lookup(options, ID2SYM(rb_intern("syntax")));
|
578
|
+
}
|
579
|
+
}
|
580
|
+
FileDescriptor_syntax_set(_self, syntax);
|
581
|
+
|
582
|
+
return Qnil;
|
583
|
+
}
|
584
|
+
|
585
|
+
/*
|
586
|
+
* call-seq:
|
587
|
+
* FileDescriptor.name => name
|
588
|
+
*
|
589
|
+
* Returns the name of the file.
|
590
|
+
*/
|
591
|
+
VALUE FileDescriptor_name(VALUE _self) {
|
592
|
+
DEFINE_SELF(FileDescriptor, self, _self);
|
593
|
+
const char* name = upb_filedef_name(self->filedef);
|
594
|
+
return name == NULL ? Qnil : rb_str_new2(name);
|
595
|
+
}
|
596
|
+
|
597
|
+
/*
|
598
|
+
* call-seq:
|
599
|
+
* FileDescriptor.syntax => syntax
|
600
|
+
*
|
601
|
+
* Returns this file descriptors syntax.
|
602
|
+
*
|
603
|
+
* Valid syntax versions are:
|
604
|
+
* :proto2 or :proto3.
|
605
|
+
*/
|
606
|
+
VALUE FileDescriptor_syntax(VALUE _self) {
|
607
|
+
DEFINE_SELF(FileDescriptor, self, _self);
|
608
|
+
|
609
|
+
switch (upb_filedef_syntax(self->filedef)) {
|
610
|
+
case UPB_SYNTAX_PROTO3: return ID2SYM(rb_intern("proto3"));
|
611
|
+
case UPB_SYNTAX_PROTO2: return ID2SYM(rb_intern("proto2"));
|
612
|
+
default: return Qnil;
|
613
|
+
}
|
614
|
+
}
|
615
|
+
|
616
|
+
/*
|
617
|
+
* call-seq:
|
618
|
+
* FileDescriptor.syntax = version
|
619
|
+
*
|
620
|
+
* Sets this file descriptor's syntax, can be :proto3 or :proto2.
|
621
|
+
*/
|
622
|
+
VALUE FileDescriptor_syntax_set(VALUE _self, VALUE syntax_rb) {
|
623
|
+
DEFINE_SELF(FileDescriptor, self, _self);
|
624
|
+
Check_Type(syntax_rb, T_SYMBOL);
|
625
|
+
|
626
|
+
upb_syntax_t syntax;
|
627
|
+
if (SYM2ID(syntax_rb) == rb_intern("proto3")) {
|
628
|
+
syntax = UPB_SYNTAX_PROTO3;
|
629
|
+
} else if (SYM2ID(syntax_rb) == rb_intern("proto2")) {
|
630
|
+
syntax = UPB_SYNTAX_PROTO2;
|
631
|
+
} else {
|
632
|
+
rb_raise(rb_eArgError, "Expected :proto3 or :proto3, received '%s'",
|
633
|
+
rb_id2name(SYM2ID(syntax_rb)));
|
634
|
+
}
|
635
|
+
|
636
|
+
CHECK_UPB(upb_filedef_setsyntax(self->filedef, syntax, &status),
|
637
|
+
"Error setting file syntax for proto");
|
638
|
+
return Qnil;
|
639
|
+
}
|
640
|
+
|
475
641
|
// -----------------------------------------------------------------------------
|
476
642
|
// FieldDescriptor.
|
477
643
|
// -----------------------------------------------------------------------------
|
@@ -511,6 +677,8 @@ void FieldDescriptor_register(VALUE module) {
|
|
511
677
|
rb_define_method(klass, "name=", FieldDescriptor_name_set, 1);
|
512
678
|
rb_define_method(klass, "type", FieldDescriptor_type, 0);
|
513
679
|
rb_define_method(klass, "type=", FieldDescriptor_type_set, 1);
|
680
|
+
rb_define_method(klass, "default", FieldDescriptor_default, 0);
|
681
|
+
rb_define_method(klass, "default=", FieldDescriptor_default_set, 1);
|
514
682
|
rb_define_method(klass, "label", FieldDescriptor_label, 0);
|
515
683
|
rb_define_method(klass, "label=", FieldDescriptor_label_set, 1);
|
516
684
|
rb_define_method(klass, "number", FieldDescriptor_number, 0);
|
@@ -518,10 +686,12 @@ void FieldDescriptor_register(VALUE module) {
|
|
518
686
|
rb_define_method(klass, "submsg_name", FieldDescriptor_submsg_name, 0);
|
519
687
|
rb_define_method(klass, "submsg_name=", FieldDescriptor_submsg_name_set, 1);
|
520
688
|
rb_define_method(klass, "subtype", FieldDescriptor_subtype, 0);
|
689
|
+
rb_define_method(klass, "has?", FieldDescriptor_has, 1);
|
690
|
+
rb_define_method(klass, "clear", FieldDescriptor_clear, 1);
|
521
691
|
rb_define_method(klass, "get", FieldDescriptor_get, 1);
|
522
692
|
rb_define_method(klass, "set", FieldDescriptor_set, 2);
|
523
|
-
cFieldDescriptor = klass;
|
524
693
|
rb_gc_register_address(&cFieldDescriptor);
|
694
|
+
cFieldDescriptor = klass;
|
525
695
|
}
|
526
696
|
|
527
697
|
/*
|
@@ -693,6 +863,71 @@ VALUE FieldDescriptor_type_set(VALUE _self, VALUE type) {
|
|
693
863
|
return Qnil;
|
694
864
|
}
|
695
865
|
|
866
|
+
/*
|
867
|
+
* call-seq:
|
868
|
+
* FieldDescriptor.default => default
|
869
|
+
*
|
870
|
+
* Returns this field's default, as a Ruby object, or nil if not yet set.
|
871
|
+
*/
|
872
|
+
VALUE FieldDescriptor_default(VALUE _self) {
|
873
|
+
DEFINE_SELF(FieldDescriptor, self, _self);
|
874
|
+
return layout_get_default(self->fielddef);
|
875
|
+
}
|
876
|
+
|
877
|
+
/*
|
878
|
+
* call-seq:
|
879
|
+
* FieldDescriptor.default = default
|
880
|
+
*
|
881
|
+
* Sets this field's default value. Raises an exception when calling with
|
882
|
+
* proto syntax 3.
|
883
|
+
*/
|
884
|
+
VALUE FieldDescriptor_default_set(VALUE _self, VALUE default_value) {
|
885
|
+
DEFINE_SELF(FieldDescriptor, self, _self);
|
886
|
+
upb_fielddef* mut_def = check_field_notfrozen(self->fielddef);
|
887
|
+
|
888
|
+
switch (upb_fielddef_type(mut_def)) {
|
889
|
+
case UPB_TYPE_FLOAT:
|
890
|
+
upb_fielddef_setdefaultfloat(mut_def, NUM2DBL(default_value));
|
891
|
+
break;
|
892
|
+
case UPB_TYPE_DOUBLE:
|
893
|
+
upb_fielddef_setdefaultdouble(mut_def, NUM2DBL(default_value));
|
894
|
+
break;
|
895
|
+
case UPB_TYPE_BOOL:
|
896
|
+
if (!RB_TYPE_P(default_value, T_TRUE) &&
|
897
|
+
!RB_TYPE_P(default_value, T_FALSE) &&
|
898
|
+
!RB_TYPE_P(default_value, T_NIL)) {
|
899
|
+
rb_raise(cTypeError, "Expected boolean for default value.");
|
900
|
+
}
|
901
|
+
|
902
|
+
upb_fielddef_setdefaultbool(mut_def, RTEST(default_value));
|
903
|
+
break;
|
904
|
+
case UPB_TYPE_ENUM:
|
905
|
+
case UPB_TYPE_INT32:
|
906
|
+
upb_fielddef_setdefaultint32(mut_def, NUM2INT(default_value));
|
907
|
+
break;
|
908
|
+
case UPB_TYPE_INT64:
|
909
|
+
upb_fielddef_setdefaultint64(mut_def, NUM2INT(default_value));
|
910
|
+
break;
|
911
|
+
case UPB_TYPE_UINT32:
|
912
|
+
upb_fielddef_setdefaultuint32(mut_def, NUM2UINT(default_value));
|
913
|
+
break;
|
914
|
+
case UPB_TYPE_UINT64:
|
915
|
+
upb_fielddef_setdefaultuint64(mut_def, NUM2UINT(default_value));
|
916
|
+
break;
|
917
|
+
case UPB_TYPE_STRING:
|
918
|
+
case UPB_TYPE_BYTES:
|
919
|
+
CHECK_UPB(upb_fielddef_setdefaultcstr(mut_def, StringValuePtr(default_value),
|
920
|
+
&status),
|
921
|
+
"Error setting default string");
|
922
|
+
break;
|
923
|
+
default:
|
924
|
+
rb_raise(rb_eArgError, "Defaults not supported on field %s.%s",
|
925
|
+
upb_fielddef_fullname(mut_def), upb_fielddef_name(mut_def));
|
926
|
+
}
|
927
|
+
|
928
|
+
return Qnil;
|
929
|
+
}
|
930
|
+
|
696
931
|
/*
|
697
932
|
* call-seq:
|
698
933
|
* FieldDescriptor.label => label
|
@@ -814,7 +1049,7 @@ VALUE FieldDescriptor_submsg_name_set(VALUE _self, VALUE value) {
|
|
814
1049
|
upb_fielddef* mut_def = check_field_notfrozen(self->fielddef);
|
815
1050
|
const char* str = get_str(value);
|
816
1051
|
if (!upb_fielddef_hassubdef(self->fielddef)) {
|
817
|
-
rb_raise(
|
1052
|
+
rb_raise(cTypeError, "FieldDescriptor does not have subdef.");
|
818
1053
|
}
|
819
1054
|
CHECK_UPB(upb_fielddef_setsubdefname(mut_def, str, &status),
|
820
1055
|
"Error setting submessage name");
|
@@ -856,11 +1091,49 @@ VALUE FieldDescriptor_get(VALUE _self, VALUE msg_rb) {
|
|
856
1091
|
MessageHeader* msg;
|
857
1092
|
TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg);
|
858
1093
|
if (msg->descriptor->msgdef != upb_fielddef_containingtype(self->fielddef)) {
|
859
|
-
rb_raise(
|
1094
|
+
rb_raise(cTypeError, "get method called on wrong message type");
|
860
1095
|
}
|
861
1096
|
return layout_get(msg->descriptor->layout, Message_data(msg), self->fielddef);
|
862
1097
|
}
|
863
1098
|
|
1099
|
+
/*
|
1100
|
+
* call-seq:
|
1101
|
+
* FieldDescriptor.has?(message) => boolean
|
1102
|
+
*
|
1103
|
+
* Returns whether the value is set on the given message. Raises an
|
1104
|
+
* exception when calling with proto syntax 3.
|
1105
|
+
*/
|
1106
|
+
VALUE FieldDescriptor_has(VALUE _self, VALUE msg_rb) {
|
1107
|
+
DEFINE_SELF(FieldDescriptor, self, _self);
|
1108
|
+
MessageHeader* msg;
|
1109
|
+
TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg);
|
1110
|
+
if (msg->descriptor->msgdef != upb_fielddef_containingtype(self->fielddef)) {
|
1111
|
+
rb_raise(cTypeError, "has method called on wrong message type");
|
1112
|
+
} else if (!upb_fielddef_haspresence(self->fielddef)) {
|
1113
|
+
rb_raise(rb_eArgError, "does not track presence");
|
1114
|
+
}
|
1115
|
+
|
1116
|
+
return layout_has(msg->descriptor->layout, Message_data(msg), self->fielddef);
|
1117
|
+
}
|
1118
|
+
|
1119
|
+
/*
|
1120
|
+
* call-seq:
|
1121
|
+
* FieldDescriptor.clear(message)
|
1122
|
+
*
|
1123
|
+
* Clears the field from the message if it's set.
|
1124
|
+
*/
|
1125
|
+
VALUE FieldDescriptor_clear(VALUE _self, VALUE msg_rb) {
|
1126
|
+
DEFINE_SELF(FieldDescriptor, self, _self);
|
1127
|
+
MessageHeader* msg;
|
1128
|
+
TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg);
|
1129
|
+
if (msg->descriptor->msgdef != upb_fielddef_containingtype(self->fielddef)) {
|
1130
|
+
rb_raise(cTypeError, "has method called on wrong message type");
|
1131
|
+
}
|
1132
|
+
|
1133
|
+
layout_clear(msg->descriptor->layout, Message_data(msg), self->fielddef);
|
1134
|
+
return Qnil;
|
1135
|
+
}
|
1136
|
+
|
864
1137
|
/*
|
865
1138
|
* call-seq:
|
866
1139
|
* FieldDescriptor.set(message, value)
|
@@ -874,7 +1147,7 @@ VALUE FieldDescriptor_set(VALUE _self, VALUE msg_rb, VALUE value) {
|
|
874
1147
|
MessageHeader* msg;
|
875
1148
|
TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg);
|
876
1149
|
if (msg->descriptor->msgdef != upb_fielddef_containingtype(self->fielddef)) {
|
877
|
-
rb_raise(
|
1150
|
+
rb_raise(cTypeError, "set method called on wrong message type");
|
878
1151
|
}
|
879
1152
|
layout_set(msg->descriptor->layout, Message_data(msg), self->fielddef, value);
|
880
1153
|
return Qnil;
|
@@ -918,8 +1191,8 @@ void OneofDescriptor_register(VALUE module) {
|
|
918
1191
|
rb_define_method(klass, "add_field", OneofDescriptor_add_field, 1);
|
919
1192
|
rb_define_method(klass, "each", OneofDescriptor_each, 0);
|
920
1193
|
rb_include_module(klass, rb_mEnumerable);
|
921
|
-
cOneofDescriptor = klass;
|
922
1194
|
rb_gc_register_address(&cOneofDescriptor);
|
1195
|
+
cOneofDescriptor = klass;
|
923
1196
|
}
|
924
1197
|
|
925
1198
|
/*
|
@@ -1031,6 +1304,7 @@ void EnumDescriptor_register(VALUE module) {
|
|
1031
1304
|
VALUE klass = rb_define_class_under(
|
1032
1305
|
module, "EnumDescriptor", rb_cObject);
|
1033
1306
|
rb_define_alloc_func(klass, EnumDescriptor_alloc);
|
1307
|
+
rb_define_method(klass, "initialize", EnumDescriptor_initialize, 1);
|
1034
1308
|
rb_define_method(klass, "name", EnumDescriptor_name, 0);
|
1035
1309
|
rb_define_method(klass, "name=", EnumDescriptor_name_set, 1);
|
1036
1310
|
rb_define_method(klass, "add_value", EnumDescriptor_add_value, 2);
|
@@ -1038,9 +1312,39 @@ void EnumDescriptor_register(VALUE module) {
|
|
1038
1312
|
rb_define_method(klass, "lookup_value", EnumDescriptor_lookup_value, 1);
|
1039
1313
|
rb_define_method(klass, "each", EnumDescriptor_each, 0);
|
1040
1314
|
rb_define_method(klass, "enummodule", EnumDescriptor_enummodule, 0);
|
1315
|
+
rb_define_method(klass, "file_descriptor", EnumDescriptor_file_descriptor, 0);
|
1041
1316
|
rb_include_module(klass, rb_mEnumerable);
|
1042
|
-
cEnumDescriptor = klass;
|
1043
1317
|
rb_gc_register_address(&cEnumDescriptor);
|
1318
|
+
cEnumDescriptor = klass;
|
1319
|
+
}
|
1320
|
+
|
1321
|
+
/*
|
1322
|
+
* call-seq:
|
1323
|
+
* Descriptor.new(file_descriptor)
|
1324
|
+
*
|
1325
|
+
* Initializes a new descriptor and assigns a file descriptor to it.
|
1326
|
+
*/
|
1327
|
+
VALUE EnumDescriptor_initialize(VALUE _self, VALUE file_descriptor_rb) {
|
1328
|
+
DEFINE_SELF(EnumDescriptor, self, _self);
|
1329
|
+
FileDescriptor* file_descriptor = ruby_to_FileDescriptor(file_descriptor_rb);
|
1330
|
+
CHECK_UPB(
|
1331
|
+
upb_filedef_addenum(file_descriptor->filedef, self->enumdef,
|
1332
|
+
NULL, &status),
|
1333
|
+
"Failed to associate enum to file descriptor.");
|
1334
|
+
add_def_obj(file_descriptor->filedef, file_descriptor_rb);
|
1335
|
+
|
1336
|
+
return Qnil;
|
1337
|
+
}
|
1338
|
+
|
1339
|
+
/*
|
1340
|
+
* call-seq:
|
1341
|
+
* Descriptor.file_descriptor
|
1342
|
+
*
|
1343
|
+
* Returns the FileDescriptor object this enum belongs to.
|
1344
|
+
*/
|
1345
|
+
VALUE EnumDescriptor_file_descriptor(VALUE _self) {
|
1346
|
+
DEFINE_SELF(EnumDescriptor, self, _self);
|
1347
|
+
return get_def_obj(upb_def_file(self->enumdef));
|
1044
1348
|
}
|
1045
1349
|
|
1046
1350
|
/*
|
@@ -1204,8 +1508,8 @@ void MessageBuilderContext_register(VALUE module) {
|
|
1204
1508
|
rb_define_method(klass, "repeated", MessageBuilderContext_repeated, -1);
|
1205
1509
|
rb_define_method(klass, "map", MessageBuilderContext_map, -1);
|
1206
1510
|
rb_define_method(klass, "oneof", MessageBuilderContext_oneof, 1);
|
1207
|
-
cMessageBuilderContext = klass;
|
1208
1511
|
rb_gc_register_address(&cMessageBuilderContext);
|
1512
|
+
cMessageBuilderContext = klass;
|
1209
1513
|
}
|
1210
1514
|
|
1211
1515
|
/*
|
@@ -1225,34 +1529,56 @@ VALUE MessageBuilderContext_initialize(VALUE _self,
|
|
1225
1529
|
return Qnil;
|
1226
1530
|
}
|
1227
1531
|
|
1228
|
-
static VALUE msgdef_add_field(VALUE
|
1532
|
+
static VALUE msgdef_add_field(VALUE msgdef_rb,
|
1229
1533
|
const char* label, VALUE name,
|
1230
1534
|
VALUE type, VALUE number,
|
1231
|
-
VALUE type_class
|
1232
|
-
|
1535
|
+
VALUE type_class,
|
1536
|
+
VALUE options) {
|
1537
|
+
VALUE fielddef_rb = rb_class_new_instance(0, NULL, cFieldDescriptor);
|
1233
1538
|
VALUE name_str = rb_str_new2(rb_id2name(SYM2ID(name)));
|
1234
1539
|
|
1235
|
-
rb_funcall(
|
1236
|
-
rb_funcall(
|
1237
|
-
rb_funcall(
|
1238
|
-
rb_funcall(
|
1540
|
+
rb_funcall(fielddef_rb, rb_intern("label="), 1, ID2SYM(rb_intern(label)));
|
1541
|
+
rb_funcall(fielddef_rb, rb_intern("name="), 1, name_str);
|
1542
|
+
rb_funcall(fielddef_rb, rb_intern("type="), 1, type);
|
1543
|
+
rb_funcall(fielddef_rb, rb_intern("number="), 1, number);
|
1239
1544
|
|
1240
1545
|
if (type_class != Qnil) {
|
1241
|
-
|
1242
|
-
|
1243
|
-
}
|
1546
|
+
Check_Type(type_class, T_STRING);
|
1547
|
+
|
1244
1548
|
// Make it an absolute type name by prepending a dot.
|
1245
1549
|
type_class = rb_str_append(rb_str_new2("."), type_class);
|
1246
|
-
rb_funcall(
|
1550
|
+
rb_funcall(fielddef_rb, rb_intern("submsg_name="), 1, type_class);
|
1247
1551
|
}
|
1248
1552
|
|
1249
|
-
|
1250
|
-
|
1553
|
+
if (options != Qnil) {
|
1554
|
+
Check_Type(options, T_HASH);
|
1555
|
+
|
1556
|
+
if (rb_funcall(options, rb_intern("key?"), 1,
|
1557
|
+
ID2SYM(rb_intern("default"))) == Qtrue) {
|
1558
|
+
Descriptor* msgdef = ruby_to_Descriptor(msgdef_rb);
|
1559
|
+
if (upb_msgdef_syntax((upb_msgdef*)msgdef->msgdef) == UPB_SYNTAX_PROTO3) {
|
1560
|
+
rb_raise(rb_eArgError, "Cannot set :default when using proto3 syntax.");
|
1561
|
+
}
|
1562
|
+
|
1563
|
+
FieldDescriptor* fielddef = ruby_to_FieldDescriptor(fielddef_rb);
|
1564
|
+
if (!upb_fielddef_haspresence((upb_fielddef*)fielddef->fielddef) ||
|
1565
|
+
upb_fielddef_issubmsg((upb_fielddef*)fielddef->fielddef)) {
|
1566
|
+
rb_raise(rb_eArgError, "Cannot set :default on this kind of field.");
|
1567
|
+
}
|
1568
|
+
|
1569
|
+
rb_funcall(fielddef_rb, rb_intern("default="), 1,
|
1570
|
+
rb_hash_lookup(options, ID2SYM(rb_intern("default"))));
|
1571
|
+
}
|
1572
|
+
}
|
1573
|
+
|
1574
|
+
rb_funcall(msgdef_rb, rb_intern("add_field"), 1, fielddef_rb);
|
1575
|
+
return fielddef_rb;
|
1251
1576
|
}
|
1252
1577
|
|
1253
1578
|
/*
|
1254
1579
|
* call-seq:
|
1255
|
-
* MessageBuilderContext.optional(name, type, number, type_class = nil
|
1580
|
+
* MessageBuilderContext.optional(name, type, number, type_class = nil,
|
1581
|
+
* options = nil)
|
1256
1582
|
*
|
1257
1583
|
* Defines a new optional field on this message type with the given type, tag
|
1258
1584
|
* number, and type class (for message and enum fields). The type must be a Ruby
|
@@ -1261,23 +1587,26 @@ static VALUE msgdef_add_field(VALUE msgdef,
|
|
1261
1587
|
*/
|
1262
1588
|
VALUE MessageBuilderContext_optional(int argc, VALUE* argv, VALUE _self) {
|
1263
1589
|
DEFINE_SELF(MessageBuilderContext, self, _self);
|
1264
|
-
VALUE name, type, number
|
1590
|
+
VALUE name, type, number;
|
1591
|
+
VALUE type_class, options = Qnil;
|
1265
1592
|
|
1266
|
-
|
1267
|
-
|
1593
|
+
rb_scan_args(argc, argv, "32", &name, &type, &number, &type_class, &options);
|
1594
|
+
|
1595
|
+
// Allow passing (name, type, number, options) or
|
1596
|
+
// (name, type, number, type_class, options)
|
1597
|
+
if (argc == 4 && RB_TYPE_P(type_class, T_HASH)) {
|
1598
|
+
options = type_class;
|
1599
|
+
type_class = Qnil;
|
1268
1600
|
}
|
1269
|
-
name = argv[0];
|
1270
|
-
type = argv[1];
|
1271
|
-
number = argv[2];
|
1272
|
-
type_class = (argc > 3) ? argv[3] : Qnil;
|
1273
1601
|
|
1274
1602
|
return msgdef_add_field(self->descriptor, "optional",
|
1275
|
-
name, type, number, type_class);
|
1603
|
+
name, type, number, type_class, options);
|
1276
1604
|
}
|
1277
1605
|
|
1278
1606
|
/*
|
1279
1607
|
* call-seq:
|
1280
|
-
* MessageBuilderContext.required(name, type, number, type_class = nil
|
1608
|
+
* MessageBuilderContext.required(name, type, number, type_class = nil,
|
1609
|
+
* options = nil)
|
1281
1610
|
*
|
1282
1611
|
* Defines a new required field on this message type with the given type, tag
|
1283
1612
|
* number, and type class (for message and enum fields). The type must be a Ruby
|
@@ -1290,18 +1619,20 @@ VALUE MessageBuilderContext_optional(int argc, VALUE* argv, VALUE _self) {
|
|
1290
1619
|
*/
|
1291
1620
|
VALUE MessageBuilderContext_required(int argc, VALUE* argv, VALUE _self) {
|
1292
1621
|
DEFINE_SELF(MessageBuilderContext, self, _self);
|
1293
|
-
VALUE name, type, number
|
1622
|
+
VALUE name, type, number;
|
1623
|
+
VALUE type_class, options = Qnil;
|
1294
1624
|
|
1295
|
-
|
1296
|
-
|
1625
|
+
rb_scan_args(argc, argv, "32", &name, &type, &number, &type_class, &options);
|
1626
|
+
|
1627
|
+
// Allow passing (name, type, number, options) or
|
1628
|
+
// (name, type, number, type_class, options)
|
1629
|
+
if (argc == 4 && RB_TYPE_P(type_class, T_HASH)) {
|
1630
|
+
options = type_class;
|
1631
|
+
type_class = Qnil;
|
1297
1632
|
}
|
1298
|
-
name = argv[0];
|
1299
|
-
type = argv[1];
|
1300
|
-
number = argv[2];
|
1301
|
-
type_class = (argc > 3) ? argv[3] : Qnil;
|
1302
1633
|
|
1303
1634
|
return msgdef_add_field(self->descriptor, "required",
|
1304
|
-
name, type, number, type_class);
|
1635
|
+
name, type, number, type_class, options);
|
1305
1636
|
}
|
1306
1637
|
|
1307
1638
|
/*
|
@@ -1326,7 +1657,7 @@ VALUE MessageBuilderContext_repeated(int argc, VALUE* argv, VALUE _self) {
|
|
1326
1657
|
type_class = (argc > 3) ? argv[3] : Qnil;
|
1327
1658
|
|
1328
1659
|
return msgdef_add_field(self->descriptor, "repeated",
|
1329
|
-
name, type, number, type_class);
|
1660
|
+
name, type, number, type_class, Qnil);
|
1330
1661
|
}
|
1331
1662
|
|
1332
1663
|
/*
|
@@ -1367,9 +1698,17 @@ VALUE MessageBuilderContext_map(int argc, VALUE* argv, VALUE _self) {
|
|
1367
1698
|
"type.");
|
1368
1699
|
}
|
1369
1700
|
|
1701
|
+
Descriptor* descriptor = ruby_to_Descriptor(self->descriptor);
|
1702
|
+
if (upb_msgdef_syntax(descriptor->msgdef) == UPB_SYNTAX_PROTO2) {
|
1703
|
+
rb_raise(rb_eArgError,
|
1704
|
+
"Cannot add a native map field using proto2 syntax.");
|
1705
|
+
}
|
1706
|
+
|
1370
1707
|
// Create a new message descriptor for the map entry message, and create a
|
1371
1708
|
// repeated submessage field here with that type.
|
1372
|
-
|
1709
|
+
VALUE file_descriptor_rb =
|
1710
|
+
rb_funcall(self->descriptor, rb_intern("file_descriptor"), 0);
|
1711
|
+
mapentry_desc = rb_class_new_instance(1, &file_descriptor_rb, cDescriptor);
|
1373
1712
|
mapentry_desc_name = rb_funcall(self->descriptor, rb_intern("name"), 0);
|
1374
1713
|
mapentry_desc_name = rb_str_cat2(mapentry_desc_name, "_MapEntry_");
|
1375
1714
|
mapentry_desc_name = rb_str_cat2(mapentry_desc_name,
|
@@ -1412,8 +1751,8 @@ VALUE MessageBuilderContext_map(int argc, VALUE* argv, VALUE _self) {
|
|
1412
1751
|
{
|
1413
1752
|
// Add the map-entry message type to the current builder, and use the type
|
1414
1753
|
// to create the map field itself.
|
1415
|
-
Builder*
|
1416
|
-
rb_ary_push(
|
1754
|
+
Builder* builder = ruby_to_Builder(self->builder);
|
1755
|
+
rb_ary_push(builder->pending_list, mapentry_desc);
|
1417
1756
|
}
|
1418
1757
|
|
1419
1758
|
{
|
@@ -1493,8 +1832,8 @@ void OneofBuilderContext_register(VALUE module) {
|
|
1493
1832
|
rb_define_method(klass, "initialize",
|
1494
1833
|
OneofBuilderContext_initialize, 2);
|
1495
1834
|
rb_define_method(klass, "optional", OneofBuilderContext_optional, -1);
|
1496
|
-
cOneofBuilderContext = klass;
|
1497
1835
|
rb_gc_register_address(&cOneofBuilderContext);
|
1836
|
+
cOneofBuilderContext = klass;
|
1498
1837
|
}
|
1499
1838
|
|
1500
1839
|
/*
|
@@ -1516,7 +1855,8 @@ VALUE OneofBuilderContext_initialize(VALUE _self,
|
|
1516
1855
|
|
1517
1856
|
/*
|
1518
1857
|
* call-seq:
|
1519
|
-
* OneofBuilderContext.optional(name, type, number, type_class = nil
|
1858
|
+
* OneofBuilderContext.optional(name, type, number, type_class = nil,
|
1859
|
+
* default_value = nil)
|
1520
1860
|
*
|
1521
1861
|
* Defines a new optional field in this oneof with the given type, tag number,
|
1522
1862
|
* and type class (for message and enum fields). The type must be a Ruby symbol
|
@@ -1525,18 +1865,13 @@ VALUE OneofBuilderContext_initialize(VALUE _self,
|
|
1525
1865
|
*/
|
1526
1866
|
VALUE OneofBuilderContext_optional(int argc, VALUE* argv, VALUE _self) {
|
1527
1867
|
DEFINE_SELF(OneofBuilderContext, self, _self);
|
1528
|
-
VALUE name, type, number
|
1868
|
+
VALUE name, type, number;
|
1869
|
+
VALUE type_class, options = Qnil;
|
1529
1870
|
|
1530
|
-
|
1531
|
-
rb_raise(rb_eArgError, "Expected at least 3 arguments.");
|
1532
|
-
}
|
1533
|
-
name = argv[0];
|
1534
|
-
type = argv[1];
|
1535
|
-
number = argv[2];
|
1536
|
-
type_class = (argc > 3) ? argv[3] : Qnil;
|
1871
|
+
rb_scan_args(argc, argv, "32", &name, &type, &number, &type_class, &options);
|
1537
1872
|
|
1538
1873
|
return msgdef_add_field(self->descriptor, "optional",
|
1539
|
-
name, type, number, type_class);
|
1874
|
+
name, type, number, type_class, options);
|
1540
1875
|
}
|
1541
1876
|
|
1542
1877
|
// -----------------------------------------------------------------------------
|
@@ -1571,8 +1906,8 @@ void EnumBuilderContext_register(VALUE module) {
|
|
1571
1906
|
rb_define_method(klass, "initialize",
|
1572
1907
|
EnumBuilderContext_initialize, 1);
|
1573
1908
|
rb_define_method(klass, "value", EnumBuilderContext_value, 2);
|
1574
|
-
cEnumBuilderContext = klass;
|
1575
1909
|
rb_gc_register_address(&cEnumBuilderContext);
|
1910
|
+
cEnumBuilderContext = klass;
|
1576
1911
|
}
|
1577
1912
|
|
1578
1913
|
/*
|
@@ -1606,6 +1941,112 @@ VALUE EnumBuilderContext_value(VALUE _self, VALUE name, VALUE number) {
|
|
1606
1941
|
return enumdef_add_value(self->enumdesc, name, number);
|
1607
1942
|
}
|
1608
1943
|
|
1944
|
+
|
1945
|
+
// -----------------------------------------------------------------------------
|
1946
|
+
// FileBuilderContext.
|
1947
|
+
// -----------------------------------------------------------------------------
|
1948
|
+
|
1949
|
+
DEFINE_CLASS(FileBuilderContext,
|
1950
|
+
"Google::Protobuf::Internal::FileBuilderContext");
|
1951
|
+
|
1952
|
+
void FileBuilderContext_mark(void* _self) {
|
1953
|
+
FileBuilderContext* self = _self;
|
1954
|
+
rb_gc_mark(self->pending_list);
|
1955
|
+
rb_gc_mark(self->file_descriptor);
|
1956
|
+
rb_gc_mark(self->builder);
|
1957
|
+
}
|
1958
|
+
|
1959
|
+
void FileBuilderContext_free(void* _self) {
|
1960
|
+
FileBuilderContext* self = _self;
|
1961
|
+
xfree(self);
|
1962
|
+
}
|
1963
|
+
|
1964
|
+
VALUE FileBuilderContext_alloc(VALUE klass) {
|
1965
|
+
FileBuilderContext* self = ALLOC(FileBuilderContext);
|
1966
|
+
VALUE ret = TypedData_Wrap_Struct(klass, &_FileBuilderContext_type, self);
|
1967
|
+
self->pending_list = Qnil;
|
1968
|
+
self->file_descriptor = Qnil;
|
1969
|
+
self->builder = Qnil;
|
1970
|
+
return ret;
|
1971
|
+
}
|
1972
|
+
|
1973
|
+
void FileBuilderContext_register(VALUE module) {
|
1974
|
+
VALUE klass = rb_define_class_under(module, "FileBuilderContext", rb_cObject);
|
1975
|
+
rb_define_alloc_func(klass, FileBuilderContext_alloc);
|
1976
|
+
rb_define_method(klass, "initialize", FileBuilderContext_initialize, 2);
|
1977
|
+
rb_define_method(klass, "add_message", FileBuilderContext_add_message, 1);
|
1978
|
+
rb_define_method(klass, "add_enum", FileBuilderContext_add_enum, 1);
|
1979
|
+
rb_gc_register_address(&cFileBuilderContext);
|
1980
|
+
cFileBuilderContext = klass;
|
1981
|
+
}
|
1982
|
+
|
1983
|
+
/*
|
1984
|
+
* call-seq:
|
1985
|
+
* FileBuilderContext.new(file_descriptor, builder) => context
|
1986
|
+
*
|
1987
|
+
* Create a new file builder context for the given file descriptor and
|
1988
|
+
* builder context. This class is intended to serve as a DSL context to be used
|
1989
|
+
* with #instance_eval.
|
1990
|
+
*/
|
1991
|
+
VALUE FileBuilderContext_initialize(VALUE _self, VALUE file_descriptor,
|
1992
|
+
VALUE builder) {
|
1993
|
+
DEFINE_SELF(FileBuilderContext, self, _self);
|
1994
|
+
self->pending_list = rb_ary_new();
|
1995
|
+
self->file_descriptor = file_descriptor;
|
1996
|
+
self->builder = builder;
|
1997
|
+
return Qnil;
|
1998
|
+
}
|
1999
|
+
|
2000
|
+
/*
|
2001
|
+
* call-seq:
|
2002
|
+
* FileBuilderContext.add_message(name, &block)
|
2003
|
+
*
|
2004
|
+
* Creates a new, empty descriptor with the given name, and invokes the block in
|
2005
|
+
* the context of a MessageBuilderContext on that descriptor. The block can then
|
2006
|
+
* call, e.g., MessageBuilderContext#optional and MessageBuilderContext#repeated
|
2007
|
+
* methods to define the message fields.
|
2008
|
+
*
|
2009
|
+
* This is the recommended, idiomatic way to build message definitions.
|
2010
|
+
*/
|
2011
|
+
VALUE FileBuilderContext_add_message(VALUE _self, VALUE name) {
|
2012
|
+
DEFINE_SELF(FileBuilderContext, self, _self);
|
2013
|
+
VALUE msgdef = rb_class_new_instance(1, &self->file_descriptor, cDescriptor);
|
2014
|
+
VALUE args[2] = { msgdef, self->builder };
|
2015
|
+
VALUE ctx = rb_class_new_instance(2, args, cMessageBuilderContext);
|
2016
|
+
VALUE block = rb_block_proc();
|
2017
|
+
rb_funcall(msgdef, rb_intern("name="), 1, name);
|
2018
|
+
rb_funcall_with_block(ctx, rb_intern("instance_eval"), 0, NULL, block);
|
2019
|
+
rb_ary_push(self->pending_list, msgdef);
|
2020
|
+
return Qnil;
|
2021
|
+
}
|
2022
|
+
|
2023
|
+
/*
|
2024
|
+
* call-seq:
|
2025
|
+
* FileBuilderContext.add_enum(name, &block)
|
2026
|
+
*
|
2027
|
+
* Creates a new, empty enum descriptor with the given name, and invokes the
|
2028
|
+
* block in the context of an EnumBuilderContext on that descriptor. The block
|
2029
|
+
* can then call EnumBuilderContext#add_value to define the enum values.
|
2030
|
+
*
|
2031
|
+
* This is the recommended, idiomatic way to build enum definitions.
|
2032
|
+
*/
|
2033
|
+
VALUE FileBuilderContext_add_enum(VALUE _self, VALUE name) {
|
2034
|
+
DEFINE_SELF(FileBuilderContext, self, _self);
|
2035
|
+
VALUE enumdef =
|
2036
|
+
rb_class_new_instance(1, &self->file_descriptor, cEnumDescriptor);
|
2037
|
+
VALUE ctx = rb_class_new_instance(1, &enumdef, cEnumBuilderContext);
|
2038
|
+
VALUE block = rb_block_proc();
|
2039
|
+
rb_funcall(enumdef, rb_intern("name="), 1, name);
|
2040
|
+
rb_funcall_with_block(ctx, rb_intern("instance_eval"), 0, NULL, block);
|
2041
|
+
rb_ary_push(self->pending_list, enumdef);
|
2042
|
+
return Qnil;
|
2043
|
+
}
|
2044
|
+
|
2045
|
+
VALUE FileBuilderContext_pending_descriptors(VALUE _self) {
|
2046
|
+
DEFINE_SELF(FileBuilderContext, self, _self);
|
2047
|
+
return self->pending_list;
|
2048
|
+
}
|
2049
|
+
|
1609
2050
|
// -----------------------------------------------------------------------------
|
1610
2051
|
// Builder.
|
1611
2052
|
// -----------------------------------------------------------------------------
|
@@ -1615,6 +2056,7 @@ DEFINE_CLASS(Builder, "Google::Protobuf::Internal::Builder");
|
|
1615
2056
|
void Builder_mark(void* _self) {
|
1616
2057
|
Builder* self = _self;
|
1617
2058
|
rb_gc_mark(self->pending_list);
|
2059
|
+
rb_gc_mark(self->default_file_descriptor);
|
1618
2060
|
}
|
1619
2061
|
|
1620
2062
|
void Builder_free(void* _self) {
|
@@ -1635,35 +2077,78 @@ VALUE Builder_alloc(VALUE klass) {
|
|
1635
2077
|
Builder* self = ALLOC(Builder);
|
1636
2078
|
VALUE ret = TypedData_Wrap_Struct(
|
1637
2079
|
klass, &_Builder_type, self);
|
1638
|
-
self->pending_list =
|
2080
|
+
self->pending_list = Qnil;
|
1639
2081
|
self->defs = NULL;
|
2082
|
+
self->default_file_descriptor = Qnil;
|
1640
2083
|
return ret;
|
1641
2084
|
}
|
1642
2085
|
|
1643
2086
|
void Builder_register(VALUE module) {
|
1644
2087
|
VALUE klass = rb_define_class_under(module, "Builder", rb_cObject);
|
1645
2088
|
rb_define_alloc_func(klass, Builder_alloc);
|
2089
|
+
rb_define_method(klass, "initialize", Builder_initialize, 0);
|
2090
|
+
rb_define_method(klass, "add_file", Builder_add_file, -1);
|
1646
2091
|
rb_define_method(klass, "add_message", Builder_add_message, 1);
|
1647
2092
|
rb_define_method(klass, "add_enum", Builder_add_enum, 1);
|
1648
2093
|
rb_define_method(klass, "finalize_to_pool", Builder_finalize_to_pool, 1);
|
1649
|
-
cBuilder = klass;
|
1650
2094
|
rb_gc_register_address(&cBuilder);
|
2095
|
+
cBuilder = klass;
|
2096
|
+
}
|
2097
|
+
|
2098
|
+
/*
|
2099
|
+
* call-seq:
|
2100
|
+
* Builder.new
|
2101
|
+
*
|
2102
|
+
* Initializes a new builder.
|
2103
|
+
*/
|
2104
|
+
VALUE Builder_initialize(VALUE _self) {
|
2105
|
+
DEFINE_SELF(Builder, self, _self);
|
2106
|
+
self->pending_list = rb_ary_new();
|
2107
|
+
VALUE file_name = Qnil;
|
2108
|
+
self->default_file_descriptor =
|
2109
|
+
rb_class_new_instance(1, &file_name, cFileDescriptor);
|
2110
|
+
return Qnil;
|
2111
|
+
}
|
2112
|
+
|
2113
|
+
/*
|
2114
|
+
* call-seq:
|
2115
|
+
* Builder.add_file(name, options = nil, &block)
|
2116
|
+
*
|
2117
|
+
* Creates a new, file descriptor with the given name and options and invokes
|
2118
|
+
* the block in the context of a FileBuilderContext on that descriptor. The
|
2119
|
+
* block can then call FileBuilderContext#add_message or
|
2120
|
+
* FileBuilderContext#add_enum to define new messages or enums, respectively.
|
2121
|
+
*
|
2122
|
+
* This is the recommended, idiomatic way to build file descriptors.
|
2123
|
+
*/
|
2124
|
+
VALUE Builder_add_file(int argc, VALUE* argv, VALUE _self) {
|
2125
|
+
DEFINE_SELF(Builder, self, _self);
|
2126
|
+
VALUE file_descriptor = rb_class_new_instance(argc, argv, cFileDescriptor);
|
2127
|
+
VALUE args[2] = { file_descriptor, _self };
|
2128
|
+
VALUE ctx = rb_class_new_instance(2, args, cFileBuilderContext);
|
2129
|
+
VALUE block = rb_block_proc();
|
2130
|
+
rb_funcall_with_block(ctx, rb_intern("instance_eval"), 0, NULL, block);
|
2131
|
+
|
2132
|
+
rb_ary_concat(self->pending_list,
|
2133
|
+
FileBuilderContext_pending_descriptors(ctx));
|
2134
|
+
return Qnil;
|
1651
2135
|
}
|
1652
2136
|
|
1653
2137
|
/*
|
1654
2138
|
* call-seq:
|
1655
2139
|
* Builder.add_message(name, &block)
|
1656
2140
|
*
|
1657
|
-
*
|
1658
|
-
*
|
1659
|
-
* call, e.g., MessageBuilderContext#optional and MessageBuilderContext#repeated
|
1660
|
-
* methods to define the message fields.
|
2141
|
+
* Old and deprecated way to create a new descriptor.
|
2142
|
+
* See FileBuilderContext.add_message for the recommended way.
|
1661
2143
|
*
|
1662
|
-
*
|
2144
|
+
* Exists for backwards compatibility to allow building descriptor pool for
|
2145
|
+
* files generated by protoc which don't add messages within "add_file" block.
|
2146
|
+
* Descriptors created this way get assigned to a default empty FileDescriptor.
|
1663
2147
|
*/
|
1664
2148
|
VALUE Builder_add_message(VALUE _self, VALUE name) {
|
1665
2149
|
DEFINE_SELF(Builder, self, _self);
|
1666
|
-
VALUE msgdef =
|
2150
|
+
VALUE msgdef =
|
2151
|
+
rb_class_new_instance(1, &self->default_file_descriptor, cDescriptor);
|
1667
2152
|
VALUE args[2] = { msgdef, _self };
|
1668
2153
|
VALUE ctx = rb_class_new_instance(2, args, cMessageBuilderContext);
|
1669
2154
|
VALUE block = rb_block_proc();
|
@@ -1677,15 +2162,18 @@ VALUE Builder_add_message(VALUE _self, VALUE name) {
|
|
1677
2162
|
* call-seq:
|
1678
2163
|
* Builder.add_enum(name, &block)
|
1679
2164
|
*
|
1680
|
-
*
|
1681
|
-
*
|
1682
|
-
* can then call EnumBuilderContext#add_value to define the enum values.
|
2165
|
+
* Old and deprecated way to create a new enum descriptor.
|
2166
|
+
* See FileBuilderContext.add_enum for the recommended way.
|
1683
2167
|
*
|
1684
|
-
*
|
2168
|
+
* Exists for backwards compatibility to allow building descriptor pool for
|
2169
|
+
* files generated by protoc which don't add enums within "add_file" block.
|
2170
|
+
* Enum descriptors created this way get assigned to a default empty
|
2171
|
+
* FileDescriptor.
|
1685
2172
|
*/
|
1686
2173
|
VALUE Builder_add_enum(VALUE _self, VALUE name) {
|
1687
2174
|
DEFINE_SELF(Builder, self, _self);
|
1688
|
-
VALUE enumdef =
|
2175
|
+
VALUE enumdef =
|
2176
|
+
rb_class_new_instance(1, &self->default_file_descriptor, cEnumDescriptor);
|
1689
2177
|
VALUE ctx = rb_class_new_instance(1, &enumdef, cEnumBuilderContext);
|
1690
2178
|
VALUE block = rb_block_proc();
|
1691
2179
|
rb_funcall(enumdef, rb_intern("name="), 1, name);
|
@@ -1694,7 +2182,7 @@ VALUE Builder_add_enum(VALUE _self, VALUE name) {
|
|
1694
2182
|
return Qnil;
|
1695
2183
|
}
|
1696
2184
|
|
1697
|
-
static void
|
2185
|
+
static void proto3_validate_msgdef(const upb_msgdef* msgdef) {
|
1698
2186
|
// Verify that no required fields exist. proto3 does not support these.
|
1699
2187
|
upb_msg_field_iter it;
|
1700
2188
|
for (upb_msg_field_begin(&it, msgdef);
|
@@ -1702,17 +2190,17 @@ static void validate_msgdef(const upb_msgdef* msgdef) {
|
|
1702
2190
|
upb_msg_field_next(&it)) {
|
1703
2191
|
const upb_fielddef* field = upb_msg_iter_field(&it);
|
1704
2192
|
if (upb_fielddef_label(field) == UPB_LABEL_REQUIRED) {
|
1705
|
-
rb_raise(
|
2193
|
+
rb_raise(cTypeError, "Required fields are unsupported in proto3.");
|
1706
2194
|
}
|
1707
2195
|
}
|
1708
2196
|
}
|
1709
2197
|
|
1710
|
-
static void
|
2198
|
+
static void proto3_validate_enumdef(const upb_enumdef* enumdef) {
|
1711
2199
|
// Verify that an entry exists with integer value 0. (This is the default
|
1712
2200
|
// value.)
|
1713
2201
|
const char* lookup = upb_enumdef_iton(enumdef, 0);
|
1714
2202
|
if (lookup == NULL) {
|
1715
|
-
rb_raise(
|
2203
|
+
rb_raise(cTypeError,
|
1716
2204
|
"Enum definition does not contain a value for '0'.");
|
1717
2205
|
}
|
1718
2206
|
}
|
@@ -1742,10 +2230,16 @@ VALUE Builder_finalize_to_pool(VALUE _self, VALUE pool_rb) {
|
|
1742
2230
|
VALUE def_rb = rb_ary_entry(self->pending_list, i);
|
1743
2231
|
if (CLASS_OF(def_rb) == cDescriptor) {
|
1744
2232
|
self->defs[i] = (upb_def*)ruby_to_Descriptor(def_rb)->msgdef;
|
1745
|
-
|
2233
|
+
|
2234
|
+
if (upb_filedef_syntax(upb_def_file(self->defs[i])) == UPB_SYNTAX_PROTO3) {
|
2235
|
+
proto3_validate_msgdef((const upb_msgdef*)self->defs[i]);
|
2236
|
+
}
|
1746
2237
|
} else if (CLASS_OF(def_rb) == cEnumDescriptor) {
|
1747
2238
|
self->defs[i] = (upb_def*)ruby_to_EnumDescriptor(def_rb)->enumdef;
|
1748
|
-
|
2239
|
+
|
2240
|
+
if (upb_filedef_syntax(upb_def_file(self->defs[i])) == UPB_SYNTAX_PROTO3) {
|
2241
|
+
proto3_validate_enumdef((const upb_enumdef*)self->defs[i]);
|
2242
|
+
}
|
1749
2243
|
}
|
1750
2244
|
}
|
1751
2245
|
|