google-protobuf 3.15.6 → 3.19.3

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.

@@ -36,13 +36,6 @@
36
36
  #include "message.h"
37
37
  #include "protobuf.h"
38
38
 
39
- static VALUE Builder_build(VALUE _self);
40
-
41
- static VALUE cMessageBuilderContext;
42
- static VALUE cOneofBuilderContext;
43
- static VALUE cEnumBuilderContext;
44
- static VALUE cBuilder;
45
-
46
39
  // -----------------------------------------------------------------------------
47
40
  // Global map from upb {msg,enum}defs to wrapper Descriptor/EnumDescriptor
48
41
  // instances.
@@ -75,167 +68,6 @@ static VALUE rb_str_maybe_null(const char* s) {
75
68
  return rb_str_new2(s);
76
69
  }
77
70
 
78
- // -----------------------------------------------------------------------------
79
- // Backward compatibility code.
80
- // -----------------------------------------------------------------------------
81
-
82
- static void rewrite_enum_default(const upb_symtab* symtab,
83
- google_protobuf_FileDescriptorProto* file,
84
- google_protobuf_FieldDescriptorProto* field) {
85
- upb_strview defaultval;
86
- const char *type_name_str;
87
- char *end;
88
- long val;
89
- const upb_enumdef *e;
90
- upb_strview type_name;
91
-
92
- /* Look for TYPE_ENUM fields that have a default. */
93
- if (google_protobuf_FieldDescriptorProto_type(field) !=
94
- google_protobuf_FieldDescriptorProto_TYPE_ENUM ||
95
- !google_protobuf_FieldDescriptorProto_has_default_value(field) ||
96
- !google_protobuf_FieldDescriptorProto_has_type_name(field)) {
97
- return;
98
- }
99
-
100
- defaultval = google_protobuf_FieldDescriptorProto_default_value(field);
101
- type_name = google_protobuf_FieldDescriptorProto_type_name(field);
102
-
103
- if (defaultval.size == 0 || !isdigit(defaultval.data[0])) {
104
- return;
105
- }
106
-
107
- if (type_name.size == 0 || type_name.data[0] != '.') {
108
- return;
109
- }
110
-
111
- type_name_str = type_name.data + 1;
112
-
113
- errno = 0;
114
- val = strtol(defaultval.data, &end, 10);
115
-
116
- if (errno != 0 || *end != 0 || val < INT32_MIN || val > INT32_MAX) {
117
- return;
118
- }
119
-
120
- /* Now find the corresponding enum definition. */
121
- e = upb_symtab_lookupenum(symtab, type_name_str);
122
- if (e) {
123
- /* Look in previously loaded files. */
124
- const char *label = upb_enumdef_iton(e, val);
125
- if (!label) {
126
- return;
127
- }
128
- google_protobuf_FieldDescriptorProto_set_default_value(
129
- field, upb_strview_makez(label));
130
- } else {
131
- /* Look in enums defined in this file. */
132
- const google_protobuf_EnumDescriptorProto* matching_enum = NULL;
133
- size_t i, n;
134
- const google_protobuf_EnumDescriptorProto* const* enums =
135
- google_protobuf_FileDescriptorProto_enum_type(file, &n);
136
- const google_protobuf_EnumValueDescriptorProto* const* values;
137
-
138
- for (i = 0; i < n; i++) {
139
- if (upb_strview_eql(google_protobuf_EnumDescriptorProto_name(enums[i]),
140
- upb_strview_makez(type_name_str))) {
141
- matching_enum = enums[i];
142
- break;
143
- }
144
- }
145
-
146
- if (!matching_enum) {
147
- return;
148
- }
149
-
150
- values = google_protobuf_EnumDescriptorProto_value(matching_enum, &n);
151
- for (i = 0; i < n; i++) {
152
- if (google_protobuf_EnumValueDescriptorProto_number(values[i]) == val) {
153
- google_protobuf_FieldDescriptorProto_set_default_value(
154
- field, google_protobuf_EnumValueDescriptorProto_name(values[i]));
155
- return;
156
- }
157
- }
158
-
159
- /* We failed to find an enum default. But we'll just leave the enum
160
- * untouched and let the normal def-building code catch it. */
161
- }
162
- }
163
-
164
- /* Historically we allowed enum defaults to be specified as a number. In
165
- * retrospect this was a mistake as descriptors require defaults to be
166
- * specified as a label. This can make a difference if multiple labels have the
167
- * same number.
168
- *
169
- * Here we do a pass over all enum defaults and rewrite numeric defaults by
170
- * looking up their labels. This is complicated by the fact that the enum
171
- * definition can live in either the symtab or the file_proto.
172
- * */
173
- static void rewrite_enum_defaults(
174
- const upb_symtab* symtab, google_protobuf_FileDescriptorProto* file_proto) {
175
- size_t i, n;
176
- google_protobuf_DescriptorProto** msgs =
177
- google_protobuf_FileDescriptorProto_mutable_message_type(file_proto, &n);
178
-
179
- for (i = 0; i < n; i++) {
180
- size_t j, m;
181
- google_protobuf_FieldDescriptorProto** fields =
182
- google_protobuf_DescriptorProto_mutable_field(msgs[i], &m);
183
- for (j = 0; j < m; j++) {
184
- rewrite_enum_default(symtab, file_proto, fields[j]);
185
- }
186
- }
187
- }
188
-
189
- static void remove_path(upb_strview *name) {
190
- const char* last = strrchr(name->data, '.');
191
- if (last) {
192
- size_t remove = last - name->data + 1;
193
- name->data += remove;
194
- name->size -= remove;
195
- }
196
- }
197
-
198
- static void rewrite_nesting(VALUE msg_ent, google_protobuf_DescriptorProto* msg,
199
- google_protobuf_DescriptorProto* const* msgs,
200
- google_protobuf_EnumDescriptorProto* const* enums,
201
- upb_arena *arena) {
202
- VALUE submsgs = rb_hash_aref(msg_ent, ID2SYM(rb_intern("msgs")));
203
- VALUE enum_pos = rb_hash_aref(msg_ent, ID2SYM(rb_intern("enums")));
204
- int submsg_count;
205
- int enum_count;
206
- int i;
207
- google_protobuf_DescriptorProto** msg_msgs;
208
- google_protobuf_EnumDescriptorProto** msg_enums;
209
-
210
- Check_Type(submsgs, T_ARRAY);
211
- Check_Type(enum_pos, T_ARRAY);
212
-
213
- submsg_count = RARRAY_LEN(submsgs);
214
- enum_count = RARRAY_LEN(enum_pos);
215
-
216
- msg_msgs = google_protobuf_DescriptorProto_resize_nested_type(
217
- msg, submsg_count, arena);
218
- msg_enums =
219
- google_protobuf_DescriptorProto_resize_enum_type(msg, enum_count, arena);
220
-
221
- for (i = 0; i < submsg_count; i++) {
222
- VALUE submsg_ent = RARRAY_PTR(submsgs)[i];
223
- VALUE pos = rb_hash_aref(submsg_ent, ID2SYM(rb_intern("pos")));
224
- upb_strview name;
225
-
226
- msg_msgs[i] = msgs[NUM2INT(pos)];
227
- name = google_protobuf_DescriptorProto_name(msg_msgs[i]);
228
- remove_path(&name);
229
- google_protobuf_DescriptorProto_set_name(msg_msgs[i], name);
230
- rewrite_nesting(submsg_ent, msg_msgs[i], msgs, enums, arena);
231
- }
232
-
233
- for (i = 0; i < enum_count; i++) {
234
- VALUE pos = RARRAY_PTR(enum_pos)[i];
235
- msg_enums[i] = enums[NUM2INT(pos)];
236
- }
237
- }
238
-
239
71
  // -----------------------------------------------------------------------------
240
72
  // DescriptorPool.
241
73
  // -----------------------------------------------------------------------------
@@ -302,20 +134,32 @@ static VALUE DescriptorPool_alloc(VALUE klass) {
302
134
 
303
135
  /*
304
136
  * call-seq:
305
- * DescriptorPool.build(&block)
137
+ * DescriptorPool.add_serialized_file(serialized_file_proto)
306
138
  *
307
- * Invokes the block with a Builder instance as self. All message and enum types
308
- * added within the block are committed to the pool atomically, and may refer
309
- * (co)recursively to each other. The user should call Builder#add_message and
310
- * Builder#add_enum within the block as appropriate. This is the recommended,
311
- * idiomatic way to define new message and enum types.
139
+ * Adds the given serialized FileDescriptorProto to the pool.
312
140
  */
313
- static VALUE DescriptorPool_build(int argc, VALUE* argv, VALUE _self) {
314
- VALUE ctx = rb_class_new_instance(1, &_self, cBuilder);
315
- VALUE block = rb_block_proc();
316
- rb_funcall_with_block(ctx, rb_intern("instance_eval"), 0, NULL, block);
317
- Builder_build(ctx);
318
- return Qnil;
141
+ VALUE DescriptorPool_add_serialized_file(VALUE _self,
142
+ VALUE serialized_file_proto) {
143
+ DescriptorPool* self = ruby_to_DescriptorPool(_self);
144
+ Check_Type(serialized_file_proto, T_STRING);
145
+ VALUE arena_rb = Arena_new();
146
+ upb_arena *arena = Arena_get(arena_rb);
147
+ google_protobuf_FileDescriptorProto* file_proto =
148
+ google_protobuf_FileDescriptorProto_parse(
149
+ RSTRING_PTR(serialized_file_proto),
150
+ RSTRING_LEN(serialized_file_proto), arena);
151
+ if (!file_proto) {
152
+ rb_raise(rb_eArgError, "Unable to parse FileDescriptorProto");
153
+ }
154
+ upb_status status;
155
+ upb_status_clear(&status);
156
+ const upb_filedef* filedef =
157
+ upb_symtab_addfile(self->symtab, file_proto, &status);
158
+ if (!filedef) {
159
+ rb_raise(cTypeError, "Unable to build file to DescriptorPool: %s",
160
+ upb_status_errmsg(&status));
161
+ }
162
+ return get_filedef_obj(_self, filedef);
319
163
  }
320
164
 
321
165
  /*
@@ -361,7 +205,8 @@ static void DescriptorPool_register(VALUE module) {
361
205
  VALUE klass = rb_define_class_under(
362
206
  module, "DescriptorPool", rb_cObject);
363
207
  rb_define_alloc_func(klass, DescriptorPool_alloc);
364
- rb_define_method(klass, "build", DescriptorPool_build, -1);
208
+ rb_define_method(klass, "add_serialized_file",
209
+ DescriptorPool_add_serialized_file, 1);
365
210
  rb_define_method(klass, "lookup", DescriptorPool_lookup, 1);
366
211
  rb_define_singleton_method(klass, "generated_pool",
367
212
  DescriptorPool_generated_pool, 0);
@@ -773,41 +618,6 @@ upb_fieldtype_t ruby_to_fieldtype(VALUE type) {
773
618
  return 0;
774
619
  }
775
620
 
776
- static upb_descriptortype_t ruby_to_descriptortype(VALUE type) {
777
- if (TYPE(type) != T_SYMBOL) {
778
- rb_raise(rb_eArgError, "Expected symbol for field type.");
779
- }
780
-
781
- #define CONVERT(upb, ruby) \
782
- if (SYM2ID(type) == rb_intern( # ruby )) { \
783
- return UPB_DESCRIPTOR_TYPE_ ## upb; \
784
- }
785
-
786
- CONVERT(FLOAT, float);
787
- CONVERT(DOUBLE, double);
788
- CONVERT(BOOL, bool);
789
- CONVERT(STRING, string);
790
- CONVERT(BYTES, bytes);
791
- CONVERT(MESSAGE, message);
792
- CONVERT(GROUP, group);
793
- CONVERT(ENUM, enum);
794
- CONVERT(INT32, int32);
795
- CONVERT(INT64, int64);
796
- CONVERT(UINT32, uint32);
797
- CONVERT(UINT64, uint64);
798
- CONVERT(SINT32, sint32);
799
- CONVERT(SINT64, sint64);
800
- CONVERT(FIXED32, fixed32);
801
- CONVERT(FIXED64, fixed64);
802
- CONVERT(SFIXED32, sfixed32);
803
- CONVERT(SFIXED64, sfixed64);
804
-
805
- #undef CONVERT
806
-
807
- rb_raise(rb_eArgError, "Unknown field type.");
808
- return 0;
809
- }
810
-
811
621
  static VALUE descriptortype_to_ruby(upb_descriptortype_t type) {
812
622
  switch (type) {
813
623
  #define CONVERT(upb, ruby) \
@@ -868,6 +678,20 @@ static VALUE FieldDescriptor_default(VALUE _self) {
868
678
  return Convert_UpbToRuby(default_val, TypeInfo_get(self->fielddef), Qnil);
869
679
  }
870
680
 
681
+
682
+ /*
683
+ * call-seq:
684
+ * FieldDescriptor.json_name => json_name
685
+ *
686
+ * Returns this field's json_name, as a Ruby string, or nil if not yet set.
687
+ */
688
+ static VALUE FieldDescriptor_json_name(VALUE _self) {
689
+ FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
690
+ const upb_fielddef *f = self->fielddef;
691
+ const char *json_name = upb_fielddef_jsonname(f);
692
+ return rb_str_new2(json_name);
693
+ }
694
+
871
695
  /*
872
696
  * call-seq:
873
697
  * FieldDescriptor.label => label
@@ -1043,6 +867,7 @@ static void FieldDescriptor_register(VALUE module) {
1043
867
  rb_define_method(klass, "name", FieldDescriptor_name, 0);
1044
868
  rb_define_method(klass, "type", FieldDescriptor__type, 0);
1045
869
  rb_define_method(klass, "default", FieldDescriptor_default, 0);
870
+ rb_define_method(klass, "json_name", FieldDescriptor_json_name, 0);
1046
871
  rb_define_method(klass, "label", FieldDescriptor_label, 0);
1047
872
  rb_define_method(klass, "number", FieldDescriptor_number, 0);
1048
873
  rb_define_method(klass, "submsg_name", FieldDescriptor_submsg_name, 0);
@@ -1338,1099 +1163,6 @@ static void EnumDescriptor_register(VALUE module) {
1338
1163
  cEnumDescriptor = klass;
1339
1164
  }
1340
1165
 
1341
- // -----------------------------------------------------------------------------
1342
- // FileBuilderContext.
1343
- // -----------------------------------------------------------------------------
1344
-
1345
- typedef struct {
1346
- upb_arena *arena;
1347
- google_protobuf_FileDescriptorProto* file_proto;
1348
- VALUE descriptor_pool;
1349
- } FileBuilderContext;
1350
-
1351
- static VALUE cFileBuilderContext = Qnil;
1352
-
1353
- static void FileBuilderContext_mark(void* _self) {
1354
- FileBuilderContext* self = _self;
1355
- rb_gc_mark(self->descriptor_pool);
1356
- }
1357
-
1358
- static void FileBuilderContext_free(void* _self) {
1359
- FileBuilderContext* self = _self;
1360
- upb_arena_free(self->arena);
1361
- xfree(self);
1362
- }
1363
-
1364
- static const rb_data_type_t FileBuilderContext_type = {
1365
- "Google::Protobuf::Internal::FileBuilderContext",
1366
- {FileBuilderContext_mark, FileBuilderContext_free, NULL},
1367
- .flags = RUBY_TYPED_FREE_IMMEDIATELY,
1368
- };
1369
-
1370
- static FileBuilderContext* ruby_to_FileBuilderContext(VALUE val) {
1371
- FileBuilderContext* ret;
1372
- TypedData_Get_Struct(val, FileBuilderContext, &FileBuilderContext_type, ret);
1373
- return ret;
1374
- }
1375
-
1376
- static upb_strview FileBuilderContext_strdup2(VALUE _self, const char *str) {
1377
- FileBuilderContext* self = ruby_to_FileBuilderContext(_self);
1378
- upb_strview ret;
1379
- char *data;
1380
-
1381
- ret.size = strlen(str);
1382
- data = upb_malloc(upb_arena_alloc(self->arena), ret.size + 1);
1383
- ret.data = data;
1384
- memcpy(data, str, ret.size);
1385
- /* Null-terminate required by rewrite_enum_defaults() above. */
1386
- data[ret.size] = '\0';
1387
- return ret;
1388
- }
1389
-
1390
- static upb_strview FileBuilderContext_strdup(VALUE _self, VALUE rb_str) {
1391
- return FileBuilderContext_strdup2(_self, get_str(rb_str));
1392
- }
1393
-
1394
- static upb_strview FileBuilderContext_strdup_sym(VALUE _self, VALUE rb_sym) {
1395
- Check_Type(rb_sym, T_SYMBOL);
1396
- return FileBuilderContext_strdup(_self, rb_id2str(SYM2ID(rb_sym)));
1397
- }
1398
-
1399
- static VALUE FileBuilderContext_alloc(VALUE klass) {
1400
- FileBuilderContext* self = ALLOC(FileBuilderContext);
1401
- VALUE ret = TypedData_Wrap_Struct(klass, &FileBuilderContext_type, self);
1402
- self->arena = upb_arena_new();
1403
- self->file_proto = google_protobuf_FileDescriptorProto_new(self->arena);
1404
- self->descriptor_pool = Qnil;
1405
- return ret;
1406
- }
1407
-
1408
- /*
1409
- * call-seq:
1410
- * FileBuilderContext.new(descriptor_pool) => context
1411
- *
1412
- * Create a new file builder context for the given file descriptor and
1413
- * builder context. This class is intended to serve as a DSL context to be used
1414
- * with #instance_eval.
1415
- */
1416
- static VALUE FileBuilderContext_initialize(VALUE _self, VALUE descriptor_pool,
1417
- VALUE name, VALUE options) {
1418
- FileBuilderContext* self = ruby_to_FileBuilderContext(_self);
1419
- self->descriptor_pool = descriptor_pool;
1420
-
1421
- google_protobuf_FileDescriptorProto_set_name(
1422
- self->file_proto, FileBuilderContext_strdup(_self, name));
1423
-
1424
- // Default syntax for Ruby is proto3.
1425
- google_protobuf_FileDescriptorProto_set_syntax(
1426
- self->file_proto,
1427
- FileBuilderContext_strdup(_self, rb_str_new2("proto3")));
1428
-
1429
- if (options != Qnil) {
1430
- VALUE syntax;
1431
-
1432
- Check_Type(options, T_HASH);
1433
- syntax = rb_hash_lookup2(options, ID2SYM(rb_intern("syntax")), Qnil);
1434
-
1435
- if (syntax != Qnil) {
1436
- VALUE syntax_str;
1437
-
1438
- Check_Type(syntax, T_SYMBOL);
1439
- syntax_str = rb_id2str(SYM2ID(syntax));
1440
- google_protobuf_FileDescriptorProto_set_syntax(
1441
- self->file_proto, FileBuilderContext_strdup(_self, syntax_str));
1442
- }
1443
- }
1444
-
1445
- return Qnil;
1446
- }
1447
-
1448
- static void MessageBuilderContext_add_synthetic_oneofs(VALUE _self);
1449
-
1450
- /*
1451
- * call-seq:
1452
- * FileBuilderContext.add_message(name, &block)
1453
- *
1454
- * Creates a new, empty descriptor with the given name, and invokes the block in
1455
- * the context of a MessageBuilderContext on that descriptor. The block can then
1456
- * call, e.g., MessageBuilderContext#optional and MessageBuilderContext#repeated
1457
- * methods to define the message fields.
1458
- *
1459
- * This is the recommended, idiomatic way to build message definitions.
1460
- */
1461
- static VALUE FileBuilderContext_add_message(VALUE _self, VALUE name) {
1462
- VALUE args[2] = { _self, name };
1463
- VALUE ctx = rb_class_new_instance(2, args, cMessageBuilderContext);
1464
- VALUE block = rb_block_proc();
1465
- rb_funcall_with_block(ctx, rb_intern("instance_eval"), 0, NULL, block);
1466
- MessageBuilderContext_add_synthetic_oneofs(ctx);
1467
- return Qnil;
1468
- }
1469
-
1470
- /* We have to do some relatively complicated logic here for backward
1471
- * compatibility.
1472
- *
1473
- * In descriptor.proto, messages are nested inside other messages if that is
1474
- * what the original .proto file looks like. For example, suppose we have this
1475
- * foo.proto:
1476
- *
1477
- * package foo;
1478
- * message Bar {
1479
- * message Baz {}
1480
- * }
1481
- *
1482
- * The descriptor for this must look like this:
1483
- *
1484
- * file {
1485
- * name: "test.proto"
1486
- * package: "foo"
1487
- * message_type {
1488
- * name: "Bar"
1489
- * nested_type {
1490
- * name: "Baz"
1491
- * }
1492
- * }
1493
- * }
1494
- *
1495
- * However, the Ruby generated code has always generated messages in a flat,
1496
- * non-nested way:
1497
- *
1498
- * Google::Protobuf::DescriptorPool.generated_pool.build do
1499
- * add_message "foo.Bar" do
1500
- * end
1501
- * add_message "foo.Bar.Baz" do
1502
- * end
1503
- * end
1504
- *
1505
- * Here we need to do a translation where we turn this generated code into the
1506
- * above descriptor. We need to infer that "foo" is the package name, and not
1507
- * a message itself.
1508
- *
1509
- * We delegate to Ruby to compute the transformation, for more concice and
1510
- * readable code than we can do in C */
1511
- static void rewrite_names(VALUE _file_builder,
1512
- google_protobuf_FileDescriptorProto* file_proto) {
1513
- FileBuilderContext* file_builder = ruby_to_FileBuilderContext(_file_builder);
1514
- upb_arena *arena = file_builder->arena;
1515
- // Build params (package, msg_names, enum_names).
1516
- VALUE package = Qnil;
1517
- VALUE msg_names = rb_ary_new();
1518
- VALUE enum_names = rb_ary_new();
1519
- size_t msg_count, enum_count, i;
1520
- VALUE new_package, nesting, msg_ents, enum_ents;
1521
- google_protobuf_DescriptorProto** msgs;
1522
- google_protobuf_EnumDescriptorProto** enums;
1523
-
1524
- if (google_protobuf_FileDescriptorProto_has_package(file_proto)) {
1525
- upb_strview package_str =
1526
- google_protobuf_FileDescriptorProto_package(file_proto);
1527
- package = rb_str_new(package_str.data, package_str.size);
1528
- }
1529
-
1530
- msgs = google_protobuf_FileDescriptorProto_mutable_message_type(file_proto,
1531
- &msg_count);
1532
- for (i = 0; i < msg_count; i++) {
1533
- upb_strview name = google_protobuf_DescriptorProto_name(msgs[i]);
1534
- rb_ary_push(msg_names, rb_str_new(name.data, name.size));
1535
- }
1536
-
1537
- enums = google_protobuf_FileDescriptorProto_mutable_enum_type(file_proto,
1538
- &enum_count);
1539
- for (i = 0; i < enum_count; i++) {
1540
- upb_strview name = google_protobuf_EnumDescriptorProto_name(enums[i]);
1541
- rb_ary_push(enum_names, rb_str_new(name.data, name.size));
1542
- }
1543
-
1544
- {
1545
- // Call Ruby code to calculate package name and nesting.
1546
- VALUE args[3] = { package, msg_names, enum_names };
1547
- VALUE internal = rb_eval_string("Google::Protobuf::Internal");
1548
- VALUE ret = rb_funcallv(internal, rb_intern("fixup_descriptor"), 3, args);
1549
-
1550
- new_package = rb_ary_entry(ret, 0);
1551
- nesting = rb_ary_entry(ret, 1);
1552
- }
1553
-
1554
- // Rewrite package and names.
1555
- if (new_package != Qnil) {
1556
- upb_strview new_package_str =
1557
- FileBuilderContext_strdup(_file_builder, new_package);
1558
- google_protobuf_FileDescriptorProto_set_package(file_proto,
1559
- new_package_str);
1560
- }
1561
-
1562
- for (i = 0; i < msg_count; i++) {
1563
- upb_strview name = google_protobuf_DescriptorProto_name(msgs[i]);
1564
- remove_path(&name);
1565
- google_protobuf_DescriptorProto_set_name(msgs[i], name);
1566
- }
1567
-
1568
- for (i = 0; i < enum_count; i++) {
1569
- upb_strview name = google_protobuf_EnumDescriptorProto_name(enums[i]);
1570
- remove_path(&name);
1571
- google_protobuf_EnumDescriptorProto_set_name(enums[i], name);
1572
- }
1573
-
1574
- // Rewrite nesting.
1575
- msg_ents = rb_hash_aref(nesting, ID2SYM(rb_intern("msgs")));
1576
- enum_ents = rb_hash_aref(nesting, ID2SYM(rb_intern("enums")));
1577
-
1578
- Check_Type(msg_ents, T_ARRAY);
1579
- Check_Type(enum_ents, T_ARRAY);
1580
-
1581
- for (i = 0; i < (size_t)RARRAY_LEN(msg_ents); i++) {
1582
- VALUE msg_ent = rb_ary_entry(msg_ents, i);
1583
- VALUE pos = rb_hash_aref(msg_ent, ID2SYM(rb_intern("pos")));
1584
- msgs[i] = msgs[NUM2INT(pos)];
1585
- rewrite_nesting(msg_ent, msgs[i], msgs, enums, arena);
1586
- }
1587
-
1588
- for (i = 0; i < (size_t)RARRAY_LEN(enum_ents); i++) {
1589
- VALUE enum_pos = rb_ary_entry(enum_ents, i);
1590
- enums[i] = enums[NUM2INT(enum_pos)];
1591
- }
1592
-
1593
- google_protobuf_FileDescriptorProto_resize_message_type(
1594
- file_proto, RARRAY_LEN(msg_ents), arena);
1595
- google_protobuf_FileDescriptorProto_resize_enum_type(
1596
- file_proto, RARRAY_LEN(enum_ents), arena);
1597
- }
1598
-
1599
- /*
1600
- * call-seq:
1601
- * FileBuilderContext.add_enum(name, &block)
1602
- *
1603
- * Creates a new, empty enum descriptor with the given name, and invokes the
1604
- * block in the context of an EnumBuilderContext on that descriptor. The block
1605
- * can then call EnumBuilderContext#add_value to define the enum values.
1606
- *
1607
- * This is the recommended, idiomatic way to build enum definitions.
1608
- */
1609
- static VALUE FileBuilderContext_add_enum(VALUE _self, VALUE name) {
1610
- VALUE args[2] = { _self, name };
1611
- VALUE ctx = rb_class_new_instance(2, args, cEnumBuilderContext);
1612
- VALUE block = rb_block_proc();
1613
- rb_funcall_with_block(ctx, rb_intern("instance_eval"), 0, NULL, block);
1614
- return Qnil;
1615
- }
1616
-
1617
- static void FileBuilderContext_build(VALUE _self) {
1618
- FileBuilderContext* self = ruby_to_FileBuilderContext(_self);
1619
- DescriptorPool* pool = ruby_to_DescriptorPool(self->descriptor_pool);
1620
- upb_status status;
1621
-
1622
- rewrite_enum_defaults(pool->symtab, self->file_proto);
1623
- rewrite_names(_self, self->file_proto);
1624
-
1625
- upb_status_clear(&status);
1626
- if (!upb_symtab_addfile(pool->symtab, self->file_proto, &status)) {
1627
- rb_raise(cTypeError, "Unable to add defs to DescriptorPool: %s",
1628
- upb_status_errmsg(&status));
1629
- }
1630
- }
1631
-
1632
- static void FileBuilderContext_register(VALUE module) {
1633
- VALUE klass = rb_define_class_under(module, "FileBuilderContext", rb_cObject);
1634
- rb_define_alloc_func(klass, FileBuilderContext_alloc);
1635
- rb_define_method(klass, "initialize", FileBuilderContext_initialize, 3);
1636
- rb_define_method(klass, "add_message", FileBuilderContext_add_message, 1);
1637
- rb_define_method(klass, "add_enum", FileBuilderContext_add_enum, 1);
1638
- rb_gc_register_address(&cFileBuilderContext);
1639
- cFileBuilderContext = klass;
1640
- }
1641
-
1642
- // -----------------------------------------------------------------------------
1643
- // MessageBuilderContext.
1644
- // -----------------------------------------------------------------------------
1645
-
1646
- typedef struct {
1647
- google_protobuf_DescriptorProto* msg_proto;
1648
- VALUE file_builder;
1649
- } MessageBuilderContext;
1650
-
1651
- static VALUE cMessageBuilderContext = Qnil;
1652
-
1653
- static void MessageBuilderContext_mark(void* _self) {
1654
- MessageBuilderContext* self = _self;
1655
- rb_gc_mark(self->file_builder);
1656
- }
1657
-
1658
- static const rb_data_type_t MessageBuilderContext_type = {
1659
- "Google::Protobuf::Internal::MessageBuilderContext",
1660
- {MessageBuilderContext_mark, RUBY_DEFAULT_FREE, NULL},
1661
- .flags = RUBY_TYPED_FREE_IMMEDIATELY,
1662
- };
1663
-
1664
- static MessageBuilderContext* ruby_to_MessageBuilderContext(VALUE val) {
1665
- MessageBuilderContext* ret;
1666
- TypedData_Get_Struct(val, MessageBuilderContext, &MessageBuilderContext_type,
1667
- ret);
1668
- return ret;
1669
- }
1670
-
1671
- static VALUE MessageBuilderContext_alloc(VALUE klass) {
1672
- MessageBuilderContext* self = ALLOC(MessageBuilderContext);
1673
- VALUE ret = TypedData_Wrap_Struct(klass, &MessageBuilderContext_type, self);
1674
- self->file_builder = Qnil;
1675
- return ret;
1676
- }
1677
-
1678
- /*
1679
- * call-seq:
1680
- * MessageBuilderContext.new(file_builder, name) => context
1681
- *
1682
- * Create a new message builder context around the given message descriptor and
1683
- * builder context. This class is intended to serve as a DSL context to be used
1684
- * with #instance_eval.
1685
- */
1686
- static VALUE MessageBuilderContext_initialize(VALUE _self, VALUE _file_builder,
1687
- VALUE name) {
1688
- MessageBuilderContext* self = ruby_to_MessageBuilderContext(_self);
1689
- FileBuilderContext* file_builder = ruby_to_FileBuilderContext(_file_builder);
1690
- google_protobuf_FileDescriptorProto* file_proto = file_builder->file_proto;
1691
-
1692
- self->file_builder = _file_builder;
1693
- self->msg_proto = google_protobuf_FileDescriptorProto_add_message_type(
1694
- file_proto, file_builder->arena);
1695
-
1696
- google_protobuf_DescriptorProto_set_name(
1697
- self->msg_proto, FileBuilderContext_strdup(_file_builder, name));
1698
-
1699
- return Qnil;
1700
- }
1701
-
1702
- static void msgdef_add_field(VALUE msgbuilder_rb, upb_label_t label, VALUE name,
1703
- VALUE type, VALUE number, VALUE type_class,
1704
- VALUE options, int oneof_index,
1705
- bool proto3_optional) {
1706
- MessageBuilderContext* self = ruby_to_MessageBuilderContext(msgbuilder_rb);
1707
- FileBuilderContext* file_context =
1708
- ruby_to_FileBuilderContext(self->file_builder);
1709
- google_protobuf_FieldDescriptorProto* field_proto;
1710
- VALUE name_str;
1711
-
1712
- field_proto = google_protobuf_DescriptorProto_add_field(self->msg_proto,
1713
- file_context->arena);
1714
-
1715
- Check_Type(name, T_SYMBOL);
1716
- name_str = rb_id2str(SYM2ID(name));
1717
-
1718
- google_protobuf_FieldDescriptorProto_set_name(
1719
- field_proto, FileBuilderContext_strdup(self->file_builder, name_str));
1720
- google_protobuf_FieldDescriptorProto_set_number(field_proto, NUM2INT(number));
1721
- google_protobuf_FieldDescriptorProto_set_label(field_proto, (int)label);
1722
- google_protobuf_FieldDescriptorProto_set_type(
1723
- field_proto, (int)ruby_to_descriptortype(type));
1724
-
1725
- if (proto3_optional) {
1726
- google_protobuf_FieldDescriptorProto_set_proto3_optional(field_proto, true);
1727
- }
1728
-
1729
- if (type_class != Qnil) {
1730
- Check_Type(type_class, T_STRING);
1731
-
1732
- // Make it an absolute type name by prepending a dot.
1733
- type_class = rb_str_append(rb_str_new2("."), type_class);
1734
- google_protobuf_FieldDescriptorProto_set_type_name(
1735
- field_proto, FileBuilderContext_strdup(self->file_builder, type_class));
1736
- }
1737
-
1738
- if (options != Qnil) {
1739
- Check_Type(options, T_HASH);
1740
-
1741
- if (rb_funcall(options, rb_intern("key?"), 1,
1742
- ID2SYM(rb_intern("default"))) == Qtrue) {
1743
- VALUE default_value =
1744
- rb_hash_lookup(options, ID2SYM(rb_intern("default")));
1745
-
1746
- /* Call #to_s since all defaults are strings in the descriptor. */
1747
- default_value = rb_funcall(default_value, rb_intern("to_s"), 0);
1748
-
1749
- google_protobuf_FieldDescriptorProto_set_default_value(
1750
- field_proto,
1751
- FileBuilderContext_strdup(self->file_builder, default_value));
1752
- }
1753
- }
1754
-
1755
- if (oneof_index >= 0) {
1756
- google_protobuf_FieldDescriptorProto_set_oneof_index(field_proto,
1757
- oneof_index);
1758
- }
1759
- }
1760
-
1761
- #if RUBY_API_VERSION_CODE >= 20700
1762
- static VALUE make_mapentry(VALUE _message_builder, VALUE types, int argc,
1763
- const VALUE* argv, VALUE blockarg) {
1764
- (void)blockarg;
1765
- #else
1766
- static VALUE make_mapentry(VALUE _message_builder, VALUE types, int argc,
1767
- VALUE* argv) {
1768
- #endif
1769
- MessageBuilderContext* message_builder =
1770
- ruby_to_MessageBuilderContext(_message_builder);
1771
- VALUE type_class = rb_ary_entry(types, 2);
1772
- FileBuilderContext* file_context =
1773
- ruby_to_FileBuilderContext(message_builder->file_builder);
1774
- google_protobuf_MessageOptions* options =
1775
- google_protobuf_DescriptorProto_mutable_options(
1776
- message_builder->msg_proto, file_context->arena);
1777
-
1778
- google_protobuf_MessageOptions_set_map_entry(options, true);
1779
-
1780
- // optional <type> key = 1;
1781
- rb_funcall(_message_builder, rb_intern("optional"), 3,
1782
- ID2SYM(rb_intern("key")), rb_ary_entry(types, 0), INT2NUM(1));
1783
-
1784
- // optional <type> value = 2;
1785
- if (type_class == Qnil) {
1786
- rb_funcall(_message_builder, rb_intern("optional"), 3,
1787
- ID2SYM(rb_intern("value")), rb_ary_entry(types, 1), INT2NUM(2));
1788
- } else {
1789
- rb_funcall(_message_builder, rb_intern("optional"), 4,
1790
- ID2SYM(rb_intern("value")), rb_ary_entry(types, 1), INT2NUM(2),
1791
- type_class);
1792
- }
1793
-
1794
- return Qnil;
1795
- }
1796
-
1797
- /*
1798
- * call-seq:
1799
- * MessageBuilderContext.optional(name, type, number, type_class = nil,
1800
- * options = nil)
1801
- *
1802
- * Defines a new optional field on this message type with the given type, tag
1803
- * number, and type class (for message and enum fields). The type must be a Ruby
1804
- * symbol (as accepted by FieldDescriptor#type=) and the type_class must be a
1805
- * string, if present (as accepted by FieldDescriptor#submsg_name=).
1806
- */
1807
- VALUE MessageBuilderContext_optional(int argc, VALUE* argv, VALUE _self) {
1808
- VALUE name, type, number;
1809
- VALUE type_class, options = Qnil;
1810
-
1811
- rb_scan_args(argc, argv, "32", &name, &type, &number, &type_class, &options);
1812
-
1813
- // Allow passing (name, type, number, options) or
1814
- // (name, type, number, type_class, options)
1815
- if (argc == 4 && RB_TYPE_P(type_class, T_HASH)) {
1816
- options = type_class;
1817
- type_class = Qnil;
1818
- }
1819
-
1820
- msgdef_add_field(_self, UPB_LABEL_OPTIONAL, name, type, number, type_class,
1821
- options, -1, false);
1822
-
1823
- return Qnil;
1824
- }
1825
-
1826
- /*
1827
- * call-seq:
1828
- * MessageBuilderContext.proto3_optional(name, type, number,
1829
- * type_class = nil, options = nil)
1830
- *
1831
- * Defines a true proto3 optional field (that tracks presence) on this message
1832
- * type with the given type, tag number, and type class (for message and enum
1833
- * fields). The type must be a Ruby symbol (as accepted by
1834
- * FieldDescriptor#type=) and the type_class must be a string, if present (as
1835
- * accepted by FieldDescriptor#submsg_name=).
1836
- */
1837
- static VALUE MessageBuilderContext_proto3_optional(int argc, VALUE* argv,
1838
- VALUE _self) {
1839
- VALUE name, type, number;
1840
- VALUE type_class, options = Qnil;
1841
-
1842
- rb_scan_args(argc, argv, "32", &name, &type, &number, &type_class, &options);
1843
-
1844
- // Allow passing (name, type, number, options) or
1845
- // (name, type, number, type_class, options)
1846
- if (argc == 4 && RB_TYPE_P(type_class, T_HASH)) {
1847
- options = type_class;
1848
- type_class = Qnil;
1849
- }
1850
-
1851
- msgdef_add_field(_self, UPB_LABEL_OPTIONAL, name, type, number, type_class,
1852
- options, -1, true);
1853
-
1854
- return Qnil;
1855
- }
1856
-
1857
- /*
1858
- * call-seq:
1859
- * MessageBuilderContext.required(name, type, number, type_class = nil,
1860
- * options = nil)
1861
- *
1862
- * Defines a new required field on this message type with the given type, tag
1863
- * number, and type class (for message and enum fields). The type must be a Ruby
1864
- * symbol (as accepted by FieldDescriptor#type=) and the type_class must be a
1865
- * string, if present (as accepted by FieldDescriptor#submsg_name=).
1866
- *
1867
- * Proto3 does not have required fields, but this method exists for
1868
- * completeness. Any attempt to add a message type with required fields to a
1869
- * pool will currently result in an error.
1870
- */
1871
- static VALUE MessageBuilderContext_required(int argc, VALUE* argv,
1872
- VALUE _self) {
1873
- VALUE name, type, number;
1874
- VALUE type_class, options = Qnil;
1875
-
1876
- rb_scan_args(argc, argv, "32", &name, &type, &number, &type_class, &options);
1877
-
1878
- // Allow passing (name, type, number, options) or
1879
- // (name, type, number, type_class, options)
1880
- if (argc == 4 && RB_TYPE_P(type_class, T_HASH)) {
1881
- options = type_class;
1882
- type_class = Qnil;
1883
- }
1884
-
1885
- msgdef_add_field(_self, UPB_LABEL_REQUIRED, name, type, number, type_class,
1886
- options, -1, false);
1887
-
1888
- return Qnil;
1889
- }
1890
-
1891
- /*
1892
- * call-seq:
1893
- * MessageBuilderContext.repeated(name, type, number, type_class = nil)
1894
- *
1895
- * Defines a new repeated field on this message type with the given type, tag
1896
- * number, and type class (for message and enum fields). The type must be a Ruby
1897
- * symbol (as accepted by FieldDescriptor#type=) and the type_class must be a
1898
- * string, if present (as accepted by FieldDescriptor#submsg_name=).
1899
- */
1900
- static VALUE MessageBuilderContext_repeated(int argc, VALUE* argv,
1901
- VALUE _self) {
1902
- VALUE name, type, number, type_class;
1903
-
1904
- if (argc < 3) {
1905
- rb_raise(rb_eArgError, "Expected at least 3 arguments.");
1906
- }
1907
- name = argv[0];
1908
- type = argv[1];
1909
- number = argv[2];
1910
- type_class = (argc > 3) ? argv[3] : Qnil;
1911
-
1912
- msgdef_add_field(_self, UPB_LABEL_REPEATED, name, type, number, type_class,
1913
- Qnil, -1, false);
1914
-
1915
- return Qnil;
1916
- }
1917
-
1918
- /*
1919
- * call-seq:
1920
- * MessageBuilderContext.map(name, key_type, value_type, number,
1921
- * value_type_class = nil)
1922
- *
1923
- * Defines a new map field on this message type with the given key and value
1924
- * types, tag number, and type class (for message and enum value types). The key
1925
- * type must be :int32/:uint32/:int64/:uint64, :bool, or :string. The value type
1926
- * type must be a Ruby symbol (as accepted by FieldDescriptor#type=) and the
1927
- * type_class must be a string, if present (as accepted by
1928
- * FieldDescriptor#submsg_name=).
1929
- */
1930
- static VALUE MessageBuilderContext_map(int argc, VALUE* argv, VALUE _self) {
1931
- MessageBuilderContext* self = ruby_to_MessageBuilderContext(_self);
1932
- VALUE name, key_type, value_type, number, type_class;
1933
- VALUE mapentry_desc_name;
1934
- FileBuilderContext* file_builder;
1935
- upb_strview msg_name;
1936
-
1937
- if (argc < 4) {
1938
- rb_raise(rb_eArgError, "Expected at least 4 arguments.");
1939
- }
1940
- name = argv[0];
1941
- key_type = argv[1];
1942
- value_type = argv[2];
1943
- number = argv[3];
1944
- type_class = (argc > 4) ? argv[4] : Qnil;
1945
-
1946
- // Validate the key type. We can't accept enums, messages, or floats/doubles
1947
- // as map keys. (We exclude these explicitly, and the field-descriptor setter
1948
- // below then ensures that the type is one of the remaining valid options.)
1949
- if (SYM2ID(key_type) == rb_intern("float") ||
1950
- SYM2ID(key_type) == rb_intern("double") ||
1951
- SYM2ID(key_type) == rb_intern("enum") ||
1952
- SYM2ID(key_type) == rb_intern("message")) {
1953
- rb_raise(rb_eArgError,
1954
- "Cannot add a map field with a float, double, enum, or message "
1955
- "type.");
1956
- }
1957
-
1958
- file_builder = ruby_to_FileBuilderContext(self->file_builder);
1959
-
1960
- // Create a new message descriptor for the map entry message, and create a
1961
- // repeated submessage field here with that type.
1962
- msg_name = google_protobuf_DescriptorProto_name(self->msg_proto);
1963
- mapentry_desc_name = rb_str_new(msg_name.data, msg_name.size);
1964
- mapentry_desc_name = rb_str_cat2(mapentry_desc_name, "_MapEntry_");
1965
- mapentry_desc_name =
1966
- rb_str_cat2(mapentry_desc_name, rb_id2name(SYM2ID(name)));
1967
-
1968
- {
1969
- // message <msgname>_MapEntry_ { /* ... */ }
1970
- VALUE args[1] = {mapentry_desc_name};
1971
- VALUE types = rb_ary_new3(3, key_type, value_type, type_class);
1972
- rb_block_call(self->file_builder, rb_intern("add_message"), 1, args,
1973
- make_mapentry, types);
1974
- }
1975
-
1976
- // If this file is in a package, we need to qualify the map entry type.
1977
- if (google_protobuf_FileDescriptorProto_has_package(file_builder->file_proto)) {
1978
- upb_strview package_view =
1979
- google_protobuf_FileDescriptorProto_package(file_builder->file_proto);
1980
- VALUE package = rb_str_new(package_view.data, package_view.size);
1981
- package = rb_str_cat2(package, ".");
1982
- mapentry_desc_name = rb_str_concat(package, mapentry_desc_name);
1983
- }
1984
-
1985
- // repeated MapEntry <name> = <number>;
1986
- rb_funcall(_self, rb_intern("repeated"), 4, name,
1987
- ID2SYM(rb_intern("message")), number, mapentry_desc_name);
1988
-
1989
- return Qnil;
1990
- }
1991
-
1992
- /*
1993
- * call-seq:
1994
- * MessageBuilderContext.oneof(name, &block) => nil
1995
- *
1996
- * Creates a new OneofDescriptor with the given name, creates a
1997
- * OneofBuilderContext attached to that OneofDescriptor, evaluates the given
1998
- * block in the context of that OneofBuilderContext with #instance_eval, and
1999
- * then adds the oneof to the message.
2000
- *
2001
- * This is the recommended, idiomatic way to build oneof definitions.
2002
- */
2003
- static VALUE MessageBuilderContext_oneof(VALUE _self, VALUE name) {
2004
- MessageBuilderContext* self = ruby_to_MessageBuilderContext(_self);
2005
- size_t oneof_count;
2006
- FileBuilderContext* file_context =
2007
- ruby_to_FileBuilderContext(self->file_builder);
2008
- google_protobuf_OneofDescriptorProto* oneof_proto;
2009
-
2010
- // Existing oneof_count becomes oneof_index.
2011
- google_protobuf_DescriptorProto_oneof_decl(self->msg_proto, &oneof_count);
2012
-
2013
- // Create oneof_proto and set its name.
2014
- oneof_proto = google_protobuf_DescriptorProto_add_oneof_decl(
2015
- self->msg_proto, file_context->arena);
2016
- google_protobuf_OneofDescriptorProto_set_name(
2017
- oneof_proto, FileBuilderContext_strdup_sym(self->file_builder, name));
2018
-
2019
- // Evaluate the block with the builder as argument.
2020
- {
2021
- VALUE args[2] = { INT2NUM(oneof_count), _self };
2022
- VALUE ctx = rb_class_new_instance(2, args, cOneofBuilderContext);
2023
- VALUE block = rb_block_proc();
2024
- rb_funcall_with_block(ctx, rb_intern("instance_eval"), 0, NULL, block);
2025
- }
2026
-
2027
- return Qnil;
2028
- }
2029
-
2030
- static void MessageBuilderContext_add_synthetic_oneofs(VALUE _self) {
2031
- MessageBuilderContext* self = ruby_to_MessageBuilderContext(_self);
2032
- FileBuilderContext* file_context =
2033
- ruby_to_FileBuilderContext(self->file_builder);
2034
- size_t field_count, oneof_count;
2035
- google_protobuf_FieldDescriptorProto** fields =
2036
- google_protobuf_DescriptorProto_mutable_field(self->msg_proto, &field_count);
2037
- const google_protobuf_OneofDescriptorProto*const* oneofs =
2038
- google_protobuf_DescriptorProto_oneof_decl(self->msg_proto, &oneof_count);
2039
- VALUE names = rb_hash_new();
2040
- VALUE underscore = rb_str_new2("_");
2041
- size_t i;
2042
-
2043
- // We have to build a set of all names, to ensure that synthetic oneofs are
2044
- // not creating conflicts.
2045
- for (i = 0; i < field_count; i++) {
2046
- upb_strview name = google_protobuf_FieldDescriptorProto_name(fields[i]);
2047
- rb_hash_aset(names, rb_str_new(name.data, name.size), Qtrue);
2048
- }
2049
- for (i = 0; i < oneof_count; i++) {
2050
- upb_strview name = google_protobuf_OneofDescriptorProto_name(oneofs[i]);
2051
- rb_hash_aset(names, rb_str_new(name.data, name.size), Qtrue);
2052
- }
2053
-
2054
- for (i = 0; i < field_count; i++) {
2055
- google_protobuf_OneofDescriptorProto* oneof_proto;
2056
- VALUE oneof_name;
2057
- upb_strview field_name;
2058
-
2059
- if (!google_protobuf_FieldDescriptorProto_proto3_optional(fields[i])) {
2060
- continue;
2061
- }
2062
-
2063
- // Prepend '_' until we are no longer conflicting.
2064
- field_name = google_protobuf_FieldDescriptorProto_name(fields[i]);
2065
- oneof_name = rb_str_new(field_name.data, field_name.size);
2066
- while (rb_hash_lookup(names, oneof_name) != Qnil) {
2067
- oneof_name = rb_str_plus(underscore, oneof_name);
2068
- }
2069
-
2070
- rb_hash_aset(names, oneof_name, Qtrue);
2071
- google_protobuf_FieldDescriptorProto_set_oneof_index(fields[i],
2072
- oneof_count++);
2073
- oneof_proto = google_protobuf_DescriptorProto_add_oneof_decl(
2074
- self->msg_proto, file_context->arena);
2075
- google_protobuf_OneofDescriptorProto_set_name(
2076
- oneof_proto, FileBuilderContext_strdup(self->file_builder, oneof_name));
2077
- }
2078
- }
2079
-
2080
- static void MessageBuilderContext_register(VALUE module) {
2081
- VALUE klass = rb_define_class_under(
2082
- module, "MessageBuilderContext", rb_cObject);
2083
- rb_define_alloc_func(klass, MessageBuilderContext_alloc);
2084
- rb_define_method(klass, "initialize",
2085
- MessageBuilderContext_initialize, 2);
2086
- rb_define_method(klass, "optional", MessageBuilderContext_optional, -1);
2087
- rb_define_method(klass, "proto3_optional", MessageBuilderContext_proto3_optional, -1);
2088
- rb_define_method(klass, "required", MessageBuilderContext_required, -1);
2089
- rb_define_method(klass, "repeated", MessageBuilderContext_repeated, -1);
2090
- rb_define_method(klass, "map", MessageBuilderContext_map, -1);
2091
- rb_define_method(klass, "oneof", MessageBuilderContext_oneof, 1);
2092
- rb_gc_register_address(&cMessageBuilderContext);
2093
- cMessageBuilderContext = klass;
2094
- }
2095
-
2096
- // -----------------------------------------------------------------------------
2097
- // OneofBuilderContext.
2098
- // -----------------------------------------------------------------------------
2099
-
2100
- typedef struct {
2101
- int oneof_index;
2102
- VALUE message_builder;
2103
- } OneofBuilderContext;
2104
-
2105
- static VALUE cOneofBuilderContext = Qnil;
2106
-
2107
- void OneofBuilderContext_mark(void* _self) {
2108
- OneofBuilderContext* self = _self;
2109
- rb_gc_mark(self->message_builder);
2110
- }
2111
-
2112
- static const rb_data_type_t OneofBuilderContext_type = {
2113
- "Google::Protobuf::Internal::OneofBuilderContext",
2114
- {OneofBuilderContext_mark, RUBY_DEFAULT_FREE, NULL},
2115
- .flags = RUBY_TYPED_FREE_IMMEDIATELY,
2116
- };
2117
-
2118
- static OneofBuilderContext* ruby_to_OneofBuilderContext(VALUE val) {
2119
- OneofBuilderContext* ret;
2120
- TypedData_Get_Struct(val, OneofBuilderContext, &OneofBuilderContext_type,
2121
- ret);
2122
- return ret;
2123
- }
2124
-
2125
- static VALUE OneofBuilderContext_alloc(VALUE klass) {
2126
- OneofBuilderContext* self = ALLOC(OneofBuilderContext);
2127
- VALUE ret = TypedData_Wrap_Struct(klass, &OneofBuilderContext_type, self);
2128
- self->oneof_index = 0;
2129
- self->message_builder = Qnil;
2130
- return ret;
2131
- }
2132
-
2133
- /*
2134
- * call-seq:
2135
- * OneofBuilderContext.new(oneof_index, message_builder) => context
2136
- *
2137
- * Create a new oneof builder context around the given oneof descriptor and
2138
- * builder context. This class is intended to serve as a DSL context to be used
2139
- * with #instance_eval.
2140
- */
2141
- static VALUE OneofBuilderContext_initialize(VALUE _self, VALUE oneof_index,
2142
- VALUE message_builder) {
2143
- OneofBuilderContext* self = ruby_to_OneofBuilderContext(_self);
2144
- self->oneof_index = NUM2INT(oneof_index);
2145
- self->message_builder = message_builder;
2146
- return Qnil;
2147
- }
2148
-
2149
- /*
2150
- * call-seq:
2151
- * OneofBuilderContext.optional(name, type, number, type_class = nil,
2152
- * default_value = nil)
2153
- *
2154
- * Defines a new optional field in this oneof with the given type, tag number,
2155
- * and type class (for message and enum fields). The type must be a Ruby symbol
2156
- * (as accepted by FieldDescriptor#type=) and the type_class must be a string,
2157
- * if present (as accepted by FieldDescriptor#submsg_name=).
2158
- */
2159
- static VALUE OneofBuilderContext_optional(int argc, VALUE* argv, VALUE _self) {
2160
- OneofBuilderContext* self = ruby_to_OneofBuilderContext(_self);
2161
- VALUE name, type, number;
2162
- VALUE type_class, options = Qnil;
2163
-
2164
- rb_scan_args(argc, argv, "32", &name, &type, &number, &type_class, &options);
2165
-
2166
- msgdef_add_field(self->message_builder, UPB_LABEL_OPTIONAL, name, type,
2167
- number, type_class, options, self->oneof_index, false);
2168
-
2169
- return Qnil;
2170
- }
2171
-
2172
- static void OneofBuilderContext_register(VALUE module) {
2173
- VALUE klass = rb_define_class_under(
2174
- module, "OneofBuilderContext", rb_cObject);
2175
- rb_define_alloc_func(klass, OneofBuilderContext_alloc);
2176
- rb_define_method(klass, "initialize",
2177
- OneofBuilderContext_initialize, 2);
2178
- rb_define_method(klass, "optional", OneofBuilderContext_optional, -1);
2179
- rb_gc_register_address(&cOneofBuilderContext);
2180
- cOneofBuilderContext = klass;
2181
- }
2182
-
2183
- // -----------------------------------------------------------------------------
2184
- // EnumBuilderContext.
2185
- // -----------------------------------------------------------------------------
2186
-
2187
- typedef struct {
2188
- google_protobuf_EnumDescriptorProto* enum_proto;
2189
- VALUE file_builder;
2190
- } EnumBuilderContext;
2191
-
2192
- static VALUE cEnumBuilderContext = Qnil;
2193
-
2194
- void EnumBuilderContext_mark(void* _self) {
2195
- EnumBuilderContext* self = _self;
2196
- rb_gc_mark(self->file_builder);
2197
- }
2198
-
2199
- static const rb_data_type_t EnumBuilderContext_type = {
2200
- "Google::Protobuf::Internal::EnumBuilderContext",
2201
- {EnumBuilderContext_mark, RUBY_DEFAULT_FREE, NULL},
2202
- .flags = RUBY_TYPED_FREE_IMMEDIATELY,
2203
- };
2204
-
2205
- static EnumBuilderContext* ruby_to_EnumBuilderContext(VALUE val) {
2206
- EnumBuilderContext* ret;
2207
- TypedData_Get_Struct(val, EnumBuilderContext, &EnumBuilderContext_type, ret);
2208
- return ret;
2209
- }
2210
-
2211
- static VALUE EnumBuilderContext_alloc(VALUE klass) {
2212
- EnumBuilderContext* self = ALLOC(EnumBuilderContext);
2213
- VALUE ret = TypedData_Wrap_Struct(klass, &EnumBuilderContext_type, self);
2214
- self->enum_proto = NULL;
2215
- self->file_builder = Qnil;
2216
- return ret;
2217
- }
2218
-
2219
- /*
2220
- * call-seq:
2221
- * EnumBuilderContext.new(file_builder) => context
2222
- *
2223
- * Create a new builder context around the given enum descriptor. This class is
2224
- * intended to serve as a DSL context to be used with #instance_eval.
2225
- */
2226
- static VALUE EnumBuilderContext_initialize(VALUE _self, VALUE _file_builder,
2227
- VALUE name) {
2228
- EnumBuilderContext* self = ruby_to_EnumBuilderContext(_self);
2229
- FileBuilderContext* file_builder = ruby_to_FileBuilderContext(_file_builder);
2230
- google_protobuf_FileDescriptorProto* file_proto = file_builder->file_proto;
2231
-
2232
- self->file_builder = _file_builder;
2233
- self->enum_proto = google_protobuf_FileDescriptorProto_add_enum_type(
2234
- file_proto, file_builder->arena);
2235
-
2236
- google_protobuf_EnumDescriptorProto_set_name(
2237
- self->enum_proto, FileBuilderContext_strdup(_file_builder, name));
2238
-
2239
- return Qnil;
2240
- }
2241
-
2242
- /*
2243
- * call-seq:
2244
- * EnumBuilder.add_value(name, number)
2245
- *
2246
- * Adds the given name => number mapping to the enum type. Name must be a Ruby
2247
- * symbol.
2248
- */
2249
- static VALUE EnumBuilderContext_value(VALUE _self, VALUE name, VALUE number) {
2250
- EnumBuilderContext* self = ruby_to_EnumBuilderContext(_self);
2251
- FileBuilderContext* file_builder =
2252
- ruby_to_FileBuilderContext(self->file_builder);
2253
- google_protobuf_EnumValueDescriptorProto* enum_value;
2254
-
2255
- enum_value = google_protobuf_EnumDescriptorProto_add_value(
2256
- self->enum_proto, file_builder->arena);
2257
-
2258
- google_protobuf_EnumValueDescriptorProto_set_name(
2259
- enum_value, FileBuilderContext_strdup_sym(self->file_builder, name));
2260
- google_protobuf_EnumValueDescriptorProto_set_number(enum_value,
2261
- NUM2INT(number));
2262
-
2263
- return Qnil;
2264
- }
2265
-
2266
- static void EnumBuilderContext_register(VALUE module) {
2267
- VALUE klass = rb_define_class_under(
2268
- module, "EnumBuilderContext", rb_cObject);
2269
- rb_define_alloc_func(klass, EnumBuilderContext_alloc);
2270
- rb_define_method(klass, "initialize", EnumBuilderContext_initialize, 2);
2271
- rb_define_method(klass, "value", EnumBuilderContext_value, 2);
2272
- rb_gc_register_address(&cEnumBuilderContext);
2273
- cEnumBuilderContext = klass;
2274
- }
2275
-
2276
- // -----------------------------------------------------------------------------
2277
- // Builder.
2278
- // -----------------------------------------------------------------------------
2279
-
2280
- typedef struct {
2281
- VALUE descriptor_pool;
2282
- VALUE default_file_builder;
2283
- } Builder;
2284
-
2285
- static VALUE cBuilder = Qnil;
2286
-
2287
- static void Builder_mark(void* _self) {
2288
- Builder* self = _self;
2289
- rb_gc_mark(self->descriptor_pool);
2290
- rb_gc_mark(self->default_file_builder);
2291
- }
2292
-
2293
- static const rb_data_type_t Builder_type = {
2294
- "Google::Protobuf::Internal::Builder",
2295
- {Builder_mark, RUBY_DEFAULT_FREE, NULL},
2296
- .flags = RUBY_TYPED_FREE_IMMEDIATELY,
2297
- };
2298
-
2299
- static Builder* ruby_to_Builder(VALUE val) {
2300
- Builder* ret;
2301
- TypedData_Get_Struct(val, Builder, &Builder_type, ret);
2302
- return ret;
2303
- }
2304
-
2305
- static VALUE Builder_alloc(VALUE klass) {
2306
- Builder* self = ALLOC(Builder);
2307
- VALUE ret = TypedData_Wrap_Struct(klass, &Builder_type, self);
2308
- self->descriptor_pool = Qnil;
2309
- self->default_file_builder = Qnil;
2310
- return ret;
2311
- }
2312
-
2313
- /*
2314
- * call-seq:
2315
- * Builder.new(descriptor_pool) => builder
2316
- *
2317
- * Creates a new Builder. A Builder can accumulate a set of new message and enum
2318
- * descriptors and atomically register them into a pool in a way that allows for
2319
- * (co)recursive type references.
2320
- */
2321
- static VALUE Builder_initialize(VALUE _self, VALUE pool) {
2322
- Builder* self = ruby_to_Builder(_self);
2323
- self->descriptor_pool = pool;
2324
- self->default_file_builder = Qnil; // Created lazily if needed.
2325
- return Qnil;
2326
- }
2327
-
2328
- /*
2329
- * call-seq:
2330
- * Builder.add_file(name, options = nil, &block)
2331
- *
2332
- * Creates a new, file descriptor with the given name and options and invokes
2333
- * the block in the context of a FileBuilderContext on that descriptor. The
2334
- * block can then call FileBuilderContext#add_message or
2335
- * FileBuilderContext#add_enum to define new messages or enums, respectively.
2336
- *
2337
- * This is the recommended, idiomatic way to build file descriptors.
2338
- */
2339
- static VALUE Builder_add_file(int argc, VALUE* argv, VALUE _self) {
2340
- Builder* self = ruby_to_Builder(_self);
2341
- VALUE name, options;
2342
- VALUE ctx;
2343
- VALUE block;
2344
-
2345
- rb_scan_args(argc, argv, "11", &name, &options);
2346
-
2347
- {
2348
- VALUE args[3] = { self->descriptor_pool, name, options };
2349
- ctx = rb_class_new_instance(3, args, cFileBuilderContext);
2350
- }
2351
-
2352
- block = rb_block_proc();
2353
- rb_funcall_with_block(ctx, rb_intern("instance_eval"), 0, NULL, block);
2354
- FileBuilderContext_build(ctx);
2355
-
2356
- return Qnil;
2357
- }
2358
-
2359
- static VALUE Builder_get_default_file(VALUE _self) {
2360
- Builder* self = ruby_to_Builder(_self);
2361
-
2362
- /* Lazily create only if legacy builder-level methods are called. */
2363
- if (self->default_file_builder == Qnil) {
2364
- VALUE name = rb_str_new2("ruby_default_file.proto");
2365
- VALUE args [3] = { self->descriptor_pool, name, rb_hash_new() };
2366
- self->default_file_builder =
2367
- rb_class_new_instance(3, args, cFileBuilderContext);
2368
- }
2369
-
2370
- return self->default_file_builder;
2371
- }
2372
-
2373
- /*
2374
- * call-seq:
2375
- * Builder.add_message(name, &block)
2376
- *
2377
- * Old and deprecated way to create a new descriptor.
2378
- * See FileBuilderContext.add_message for the recommended way.
2379
- *
2380
- * Exists for backwards compatibility to allow building descriptor pool for
2381
- * files generated by protoc which don't add messages within "add_file" block.
2382
- * Descriptors created this way get assigned to a default empty FileDescriptor.
2383
- */
2384
- static VALUE Builder_add_message(VALUE _self, VALUE name) {
2385
- VALUE file_builder = Builder_get_default_file(_self);
2386
- rb_funcall_with_block(file_builder, rb_intern("add_message"), 1, &name,
2387
- rb_block_proc());
2388
- return Qnil;
2389
- }
2390
-
2391
- /*
2392
- * call-seq:
2393
- * Builder.add_enum(name, &block)
2394
- *
2395
- * Old and deprecated way to create a new enum descriptor.
2396
- * See FileBuilderContext.add_enum for the recommended way.
2397
- *
2398
- * Exists for backwards compatibility to allow building descriptor pool for
2399
- * files generated by protoc which don't add enums within "add_file" block.
2400
- * Enum descriptors created this way get assigned to a default empty
2401
- * FileDescriptor.
2402
- */
2403
- static VALUE Builder_add_enum(VALUE _self, VALUE name) {
2404
- VALUE file_builder = Builder_get_default_file(_self);
2405
- rb_funcall_with_block(file_builder, rb_intern("add_enum"), 1, &name,
2406
- rb_block_proc());
2407
- return Qnil;
2408
- }
2409
-
2410
- /* This method is hidden from Ruby, and only called directly from
2411
- * DescriptorPool_build(). */
2412
- static VALUE Builder_build(VALUE _self) {
2413
- Builder* self = ruby_to_Builder(_self);
2414
-
2415
- if (self->default_file_builder != Qnil) {
2416
- FileBuilderContext_build(self->default_file_builder);
2417
- self->default_file_builder = Qnil;
2418
- }
2419
-
2420
- return Qnil;
2421
- }
2422
-
2423
- static void Builder_register(VALUE module) {
2424
- VALUE klass = rb_define_class_under(module, "Builder", rb_cObject);
2425
- rb_define_alloc_func(klass, Builder_alloc);
2426
- rb_define_method(klass, "initialize", Builder_initialize, 1);
2427
- rb_define_method(klass, "add_file", Builder_add_file, -1);
2428
- rb_define_method(klass, "add_message", Builder_add_message, 1);
2429
- rb_define_method(klass, "add_enum", Builder_add_enum, 1);
2430
- rb_gc_register_address(&cBuilder);
2431
- cBuilder = klass;
2432
- }
2433
-
2434
1166
  static VALUE get_def_obj(VALUE _descriptor_pool, const void* ptr, VALUE klass) {
2435
1167
  DescriptorPool* descriptor_pool = ruby_to_DescriptorPool(_descriptor_pool);
2436
1168
  VALUE key = ULL2NUM((intptr_t)ptr);
@@ -2546,11 +1278,6 @@ void Defs_register(VALUE module) {
2546
1278
  FieldDescriptor_register(module);
2547
1279
  OneofDescriptor_register(module);
2548
1280
  EnumDescriptor_register(module);
2549
- FileBuilderContext_register(module);
2550
- MessageBuilderContext_register(module);
2551
- OneofBuilderContext_register(module);
2552
- EnumBuilderContext_register(module);
2553
- Builder_register(module);
2554
1281
 
2555
1282
  rb_gc_register_address(&c_only_cookie);
2556
1283
  c_only_cookie = rb_class_new_instance(0, NULL, rb_cObject);