google-protobuf 3.8.0 → 3.13.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: acc61dfa5ec7487b0b62edbf098aca5a5d0ce33145cbab091a892f1ed9f240cf
4
- data.tar.gz: f7666d31441737c415008dfa0077657b8afb3c23fd0966f972b305163ffd2a02
3
+ metadata.gz: 34afa1365c4de64d0a8922c15490b0a0559bd36d87d8fed0e37d42a6e73d7441
4
+ data.tar.gz: 742745747e3b4f4c5ebe0fdec56071c7482c45fa1ebd32629cdde8863dedcea1
5
5
  SHA512:
6
- metadata.gz: 481d523e6d2dc363c73695025811bcc181358513a9a7931d4f19d6c9aab40a085a2e02e97d5370069f339897b8170fd3ddca906952717233e582cd10a9dcfd4c
7
- data.tar.gz: 9cf2022047f865793c3edc480147e1e2c27f1d1d676239090c32f3356a8c4f6f6405bde3b8a879aeb9200725d7e340f9fec8d1457ed37411feb3b4d0546dd96c
6
+ metadata.gz: c66aff4b91bc21111a4fa09cd3f562d8cd6a2b9405f5248d7b913a171316aa6b565b5c65c01dbbe8c4ca7e34c98b7fd571b129d3b069ee2dca5b367c633dfeff
7
+ data.tar.gz: fd938105444fc70d75046efa3b28ab220b44fcf7c3e9e93934db642448f1ae960db8ab7de2af1656deeede09a46ab8b46d87ae24acf6d9e6ce80b654f0f8ecc7
@@ -28,6 +28,8 @@
28
28
  // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
29
  // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
30
 
31
+ #include <ctype.h>
32
+ #include <errno.h>
31
33
  #include "protobuf.h"
32
34
 
33
35
  // -----------------------------------------------------------------------------
@@ -46,29 +48,290 @@ static VALUE rb_str_maybe_null(const char* s) {
46
48
  return rb_str_new2(s);
47
49
  }
48
50
 
49
- static upb_def* check_notfrozen(const upb_def* def) {
50
- if (upb_def_isfrozen(def)) {
51
- rb_raise(rb_eRuntimeError,
52
- "Attempt to modify a frozen descriptor. Once descriptors are "
53
- "added to the descriptor pool, they may not be modified.");
51
+ static void rewrite_enum_default(const upb_symtab* symtab,
52
+ google_protobuf_FileDescriptorProto* file,
53
+ google_protobuf_FieldDescriptorProto* field) {
54
+ upb_strview defaultval;
55
+ const char *type_name_str;
56
+ char *end;
57
+ long val;
58
+ const upb_enumdef *e;
59
+ upb_strview type_name;
60
+
61
+ /* Look for TYPE_ENUM fields that have a default. */
62
+ if (google_protobuf_FieldDescriptorProto_type(field) !=
63
+ google_protobuf_FieldDescriptorProto_TYPE_ENUM ||
64
+ !google_protobuf_FieldDescriptorProto_has_default_value(field) ||
65
+ !google_protobuf_FieldDescriptorProto_has_type_name(field)) {
66
+ return;
54
67
  }
55
- return (upb_def*)def;
56
- }
57
68
 
58
- static upb_msgdef* check_msg_notfrozen(const upb_msgdef* def) {
59
- return upb_downcast_msgdef_mutable(check_notfrozen((const upb_def*)def));
69
+ defaultval = google_protobuf_FieldDescriptorProto_default_value(field);
70
+ type_name = google_protobuf_FieldDescriptorProto_type_name(field);
71
+
72
+ if (defaultval.size == 0 || !isdigit(defaultval.data[0])) {
73
+ return;
74
+ }
75
+
76
+ if (type_name.size == 0 || type_name.data[0] != '.') {
77
+ return;
78
+ }
79
+
80
+ type_name_str = type_name.data + 1;
81
+
82
+ errno = 0;
83
+ val = strtol(defaultval.data, &end, 10);
84
+
85
+ if (errno != 0 || *end != 0 || val < INT32_MIN || val > INT32_MAX) {
86
+ return;
87
+ }
88
+
89
+ /* Now find the corresponding enum definition. */
90
+ e = upb_symtab_lookupenum(symtab, type_name_str);
91
+ if (e) {
92
+ /* Look in previously loaded files. */
93
+ const char *label = upb_enumdef_iton(e, val);
94
+ if (!label) {
95
+ return;
96
+ }
97
+ google_protobuf_FieldDescriptorProto_set_default_value(
98
+ field, upb_strview_makez(label));
99
+ } else {
100
+ /* Look in enums defined in this file. */
101
+ const google_protobuf_EnumDescriptorProto* matching_enum = NULL;
102
+ size_t i, n;
103
+ const google_protobuf_EnumDescriptorProto* const* enums =
104
+ google_protobuf_FileDescriptorProto_enum_type(file, &n);
105
+ const google_protobuf_EnumValueDescriptorProto* const* values;
106
+
107
+ for (i = 0; i < n; i++) {
108
+ if (upb_strview_eql(google_protobuf_EnumDescriptorProto_name(enums[i]),
109
+ upb_strview_makez(type_name_str))) {
110
+ matching_enum = enums[i];
111
+ break;
112
+ }
113
+ }
114
+
115
+ if (!matching_enum) {
116
+ return;
117
+ }
118
+
119
+ values = google_protobuf_EnumDescriptorProto_value(matching_enum, &n);
120
+ for (i = 0; i < n; i++) {
121
+ if (google_protobuf_EnumValueDescriptorProto_number(values[i]) == val) {
122
+ google_protobuf_FieldDescriptorProto_set_default_value(
123
+ field, google_protobuf_EnumValueDescriptorProto_name(values[i]));
124
+ return;
125
+ }
126
+ }
127
+
128
+ /* We failed to find an enum default. But we'll just leave the enum
129
+ * untouched and let the normal def-building code catch it. */
130
+ }
60
131
  }
61
132
 
62
- static upb_fielddef* check_field_notfrozen(const upb_fielddef* def) {
63
- return upb_downcast_fielddef_mutable(check_notfrozen((const upb_def*)def));
133
+ /* Historically we allowed enum defaults to be specified as a number. In
134
+ * retrospect this was a mistake as descriptors require defaults to be
135
+ * specified as a label. This can make a difference if multiple labels have the
136
+ * same number.
137
+ *
138
+ * Here we do a pass over all enum defaults and rewrite numeric defaults by
139
+ * looking up their labels. This is complicated by the fact that the enum
140
+ * definition can live in either the symtab or the file_proto.
141
+ * */
142
+ static void rewrite_enum_defaults(
143
+ const upb_symtab* symtab, google_protobuf_FileDescriptorProto* file_proto) {
144
+ size_t i, n;
145
+ google_protobuf_DescriptorProto** msgs =
146
+ google_protobuf_FileDescriptorProto_mutable_message_type(file_proto, &n);
147
+
148
+ for (i = 0; i < n; i++) {
149
+ size_t j, m;
150
+ google_protobuf_FieldDescriptorProto** fields =
151
+ google_protobuf_DescriptorProto_mutable_field(msgs[i], &m);
152
+ for (j = 0; j < m; j++) {
153
+ rewrite_enum_default(symtab, file_proto, fields[j]);
154
+ }
155
+ }
64
156
  }
65
157
 
66
- static upb_oneofdef* check_oneof_notfrozen(const upb_oneofdef* def) {
67
- return (upb_oneofdef*)check_notfrozen((const upb_def*)def);
158
+ static void remove_path(upb_strview *name) {
159
+ const char* last = strrchr(name->data, '.');
160
+ if (last) {
161
+ size_t remove = last - name->data + 1;
162
+ name->data += remove;
163
+ name->size -= remove;
164
+ }
165
+ }
166
+
167
+ static void rewrite_nesting(VALUE msg_ent, google_protobuf_DescriptorProto* msg,
168
+ google_protobuf_DescriptorProto* const* msgs,
169
+ google_protobuf_EnumDescriptorProto* const* enums,
170
+ upb_arena *arena) {
171
+ VALUE submsgs = rb_hash_aref(msg_ent, ID2SYM(rb_intern("msgs")));
172
+ VALUE enum_pos = rb_hash_aref(msg_ent, ID2SYM(rb_intern("enums")));
173
+ int submsg_count;
174
+ int enum_count;
175
+ int i;
176
+ google_protobuf_DescriptorProto** msg_msgs;
177
+ google_protobuf_EnumDescriptorProto** msg_enums;
178
+
179
+ Check_Type(submsgs, T_ARRAY);
180
+ Check_Type(enum_pos, T_ARRAY);
181
+
182
+ submsg_count = RARRAY_LEN(submsgs);
183
+ enum_count = RARRAY_LEN(enum_pos);
184
+
185
+ msg_msgs = google_protobuf_DescriptorProto_resize_nested_type(
186
+ msg, submsg_count, arena);
187
+ msg_enums =
188
+ google_protobuf_DescriptorProto_resize_enum_type(msg, enum_count, arena);
189
+
190
+ for (i = 0; i < submsg_count; i++) {
191
+ VALUE submsg_ent = RARRAY_PTR(submsgs)[i];
192
+ VALUE pos = rb_hash_aref(submsg_ent, ID2SYM(rb_intern("pos")));
193
+ upb_strview name;
194
+
195
+ msg_msgs[i] = msgs[NUM2INT(pos)];
196
+ name = google_protobuf_DescriptorProto_name(msg_msgs[i]);
197
+ remove_path(&name);
198
+ google_protobuf_DescriptorProto_set_name(msg_msgs[i], name);
199
+ rewrite_nesting(submsg_ent, msg_msgs[i], msgs, enums, arena);
200
+ }
201
+
202
+ for (i = 0; i < enum_count; i++) {
203
+ VALUE pos = RARRAY_PTR(enum_pos)[i];
204
+ msg_enums[i] = enums[NUM2INT(pos)];
205
+ }
68
206
  }
69
207
 
70
- static upb_enumdef* check_enum_notfrozen(const upb_enumdef* def) {
71
- return (upb_enumdef*)check_notfrozen((const upb_def*)def);
208
+ /* We have to do some relatively complicated logic here for backward
209
+ * compatibility.
210
+ *
211
+ * In descriptor.proto, messages are nested inside other messages if that is
212
+ * what the original .proto file looks like. For example, suppose we have this
213
+ * foo.proto:
214
+ *
215
+ * package foo;
216
+ * message Bar {
217
+ * message Baz {}
218
+ * }
219
+ *
220
+ * The descriptor for this must look like this:
221
+ *
222
+ * file {
223
+ * name: "test.proto"
224
+ * package: "foo"
225
+ * message_type {
226
+ * name: "Bar"
227
+ * nested_type {
228
+ * name: "Baz"
229
+ * }
230
+ * }
231
+ * }
232
+ *
233
+ * However, the Ruby generated code has always generated messages in a flat,
234
+ * non-nested way:
235
+ *
236
+ * Google::Protobuf::DescriptorPool.generated_pool.build do
237
+ * add_message "foo.Bar" do
238
+ * end
239
+ * add_message "foo.Bar.Baz" do
240
+ * end
241
+ * end
242
+ *
243
+ * Here we need to do a translation where we turn this generated code into the
244
+ * above descriptor. We need to infer that "foo" is the package name, and not
245
+ * a message itself.
246
+ *
247
+ * We delegate to Ruby to compute the transformation, for more concice and
248
+ * readable code than we can do in C */
249
+ static void rewrite_names(VALUE _file_builder,
250
+ google_protobuf_FileDescriptorProto* file_proto) {
251
+ FileBuilderContext* file_builder = ruby_to_FileBuilderContext(_file_builder);
252
+ upb_arena *arena = file_builder->arena;
253
+ // Build params (package, msg_names, enum_names).
254
+ VALUE package = Qnil;
255
+ VALUE msg_names = rb_ary_new();
256
+ VALUE enum_names = rb_ary_new();
257
+ size_t msg_count, enum_count, i;
258
+ VALUE new_package, nesting, msg_ents, enum_ents;
259
+ google_protobuf_DescriptorProto** msgs;
260
+ google_protobuf_EnumDescriptorProto** enums;
261
+
262
+ if (google_protobuf_FileDescriptorProto_has_package(file_proto)) {
263
+ upb_strview package_str =
264
+ google_protobuf_FileDescriptorProto_package(file_proto);
265
+ package = rb_str_new(package_str.data, package_str.size);
266
+ }
267
+
268
+ msgs = google_protobuf_FileDescriptorProto_mutable_message_type(file_proto,
269
+ &msg_count);
270
+ for (i = 0; i < msg_count; i++) {
271
+ upb_strview name = google_protobuf_DescriptorProto_name(msgs[i]);
272
+ rb_ary_push(msg_names, rb_str_new(name.data, name.size));
273
+ }
274
+
275
+ enums = google_protobuf_FileDescriptorProto_mutable_enum_type(file_proto,
276
+ &enum_count);
277
+ for (i = 0; i < enum_count; i++) {
278
+ upb_strview name = google_protobuf_EnumDescriptorProto_name(enums[i]);
279
+ rb_ary_push(enum_names, rb_str_new(name.data, name.size));
280
+ }
281
+
282
+ {
283
+ // Call Ruby code to calculate package name and nesting.
284
+ VALUE args[3] = { package, msg_names, enum_names };
285
+ VALUE internal = rb_eval_string("Google::Protobuf::Internal");
286
+ VALUE ret = rb_funcallv(internal, rb_intern("fixup_descriptor"), 3, args);
287
+
288
+ new_package = rb_ary_entry(ret, 0);
289
+ nesting = rb_ary_entry(ret, 1);
290
+ }
291
+
292
+ // Rewrite package and names.
293
+ if (new_package != Qnil) {
294
+ upb_strview new_package_str =
295
+ FileBuilderContext_strdup(_file_builder, new_package);
296
+ google_protobuf_FileDescriptorProto_set_package(file_proto,
297
+ new_package_str);
298
+ }
299
+
300
+ for (i = 0; i < msg_count; i++) {
301
+ upb_strview name = google_protobuf_DescriptorProto_name(msgs[i]);
302
+ remove_path(&name);
303
+ google_protobuf_DescriptorProto_set_name(msgs[i], name);
304
+ }
305
+
306
+ for (i = 0; i < enum_count; i++) {
307
+ upb_strview name = google_protobuf_EnumDescriptorProto_name(enums[i]);
308
+ remove_path(&name);
309
+ google_protobuf_EnumDescriptorProto_set_name(enums[i], name);
310
+ }
311
+
312
+ // Rewrite nesting.
313
+ msg_ents = rb_hash_aref(nesting, ID2SYM(rb_intern("msgs")));
314
+ enum_ents = rb_hash_aref(nesting, ID2SYM(rb_intern("enums")));
315
+
316
+ Check_Type(msg_ents, T_ARRAY);
317
+ Check_Type(enum_ents, T_ARRAY);
318
+
319
+ for (i = 0; i < (size_t)RARRAY_LEN(msg_ents); i++) {
320
+ VALUE msg_ent = rb_ary_entry(msg_ents, i);
321
+ VALUE pos = rb_hash_aref(msg_ent, ID2SYM(rb_intern("pos")));
322
+ msgs[i] = msgs[NUM2INT(pos)];
323
+ rewrite_nesting(msg_ent, msgs[i], msgs, enums, arena);
324
+ }
325
+
326
+ for (i = 0; i < (size_t)RARRAY_LEN(enum_ents); i++) {
327
+ VALUE enum_pos = rb_ary_entry(enum_ents, i);
328
+ enums[i] = enums[NUM2INT(enum_pos)];
329
+ }
330
+
331
+ google_protobuf_FileDescriptorProto_resize_message_type(
332
+ file_proto, RARRAY_LEN(msg_ents), arena);
333
+ google_protobuf_FileDescriptorProto_resize_enum_type(
334
+ file_proto, RARRAY_LEN(enum_ents), arena);
72
335
  }
73
336
 
74
337
  // -----------------------------------------------------------------------------
@@ -92,16 +355,26 @@ static upb_enumdef* check_enum_notfrozen(const upb_enumdef* def) {
92
355
 
93
356
  // Global singleton DescriptorPool. The user is free to create others, but this
94
357
  // is used by generated code.
95
- VALUE generated_pool;
358
+ VALUE generated_pool = Qnil;
96
359
 
97
360
  DEFINE_CLASS(DescriptorPool, "Google::Protobuf::DescriptorPool");
98
361
 
99
362
  void DescriptorPool_mark(void* _self) {
363
+ DescriptorPool* self = _self;
364
+ rb_gc_mark(self->def_to_descriptor);
100
365
  }
101
366
 
102
367
  void DescriptorPool_free(void* _self) {
103
368
  DescriptorPool* self = _self;
369
+
104
370
  upb_symtab_free(self->symtab);
371
+ upb_handlercache_free(self->fill_handler_cache);
372
+ upb_handlercache_free(self->pb_serialize_handler_cache);
373
+ upb_handlercache_free(self->json_serialize_handler_cache);
374
+ upb_handlercache_free(self->json_serialize_handler_preserve_cache);
375
+ upb_pbcodecache_free(self->fill_method_cache);
376
+ upb_json_codecache_free(self->json_fill_method_cache);
377
+
105
378
  xfree(self);
106
379
  }
107
380
 
@@ -113,15 +386,29 @@ void DescriptorPool_free(void* _self) {
113
386
  */
114
387
  VALUE DescriptorPool_alloc(VALUE klass) {
115
388
  DescriptorPool* self = ALLOC(DescriptorPool);
389
+ VALUE ret;
390
+
391
+ self->def_to_descriptor = Qnil;
392
+ ret = TypedData_Wrap_Struct(klass, &_DescriptorPool_type, self);
393
+
394
+ self->def_to_descriptor = rb_hash_new();
116
395
  self->symtab = upb_symtab_new();
117
- return TypedData_Wrap_Struct(klass, &_DescriptorPool_type, self);
396
+ self->fill_handler_cache =
397
+ upb_handlercache_new(add_handlers_for_message, (void*)ret);
398
+ self->pb_serialize_handler_cache = upb_pb_encoder_newcache();
399
+ self->json_serialize_handler_cache = upb_json_printer_newcache(false);
400
+ self->json_serialize_handler_preserve_cache =
401
+ upb_json_printer_newcache(true);
402
+ self->fill_method_cache = upb_pbcodecache_new(self->fill_handler_cache);
403
+ self->json_fill_method_cache = upb_json_codecache_new();
404
+
405
+ return ret;
118
406
  }
119
407
 
120
408
  void DescriptorPool_register(VALUE module) {
121
409
  VALUE klass = rb_define_class_under(
122
410
  module, "DescriptorPool", rb_cObject);
123
411
  rb_define_alloc_func(klass, DescriptorPool_alloc);
124
- rb_define_method(klass, "add", DescriptorPool_add, 1);
125
412
  rb_define_method(klass, "build", DescriptorPool_build, -1);
126
413
  rb_define_method(klass, "lookup", DescriptorPool_lookup, 1);
127
414
  rb_define_singleton_method(klass, "generated_pool",
@@ -133,44 +420,6 @@ void DescriptorPool_register(VALUE module) {
133
420
  generated_pool = rb_class_new_instance(0, NULL, klass);
134
421
  }
135
422
 
136
- static void add_descriptor_to_pool(DescriptorPool* self,
137
- Descriptor* descriptor) {
138
- CHECK_UPB(
139
- upb_symtab_add(self->symtab, (upb_def**)&descriptor->msgdef, 1,
140
- NULL, &status),
141
- "Adding Descriptor to DescriptorPool failed");
142
- }
143
-
144
- static void add_enumdesc_to_pool(DescriptorPool* self,
145
- EnumDescriptor* enumdesc) {
146
- CHECK_UPB(
147
- upb_symtab_add(self->symtab, (upb_def**)&enumdesc->enumdef, 1,
148
- NULL, &status),
149
- "Adding EnumDescriptor to DescriptorPool failed");
150
- }
151
-
152
- /*
153
- * call-seq:
154
- * DescriptorPool.add(descriptor)
155
- *
156
- * Adds the given Descriptor or EnumDescriptor to this pool. All references to
157
- * other types in a Descriptor's fields must be resolvable within this pool or
158
- * an exception will be raised.
159
- */
160
- VALUE DescriptorPool_add(VALUE _self, VALUE def) {
161
- DEFINE_SELF(DescriptorPool, self, _self);
162
- VALUE def_klass = rb_obj_class(def);
163
- if (def_klass == cDescriptor) {
164
- add_descriptor_to_pool(self, ruby_to_Descriptor(def));
165
- } else if (def_klass == cEnumDescriptor) {
166
- add_enumdesc_to_pool(self, ruby_to_EnumDescriptor(def));
167
- } else {
168
- rb_raise(rb_eArgError,
169
- "Second argument must be a Descriptor or EnumDescriptor.");
170
- }
171
- return Qnil;
172
- }
173
-
174
423
  /*
175
424
  * call-seq:
176
425
  * DescriptorPool.build(&block)
@@ -182,10 +431,10 @@ VALUE DescriptorPool_add(VALUE _self, VALUE def) {
182
431
  * idiomatic way to define new message and enum types.
183
432
  */
184
433
  VALUE DescriptorPool_build(int argc, VALUE* argv, VALUE _self) {
185
- VALUE ctx = rb_class_new_instance(0, NULL, cBuilder);
434
+ VALUE ctx = rb_class_new_instance(1, &_self, cBuilder);
186
435
  VALUE block = rb_block_proc();
187
436
  rb_funcall_with_block(ctx, rb_intern("instance_eval"), 0, NULL, block);
188
- rb_funcall(ctx, rb_intern("finalize_to_pool"), 1, _self);
437
+ Builder_build(ctx);
189
438
  return Qnil;
190
439
  }
191
440
 
@@ -199,11 +448,20 @@ VALUE DescriptorPool_build(int argc, VALUE* argv, VALUE _self) {
199
448
  VALUE DescriptorPool_lookup(VALUE _self, VALUE name) {
200
449
  DEFINE_SELF(DescriptorPool, self, _self);
201
450
  const char* name_str = get_str(name);
202
- const upb_def* def = upb_symtab_lookup(self->symtab, name_str);
203
- if (!def) {
204
- return Qnil;
451
+ const upb_msgdef* msgdef;
452
+ const upb_enumdef* enumdef;
453
+
454
+ msgdef = upb_symtab_lookupmsg(self->symtab, name_str);
455
+ if (msgdef) {
456
+ return get_msgdef_obj(_self, msgdef);
205
457
  }
206
- return get_def_obj(def);
458
+
459
+ enumdef = upb_symtab_lookupenum(self->symtab, name_str);
460
+ if (enumdef) {
461
+ return get_enumdef_obj(_self, enumdef);
462
+ }
463
+
464
+ return Qnil;
207
465
  }
208
466
 
209
467
  /*
@@ -228,36 +486,17 @@ DEFINE_CLASS(Descriptor, "Google::Protobuf::Descriptor");
228
486
  void Descriptor_mark(void* _self) {
229
487
  Descriptor* self = _self;
230
488
  rb_gc_mark(self->klass);
489
+ rb_gc_mark(self->descriptor_pool);
490
+ if (self->layout && self->layout->empty_template) {
491
+ layout_mark(self->layout, self->layout->empty_template);
492
+ }
231
493
  }
232
494
 
233
495
  void Descriptor_free(void* _self) {
234
496
  Descriptor* self = _self;
235
- upb_msgdef_unref(self->msgdef, &self->msgdef);
236
497
  if (self->layout) {
237
498
  free_layout(self->layout);
238
499
  }
239
- if (self->fill_handlers) {
240
- upb_handlers_unref(self->fill_handlers, &self->fill_handlers);
241
- }
242
- if (self->fill_method) {
243
- upb_pbdecodermethod_unref(self->fill_method, &self->fill_method);
244
- }
245
- if (self->json_fill_method) {
246
- upb_json_parsermethod_unref(self->json_fill_method,
247
- &self->json_fill_method);
248
- }
249
- if (self->pb_serialize_handlers) {
250
- upb_handlers_unref(self->pb_serialize_handlers,
251
- &self->pb_serialize_handlers);
252
- }
253
- if (self->json_serialize_handlers) {
254
- upb_handlers_unref(self->json_serialize_handlers,
255
- &self->json_serialize_handlers);
256
- }
257
- if (self->json_serialize_handlers_preserve) {
258
- upb_handlers_unref(self->json_serialize_handlers_preserve,
259
- &self->json_serialize_handlers_preserve);
260
- }
261
500
  xfree(self);
262
501
  }
263
502
 
@@ -273,15 +512,10 @@ void Descriptor_free(void* _self) {
273
512
  VALUE Descriptor_alloc(VALUE klass) {
274
513
  Descriptor* self = ALLOC(Descriptor);
275
514
  VALUE ret = TypedData_Wrap_Struct(klass, &_Descriptor_type, self);
276
- self->msgdef = upb_msgdef_new(&self->msgdef);
515
+ self->msgdef = NULL;
277
516
  self->klass = Qnil;
517
+ self->descriptor_pool = Qnil;
278
518
  self->layout = NULL;
279
- self->fill_handlers = NULL;
280
- self->fill_method = NULL;
281
- self->json_fill_method = NULL;
282
- self->pb_serialize_handlers = NULL;
283
- self->json_serialize_handlers = NULL;
284
- self->json_serialize_handlers_preserve = NULL;
285
519
  return ret;
286
520
  }
287
521
 
@@ -289,16 +523,13 @@ void Descriptor_register(VALUE module) {
289
523
  VALUE klass = rb_define_class_under(
290
524
  module, "Descriptor", rb_cObject);
291
525
  rb_define_alloc_func(klass, Descriptor_alloc);
292
- rb_define_method(klass, "initialize", Descriptor_initialize, 1);
526
+ rb_define_method(klass, "initialize", Descriptor_initialize, 3);
293
527
  rb_define_method(klass, "each", Descriptor_each, 0);
294
528
  rb_define_method(klass, "lookup", Descriptor_lookup, 1);
295
- rb_define_method(klass, "add_field", Descriptor_add_field, 1);
296
- rb_define_method(klass, "add_oneof", Descriptor_add_oneof, 1);
297
529
  rb_define_method(klass, "each_oneof", Descriptor_each_oneof, 0);
298
530
  rb_define_method(klass, "lookup_oneof", Descriptor_lookup_oneof, 1);
299
531
  rb_define_method(klass, "msgclass", Descriptor_msgclass, 0);
300
532
  rb_define_method(klass, "name", Descriptor_name, 0);
301
- rb_define_method(klass, "name=", Descriptor_name_set, 1);
302
533
  rb_define_method(klass, "file_descriptor", Descriptor_file_descriptor, 0);
303
534
  rb_include_module(klass, rb_mEnumerable);
304
535
  rb_gc_register_address(&cDescriptor);
@@ -307,19 +538,21 @@ void Descriptor_register(VALUE module) {
307
538
 
308
539
  /*
309
540
  * call-seq:
310
- * Descriptor.new(file_descriptor)
541
+ * Descriptor.new(c_only_cookie, ptr) => Descriptor
311
542
  *
312
- * Initializes a new descriptor and assigns a file descriptor to it.
543
+ * Creates a descriptor wrapper object. May only be called from C.
313
544
  */
314
- VALUE Descriptor_initialize(VALUE _self, VALUE file_descriptor_rb) {
545
+ VALUE Descriptor_initialize(VALUE _self, VALUE cookie,
546
+ VALUE descriptor_pool, VALUE ptr) {
315
547
  DEFINE_SELF(Descriptor, self, _self);
316
548
 
317
- FileDescriptor* file_descriptor = ruby_to_FileDescriptor(file_descriptor_rb);
549
+ if (cookie != c_only_cookie) {
550
+ rb_raise(rb_eRuntimeError,
551
+ "Descriptor objects may not be created from Ruby.");
552
+ }
318
553
 
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);
554
+ self->descriptor_pool = descriptor_pool;
555
+ self->msgdef = (const upb_msgdef*)NUM2ULL(ptr);
323
556
 
324
557
  return Qnil;
325
558
  }
@@ -332,14 +565,14 @@ VALUE Descriptor_initialize(VALUE _self, VALUE file_descriptor_rb) {
332
565
  */
333
566
  VALUE Descriptor_file_descriptor(VALUE _self) {
334
567
  DEFINE_SELF(Descriptor, self, _self);
335
- return get_def_obj(upb_def_file(self->msgdef));
568
+ return get_filedef_obj(self->descriptor_pool, upb_msgdef_file(self->msgdef));
336
569
  }
337
570
 
338
571
  /*
339
572
  * call-seq:
340
573
  * Descriptor.name => name
341
574
  *
342
- * Returns the name of this message type as a fully-qualfied string (e.g.,
575
+ * Returns the name of this message type as a fully-qualified string (e.g.,
343
576
  * My.Package.MessageType).
344
577
  */
345
578
  VALUE Descriptor_name(VALUE _self) {
@@ -347,23 +580,6 @@ VALUE Descriptor_name(VALUE _self) {
347
580
  return rb_str_maybe_null(upb_msgdef_fullname(self->msgdef));
348
581
  }
349
582
 
350
- /*
351
- * call-seq:
352
- * Descriptor.name = name
353
- *
354
- * Assigns a name to this message type. The descriptor must not have been added
355
- * to a pool yet.
356
- */
357
- VALUE Descriptor_name_set(VALUE _self, VALUE str) {
358
- DEFINE_SELF(Descriptor, self, _self);
359
- upb_msgdef* mut_def = check_msg_notfrozen(self->msgdef);
360
- const char* name = get_str(str);
361
- CHECK_UPB(
362
- upb_msgdef_setfullname(mut_def, name, &status),
363
- "Error setting Descriptor name");
364
- return Qnil;
365
- }
366
-
367
583
  /*
368
584
  * call-seq:
369
585
  * Descriptor.each(&block)
@@ -378,7 +594,7 @@ VALUE Descriptor_each(VALUE _self) {
378
594
  !upb_msg_field_done(&it);
379
595
  upb_msg_field_next(&it)) {
380
596
  const upb_fielddef* field = upb_msg_iter_field(&it);
381
- VALUE obj = get_def_obj(field);
597
+ VALUE obj = get_fielddef_obj(self->descriptor_pool, field);
382
598
  rb_yield(obj);
383
599
  }
384
600
  return Qnil;
@@ -398,51 +614,7 @@ VALUE Descriptor_lookup(VALUE _self, VALUE name) {
398
614
  if (field == NULL) {
399
615
  return Qnil;
400
616
  }
401
- return get_def_obj(field);
402
- }
403
-
404
- /*
405
- * call-seq:
406
- * Descriptor.add_field(field) => nil
407
- *
408
- * Adds the given FieldDescriptor to this message type. This descriptor must not
409
- * have been added to a pool yet. Raises an exception if a field with the same
410
- * name or number already exists. Sub-type references (e.g. for fields of type
411
- * message) are not resolved at this point.
412
- */
413
- VALUE Descriptor_add_field(VALUE _self, VALUE obj) {
414
- DEFINE_SELF(Descriptor, self, _self);
415
- upb_msgdef* mut_def = check_msg_notfrozen(self->msgdef);
416
- FieldDescriptor* def = ruby_to_FieldDescriptor(obj);
417
- upb_fielddef* mut_field_def = check_field_notfrozen(def->fielddef);
418
- CHECK_UPB(
419
- upb_msgdef_addfield(mut_def, mut_field_def, NULL, &status),
420
- "Adding field to Descriptor failed");
421
- add_def_obj(def->fielddef, obj);
422
- return Qnil;
423
- }
424
-
425
- /*
426
- * call-seq:
427
- * Descriptor.add_oneof(oneof) => nil
428
- *
429
- * Adds the given OneofDescriptor to this message type. This descriptor must not
430
- * have been added to a pool yet. Raises an exception if a oneof with the same
431
- * name already exists, or if any of the oneof's fields' names or numbers
432
- * conflict with an existing field in this message type. All fields in the oneof
433
- * are added to the message descriptor. Sub-type references (e.g. for fields of
434
- * type message) are not resolved at this point.
435
- */
436
- VALUE Descriptor_add_oneof(VALUE _self, VALUE obj) {
437
- DEFINE_SELF(Descriptor, self, _self);
438
- upb_msgdef* mut_def = check_msg_notfrozen(self->msgdef);
439
- OneofDescriptor* def = ruby_to_OneofDescriptor(obj);
440
- upb_oneofdef* mut_oneof_def = check_oneof_notfrozen(def->oneofdef);
441
- CHECK_UPB(
442
- upb_msgdef_addoneof(mut_def, mut_oneof_def, NULL, &status),
443
- "Adding oneof to Descriptor failed");
444
- add_def_obj(def->oneofdef, obj);
445
- return Qnil;
617
+ return get_fielddef_obj(self->descriptor_pool, field);
446
618
  }
447
619
 
448
620
  /*
@@ -460,7 +632,7 @@ VALUE Descriptor_each_oneof(VALUE _self) {
460
632
  !upb_msg_oneof_done(&it);
461
633
  upb_msg_oneof_next(&it)) {
462
634
  const upb_oneofdef* oneof = upb_msg_iter_oneof(&it);
463
- VALUE obj = get_def_obj(oneof);
635
+ VALUE obj = get_oneofdef_obj(self->descriptor_pool, oneof);
464
636
  rb_yield(obj);
465
637
  }
466
638
  return Qnil;
@@ -480,24 +652,19 @@ VALUE Descriptor_lookup_oneof(VALUE _self, VALUE name) {
480
652
  if (oneof == NULL) {
481
653
  return Qnil;
482
654
  }
483
- return get_def_obj(oneof);
655
+ return get_oneofdef_obj(self->descriptor_pool, oneof);
484
656
  }
485
657
 
486
658
  /*
487
659
  * call-seq:
488
660
  * Descriptor.msgclass => message_klass
489
661
  *
490
- * Returns the Ruby class created for this message type. Valid only once the
491
- * message type has been added to a pool.
662
+ * Returns the Ruby class created for this message type.
492
663
  */
493
664
  VALUE Descriptor_msgclass(VALUE _self) {
494
665
  DEFINE_SELF(Descriptor, self, _self);
495
- if (!upb_def_isfrozen((const upb_def*)self->msgdef)) {
496
- rb_raise(rb_eRuntimeError,
497
- "Cannot fetch message class from a Descriptor not yet in a pool.");
498
- }
499
666
  if (self->klass == Qnil) {
500
- self->klass = build_class_from_descriptor(self);
667
+ self->klass = build_class_from_descriptor(_self);
501
668
  }
502
669
  return self->klass;
503
670
  }
@@ -509,12 +676,20 @@ VALUE Descriptor_msgclass(VALUE _self) {
509
676
  DEFINE_CLASS(FileDescriptor, "Google::Protobuf::FileDescriptor");
510
677
 
511
678
  void FileDescriptor_mark(void* _self) {
679
+ FileDescriptor* self = _self;
680
+ rb_gc_mark(self->descriptor_pool);
512
681
  }
513
682
 
514
683
  void FileDescriptor_free(void* _self) {
515
- FileDescriptor* self = _self;
516
- upb_filedef_unref(self->filedef, &self->filedef);
517
- xfree(self);
684
+ xfree(_self);
685
+ }
686
+
687
+ VALUE FileDescriptor_alloc(VALUE klass) {
688
+ FileDescriptor* self = ALLOC(FileDescriptor);
689
+ VALUE ret = TypedData_Wrap_Struct(klass, &_FileDescriptor_type, self);
690
+ self->descriptor_pool = Qnil;
691
+ self->filedef = NULL;
692
+ return ret;
518
693
  }
519
694
 
520
695
  /*
@@ -524,64 +699,32 @@ void FileDescriptor_free(void* _self) {
524
699
  * Returns a new file descriptor. The syntax must be set before it's passed
525
700
  * to a builder.
526
701
  */
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;
702
+ VALUE FileDescriptor_initialize(VALUE _self, VALUE cookie,
703
+ VALUE descriptor_pool, VALUE ptr) {
704
+ DEFINE_SELF(FileDescriptor, self, _self);
705
+
706
+ if (cookie != c_only_cookie) {
707
+ rb_raise(rb_eRuntimeError,
708
+ "Descriptor objects may not be created from Ruby.");
709
+ }
710
+
711
+ self->descriptor_pool = descriptor_pool;
712
+ self->filedef = (const upb_filedef*)NUM2ULL(ptr);
713
+
714
+ return Qnil;
533
715
  }
534
716
 
535
717
  void FileDescriptor_register(VALUE module) {
536
718
  VALUE klass = rb_define_class_under(
537
719
  module, "FileDescriptor", rb_cObject);
538
720
  rb_define_alloc_func(klass, FileDescriptor_alloc);
539
- rb_define_method(klass, "initialize", FileDescriptor_initialize, -1);
721
+ rb_define_method(klass, "initialize", FileDescriptor_initialize, 3);
540
722
  rb_define_method(klass, "name", FileDescriptor_name, 0);
541
723
  rb_define_method(klass, "syntax", FileDescriptor_syntax, 0);
542
- rb_define_method(klass, "syntax=", FileDescriptor_syntax_set, 1);
543
724
  rb_gc_register_address(&cFileDescriptor);
544
725
  cFileDescriptor = klass;
545
726
  }
546
727
 
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
728
  /*
586
729
  * call-seq:
587
730
  * FileDescriptor.name => name
@@ -613,31 +756,6 @@ VALUE FileDescriptor_syntax(VALUE _self) {
613
756
  }
614
757
  }
615
758
 
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
-
641
759
  // -----------------------------------------------------------------------------
642
760
  // FieldDescriptor.
643
761
  // -----------------------------------------------------------------------------
@@ -645,12 +763,12 @@ VALUE FileDescriptor_syntax_set(VALUE _self, VALUE syntax_rb) {
645
763
  DEFINE_CLASS(FieldDescriptor, "Google::Protobuf::FieldDescriptor");
646
764
 
647
765
  void FieldDescriptor_mark(void* _self) {
766
+ FieldDescriptor* self = _self;
767
+ rb_gc_mark(self->descriptor_pool);
648
768
  }
649
769
 
650
770
  void FieldDescriptor_free(void* _self) {
651
- FieldDescriptor* self = _self;
652
- upb_fielddef_unref(self->fielddef, &self->fielddef);
653
- xfree(self);
771
+ xfree(_self);
654
772
  }
655
773
 
656
774
  /*
@@ -663,9 +781,7 @@ void FieldDescriptor_free(void* _self) {
663
781
  VALUE FieldDescriptor_alloc(VALUE klass) {
664
782
  FieldDescriptor* self = ALLOC(FieldDescriptor);
665
783
  VALUE ret = TypedData_Wrap_Struct(klass, &_FieldDescriptor_type, self);
666
- upb_fielddef* fielddef = upb_fielddef_new(&self->fielddef);
667
- upb_fielddef_setpacked(fielddef, false);
668
- self->fielddef = fielddef;
784
+ self->fielddef = NULL;
669
785
  return ret;
670
786
  }
671
787
 
@@ -673,18 +789,13 @@ void FieldDescriptor_register(VALUE module) {
673
789
  VALUE klass = rb_define_class_under(
674
790
  module, "FieldDescriptor", rb_cObject);
675
791
  rb_define_alloc_func(klass, FieldDescriptor_alloc);
792
+ rb_define_method(klass, "initialize", FieldDescriptor_initialize, 3);
676
793
  rb_define_method(klass, "name", FieldDescriptor_name, 0);
677
- rb_define_method(klass, "name=", FieldDescriptor_name_set, 1);
678
794
  rb_define_method(klass, "type", FieldDescriptor_type, 0);
679
- rb_define_method(klass, "type=", FieldDescriptor_type_set, 1);
680
795
  rb_define_method(klass, "default", FieldDescriptor_default, 0);
681
- rb_define_method(klass, "default=", FieldDescriptor_default_set, 1);
682
796
  rb_define_method(klass, "label", FieldDescriptor_label, 0);
683
- rb_define_method(klass, "label=", FieldDescriptor_label_set, 1);
684
797
  rb_define_method(klass, "number", FieldDescriptor_number, 0);
685
- rb_define_method(klass, "number=", FieldDescriptor_number_set, 1);
686
798
  rb_define_method(klass, "submsg_name", FieldDescriptor_submsg_name, 0);
687
- rb_define_method(klass, "submsg_name=", FieldDescriptor_submsg_name_set, 1);
688
799
  rb_define_method(klass, "subtype", FieldDescriptor_subtype, 0);
689
800
  rb_define_method(klass, "has?", FieldDescriptor_has, 1);
690
801
  rb_define_method(klass, "clear", FieldDescriptor_clear, 1);
@@ -696,29 +807,34 @@ void FieldDescriptor_register(VALUE module) {
696
807
 
697
808
  /*
698
809
  * call-seq:
699
- * FieldDescriptor.name => name
810
+ * EnumDescriptor.new(c_only_cookie, pool, ptr) => EnumDescriptor
700
811
  *
701
- * Returns the name of this field.
812
+ * Creates a descriptor wrapper object. May only be called from C.
702
813
  */
703
- VALUE FieldDescriptor_name(VALUE _self) {
814
+ VALUE FieldDescriptor_initialize(VALUE _self, VALUE cookie,
815
+ VALUE descriptor_pool, VALUE ptr) {
704
816
  DEFINE_SELF(FieldDescriptor, self, _self);
705
- return rb_str_maybe_null(upb_fielddef_name(self->fielddef));
817
+
818
+ if (cookie != c_only_cookie) {
819
+ rb_raise(rb_eRuntimeError,
820
+ "Descriptor objects may not be created from Ruby.");
821
+ }
822
+
823
+ self->descriptor_pool = descriptor_pool;
824
+ self->fielddef = (const upb_fielddef*)NUM2ULL(ptr);
825
+
826
+ return Qnil;
706
827
  }
707
828
 
708
829
  /*
709
830
  * call-seq:
710
- * FieldDescriptor.name = name
831
+ * FieldDescriptor.name => name
711
832
  *
712
- * Sets the name of this field. Cannot be called once the containing message
713
- * type, if any, is added to a pool.
833
+ * Returns the name of this field.
714
834
  */
715
- VALUE FieldDescriptor_name_set(VALUE _self, VALUE str) {
835
+ VALUE FieldDescriptor_name(VALUE _self) {
716
836
  DEFINE_SELF(FieldDescriptor, self, _self);
717
- upb_fielddef* mut_def = check_field_notfrozen(self->fielddef);
718
- const char* name = get_str(str);
719
- CHECK_UPB(upb_fielddef_setname(mut_def, name, &status),
720
- "Error setting FieldDescriptor name");
721
- return Qnil;
837
+ return rb_str_maybe_null(upb_fielddef_name(self->fielddef));
722
838
  }
723
839
 
724
840
  upb_fieldtype_t ruby_to_fieldtype(VALUE type) {
@@ -831,6 +947,29 @@ VALUE descriptortype_to_ruby(upb_descriptortype_t type) {
831
947
  return Qnil;
832
948
  }
833
949
 
950
+ VALUE ruby_to_label(VALUE label) {
951
+ upb_label_t upb_label;
952
+ bool converted = false;
953
+
954
+ #define CONVERT(upb, ruby) \
955
+ if (SYM2ID(label) == rb_intern( # ruby )) { \
956
+ upb_label = UPB_LABEL_ ## upb; \
957
+ converted = true; \
958
+ }
959
+
960
+ CONVERT(OPTIONAL, optional);
961
+ CONVERT(REQUIRED, required);
962
+ CONVERT(REPEATED, repeated);
963
+
964
+ #undef CONVERT
965
+
966
+ if (!converted) {
967
+ rb_raise(rb_eArgError, "Unknown field label.");
968
+ }
969
+
970
+ return upb_label;
971
+ }
972
+
834
973
  /*
835
974
  * call-seq:
836
975
  * FieldDescriptor.type => type
@@ -843,26 +982,9 @@ VALUE descriptortype_to_ruby(upb_descriptortype_t type) {
843
982
  */
844
983
  VALUE FieldDescriptor_type(VALUE _self) {
845
984
  DEFINE_SELF(FieldDescriptor, self, _self);
846
- if (!upb_fielddef_typeisset(self->fielddef)) {
847
- return Qnil;
848
- }
849
985
  return descriptortype_to_ruby(upb_fielddef_descriptortype(self->fielddef));
850
986
  }
851
987
 
852
- /*
853
- * call-seq:
854
- * FieldDescriptor.type = type
855
- *
856
- * Sets this field's type. Cannot be called if field is part of a message type
857
- * already in a pool.
858
- */
859
- VALUE FieldDescriptor_type_set(VALUE _self, VALUE type) {
860
- DEFINE_SELF(FieldDescriptor, self, _self);
861
- upb_fielddef* mut_def = check_field_notfrozen(self->fielddef);
862
- upb_fielddef_setdescriptortype(mut_def, ruby_to_descriptortype(type));
863
- return Qnil;
864
- }
865
-
866
988
  /*
867
989
  * call-seq:
868
990
  * FieldDescriptor.default => default
@@ -874,60 +996,6 @@ VALUE FieldDescriptor_default(VALUE _self) {
874
996
  return layout_get_default(self->fielddef);
875
997
  }
876
998
 
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
-
931
999
  /*
932
1000
  * call-seq:
933
1001
  * FieldDescriptor.label => label
@@ -953,44 +1021,6 @@ VALUE FieldDescriptor_label(VALUE _self) {
953
1021
  return Qnil;
954
1022
  }
955
1023
 
956
- /*
957
- * call-seq:
958
- * FieldDescriptor.label = label
959
- *
960
- * Sets the label on this field. Cannot be called if field is part of a message
961
- * type already in a pool.
962
- */
963
- VALUE FieldDescriptor_label_set(VALUE _self, VALUE label) {
964
- DEFINE_SELF(FieldDescriptor, self, _self);
965
- upb_fielddef* mut_def = check_field_notfrozen(self->fielddef);
966
- upb_label_t upb_label = -1;
967
- bool converted = false;
968
-
969
- if (TYPE(label) != T_SYMBOL) {
970
- rb_raise(rb_eArgError, "Expected symbol for field label.");
971
- }
972
-
973
- #define CONVERT(upb, ruby) \
974
- if (SYM2ID(label) == rb_intern( # ruby )) { \
975
- upb_label = UPB_LABEL_ ## upb; \
976
- converted = true; \
977
- }
978
-
979
- CONVERT(OPTIONAL, optional);
980
- CONVERT(REQUIRED, required);
981
- CONVERT(REPEATED, repeated);
982
-
983
- #undef CONVERT
984
-
985
- if (!converted) {
986
- rb_raise(rb_eArgError, "Unknown field label.");
987
- }
988
-
989
- upb_fielddef_setlabel(mut_def, upb_label);
990
-
991
- return Qnil;
992
- }
993
-
994
1024
  /*
995
1025
  * call-seq:
996
1026
  * FieldDescriptor.number => number
@@ -1002,21 +1032,6 @@ VALUE FieldDescriptor_number(VALUE _self) {
1002
1032
  return INT2NUM(upb_fielddef_number(self->fielddef));
1003
1033
  }
1004
1034
 
1005
- /*
1006
- * call-seq:
1007
- * FieldDescriptor.number = number
1008
- *
1009
- * Sets the tag number for this field. Cannot be called if field is part of a
1010
- * message type already in a pool.
1011
- */
1012
- VALUE FieldDescriptor_number_set(VALUE _self, VALUE number) {
1013
- DEFINE_SELF(FieldDescriptor, self, _self);
1014
- upb_fielddef* mut_def = check_field_notfrozen(self->fielddef);
1015
- CHECK_UPB(upb_fielddef_setnumber(mut_def, NUM2INT(number), &status),
1016
- "Error setting field number");
1017
- return Qnil;
1018
- }
1019
-
1020
1035
  /*
1021
1036
  * call-seq:
1022
1037
  * FieldDescriptor.submsg_name => submsg_name
@@ -1028,32 +1043,16 @@ VALUE FieldDescriptor_number_set(VALUE _self, VALUE number) {
1028
1043
  */
1029
1044
  VALUE FieldDescriptor_submsg_name(VALUE _self) {
1030
1045
  DEFINE_SELF(FieldDescriptor, self, _self);
1031
- if (!upb_fielddef_hassubdef(self->fielddef)) {
1032
- return Qnil;
1033
- }
1034
- return rb_str_maybe_null(upb_fielddef_subdefname(self->fielddef));
1035
- }
1036
-
1037
- /*
1038
- * call-seq:
1039
- * FieldDescriptor.submsg_name = submsg_name
1040
- *
1041
- * Sets the name of the message or enum type corresponding to this field, if it
1042
- * is a message or enum field (respectively). This type name will be resolved
1043
- * within the context of the pool to which the containing message type is added.
1044
- * Cannot be called on field that are not of message or enum type, or on fields
1045
- * that are part of a message type already added to a pool.
1046
- */
1047
- VALUE FieldDescriptor_submsg_name_set(VALUE _self, VALUE value) {
1048
- DEFINE_SELF(FieldDescriptor, self, _self);
1049
- upb_fielddef* mut_def = check_field_notfrozen(self->fielddef);
1050
- const char* str = get_str(value);
1051
- if (!upb_fielddef_hassubdef(self->fielddef)) {
1052
- rb_raise(cTypeError, "FieldDescriptor does not have subdef.");
1046
+ switch (upb_fielddef_type(self->fielddef)) {
1047
+ case UPB_TYPE_ENUM:
1048
+ return rb_str_new2(
1049
+ upb_enumdef_fullname(upb_fielddef_enumsubdef(self->fielddef)));
1050
+ case UPB_TYPE_MESSAGE:
1051
+ return rb_str_new2(
1052
+ upb_msgdef_fullname(upb_fielddef_msgsubdef(self->fielddef)));
1053
+ default:
1054
+ return Qnil;
1053
1055
  }
1054
- CHECK_UPB(upb_fielddef_setsubdefname(mut_def, str, &status),
1055
- "Error setting submessage name");
1056
- return Qnil;
1057
1056
  }
1058
1057
 
1059
1058
  /*
@@ -1067,16 +1066,16 @@ VALUE FieldDescriptor_submsg_name_set(VALUE _self, VALUE value) {
1067
1066
  */
1068
1067
  VALUE FieldDescriptor_subtype(VALUE _self) {
1069
1068
  DEFINE_SELF(FieldDescriptor, self, _self);
1070
- const upb_def* def;
1071
-
1072
- if (!upb_fielddef_hassubdef(self->fielddef)) {
1073
- return Qnil;
1074
- }
1075
- def = upb_fielddef_subdef(self->fielddef);
1076
- if (def == NULL) {
1077
- return Qnil;
1069
+ switch (upb_fielddef_type(self->fielddef)) {
1070
+ case UPB_TYPE_ENUM:
1071
+ return get_enumdef_obj(self->descriptor_pool,
1072
+ upb_fielddef_enumsubdef(self->fielddef));
1073
+ case UPB_TYPE_MESSAGE:
1074
+ return get_msgdef_obj(self->descriptor_pool,
1075
+ upb_fielddef_msgsubdef(self->fielddef));
1076
+ default:
1077
+ return Qnil;
1078
1078
  }
1079
- return get_def_obj(def);
1080
1079
  }
1081
1080
 
1082
1081
  /*
@@ -1101,7 +1100,7 @@ VALUE FieldDescriptor_get(VALUE _self, VALUE msg_rb) {
1101
1100
  * FieldDescriptor.has?(message) => boolean
1102
1101
  *
1103
1102
  * Returns whether the value is set on the given message. Raises an
1104
- * exception when calling with proto syntax 3.
1103
+ * exception when calling for fields that do not have presence.
1105
1104
  */
1106
1105
  VALUE FieldDescriptor_has(VALUE _self, VALUE msg_rb) {
1107
1106
  DEFINE_SELF(FieldDescriptor, self, _self);
@@ -1160,12 +1159,12 @@ VALUE FieldDescriptor_set(VALUE _self, VALUE msg_rb, VALUE value) {
1160
1159
  DEFINE_CLASS(OneofDescriptor, "Google::Protobuf::OneofDescriptor");
1161
1160
 
1162
1161
  void OneofDescriptor_mark(void* _self) {
1162
+ OneofDescriptor* self = _self;
1163
+ rb_gc_mark(self->descriptor_pool);
1163
1164
  }
1164
1165
 
1165
1166
  void OneofDescriptor_free(void* _self) {
1166
- OneofDescriptor* self = _self;
1167
- upb_oneofdef_unref(self->oneofdef, &self->oneofdef);
1168
- xfree(self);
1167
+ xfree(_self);
1169
1168
  }
1170
1169
 
1171
1170
  /*
@@ -1178,7 +1177,8 @@ void OneofDescriptor_free(void* _self) {
1178
1177
  VALUE OneofDescriptor_alloc(VALUE klass) {
1179
1178
  OneofDescriptor* self = ALLOC(OneofDescriptor);
1180
1179
  VALUE ret = TypedData_Wrap_Struct(klass, &_OneofDescriptor_type, self);
1181
- self->oneofdef = upb_oneofdef_new(&self->oneofdef);
1180
+ self->oneofdef = NULL;
1181
+ self->descriptor_pool = Qnil;
1182
1182
  return ret;
1183
1183
  }
1184
1184
 
@@ -1186,9 +1186,8 @@ void OneofDescriptor_register(VALUE module) {
1186
1186
  VALUE klass = rb_define_class_under(
1187
1187
  module, "OneofDescriptor", rb_cObject);
1188
1188
  rb_define_alloc_func(klass, OneofDescriptor_alloc);
1189
+ rb_define_method(klass, "initialize", OneofDescriptor_initialize, 3);
1189
1190
  rb_define_method(klass, "name", OneofDescriptor_name, 0);
1190
- rb_define_method(klass, "name=", OneofDescriptor_name_set, 1);
1191
- rb_define_method(klass, "add_field", OneofDescriptor_add_field, 1);
1192
1191
  rb_define_method(klass, "each", OneofDescriptor_each, 0);
1193
1192
  rb_include_module(klass, rb_mEnumerable);
1194
1193
  rb_gc_register_address(&cOneofDescriptor);
@@ -1197,55 +1196,34 @@ void OneofDescriptor_register(VALUE module) {
1197
1196
 
1198
1197
  /*
1199
1198
  * call-seq:
1200
- * OneofDescriptor.name => name
1199
+ * OneofDescriptor.new(c_only_cookie, pool, ptr) => OneofDescriptor
1201
1200
  *
1202
- * Returns the name of this oneof.
1201
+ * Creates a descriptor wrapper object. May only be called from C.
1203
1202
  */
1204
- VALUE OneofDescriptor_name(VALUE _self) {
1203
+ VALUE OneofDescriptor_initialize(VALUE _self, VALUE cookie,
1204
+ VALUE descriptor_pool, VALUE ptr) {
1205
1205
  DEFINE_SELF(OneofDescriptor, self, _self);
1206
- return rb_str_maybe_null(upb_oneofdef_name(self->oneofdef));
1207
- }
1208
1206
 
1209
- /*
1210
- * call-seq:
1211
- * OneofDescriptor.name = name
1212
- *
1213
- * Sets a new name for this oneof. The oneof must not have been added to a
1214
- * message descriptor yet.
1215
- */
1216
- VALUE OneofDescriptor_name_set(VALUE _self, VALUE value) {
1217
- DEFINE_SELF(OneofDescriptor, self, _self);
1218
- upb_oneofdef* mut_def = check_oneof_notfrozen(self->oneofdef);
1219
- const char* str = get_str(value);
1220
- CHECK_UPB(upb_oneofdef_setname(mut_def, str, &status),
1221
- "Error setting oneof name");
1207
+ if (cookie != c_only_cookie) {
1208
+ rb_raise(rb_eRuntimeError,
1209
+ "Descriptor objects may not be created from Ruby.");
1210
+ }
1211
+
1212
+ self->descriptor_pool = descriptor_pool;
1213
+ self->oneofdef = (const upb_oneofdef*)NUM2ULL(ptr);
1214
+
1222
1215
  return Qnil;
1223
1216
  }
1224
1217
 
1225
1218
  /*
1226
1219
  * call-seq:
1227
- * OneofDescriptor.add_field(field) => nil
1228
- *
1229
- * Adds a field to this oneof. The field may have been added to this oneof in
1230
- * the past, or the message to which this oneof belongs (if any), but may not
1231
- * have already been added to any other oneof or message. Otherwise, an
1232
- * exception is raised.
1220
+ * OneofDescriptor.name => name
1233
1221
  *
1234
- * All fields added to the oneof via this method will be automatically added to
1235
- * the message to which this oneof belongs, if it belongs to one currently, or
1236
- * else will be added to any message to which the oneof is later added at the
1237
- * time that it is added.
1222
+ * Returns the name of this oneof.
1238
1223
  */
1239
- VALUE OneofDescriptor_add_field(VALUE _self, VALUE obj) {
1224
+ VALUE OneofDescriptor_name(VALUE _self) {
1240
1225
  DEFINE_SELF(OneofDescriptor, self, _self);
1241
- upb_oneofdef* mut_def = check_oneof_notfrozen(self->oneofdef);
1242
- FieldDescriptor* def = ruby_to_FieldDescriptor(obj);
1243
- upb_fielddef* mut_field_def = check_field_notfrozen(def->fielddef);
1244
- CHECK_UPB(
1245
- upb_oneofdef_addfield(mut_def, mut_field_def, NULL, &status),
1246
- "Adding field to OneofDescriptor failed");
1247
- add_def_obj(def->fielddef, obj);
1248
- return Qnil;
1226
+ return rb_str_maybe_null(upb_oneofdef_name(self->oneofdef));
1249
1227
  }
1250
1228
 
1251
1229
  /*
@@ -1254,14 +1232,14 @@ VALUE OneofDescriptor_add_field(VALUE _self, VALUE obj) {
1254
1232
  *
1255
1233
  * Iterates through fields in this oneof, yielding to the block on each one.
1256
1234
  */
1257
- VALUE OneofDescriptor_each(VALUE _self, VALUE field) {
1235
+ VALUE OneofDescriptor_each(VALUE _self) {
1258
1236
  DEFINE_SELF(OneofDescriptor, self, _self);
1259
1237
  upb_oneof_iter it;
1260
1238
  for (upb_oneof_begin(&it, self->oneofdef);
1261
1239
  !upb_oneof_done(&it);
1262
1240
  upb_oneof_next(&it)) {
1263
1241
  const upb_fielddef* f = upb_oneof_iter_field(&it);
1264
- VALUE obj = get_def_obj(f);
1242
+ VALUE obj = get_fielddef_obj(self->descriptor_pool, f);
1265
1243
  rb_yield(obj);
1266
1244
  }
1267
1245
  return Qnil;
@@ -1276,38 +1254,49 @@ DEFINE_CLASS(EnumDescriptor, "Google::Protobuf::EnumDescriptor");
1276
1254
  void EnumDescriptor_mark(void* _self) {
1277
1255
  EnumDescriptor* self = _self;
1278
1256
  rb_gc_mark(self->module);
1257
+ rb_gc_mark(self->descriptor_pool);
1279
1258
  }
1280
1259
 
1281
1260
  void EnumDescriptor_free(void* _self) {
1282
- EnumDescriptor* self = _self;
1283
- upb_enumdef_unref(self->enumdef, &self->enumdef);
1284
- xfree(self);
1261
+ xfree(_self);
1285
1262
  }
1286
1263
 
1287
- /*
1288
- * call-seq:
1289
- * EnumDescriptor.new => enum_descriptor
1290
- *
1291
- * Creates a new, empty, enum descriptor. Must be added to a pool before the
1292
- * enum type can be used. The enum type may only be modified prior to adding to
1293
- * a pool.
1294
- */
1295
1264
  VALUE EnumDescriptor_alloc(VALUE klass) {
1296
1265
  EnumDescriptor* self = ALLOC(EnumDescriptor);
1297
1266
  VALUE ret = TypedData_Wrap_Struct(klass, &_EnumDescriptor_type, self);
1298
- self->enumdef = upb_enumdef_new(&self->enumdef);
1267
+ self->enumdef = NULL;
1299
1268
  self->module = Qnil;
1269
+ self->descriptor_pool = Qnil;
1300
1270
  return ret;
1301
1271
  }
1302
1272
 
1273
+ /*
1274
+ * call-seq:
1275
+ * EnumDescriptor.new(c_only_cookie, ptr) => EnumDescriptor
1276
+ *
1277
+ * Creates a descriptor wrapper object. May only be called from C.
1278
+ */
1279
+ VALUE EnumDescriptor_initialize(VALUE _self, VALUE cookie,
1280
+ VALUE descriptor_pool, VALUE ptr) {
1281
+ DEFINE_SELF(EnumDescriptor, self, _self);
1282
+
1283
+ if (cookie != c_only_cookie) {
1284
+ rb_raise(rb_eRuntimeError,
1285
+ "Descriptor objects may not be created from Ruby.");
1286
+ }
1287
+
1288
+ self->descriptor_pool = descriptor_pool;
1289
+ self->enumdef = (const upb_enumdef*)NUM2ULL(ptr);
1290
+
1291
+ return Qnil;
1292
+ }
1293
+
1303
1294
  void EnumDescriptor_register(VALUE module) {
1304
1295
  VALUE klass = rb_define_class_under(
1305
1296
  module, "EnumDescriptor", rb_cObject);
1306
1297
  rb_define_alloc_func(klass, EnumDescriptor_alloc);
1307
- rb_define_method(klass, "initialize", EnumDescriptor_initialize, 1);
1298
+ rb_define_method(klass, "initialize", EnumDescriptor_initialize, 3);
1308
1299
  rb_define_method(klass, "name", EnumDescriptor_name, 0);
1309
- rb_define_method(klass, "name=", EnumDescriptor_name_set, 1);
1310
- rb_define_method(klass, "add_value", EnumDescriptor_add_value, 2);
1311
1300
  rb_define_method(klass, "lookup_name", EnumDescriptor_lookup_name, 1);
1312
1301
  rb_define_method(klass, "lookup_value", EnumDescriptor_lookup_value, 1);
1313
1302
  rb_define_method(klass, "each", EnumDescriptor_each, 0);
@@ -1320,31 +1309,14 @@ void EnumDescriptor_register(VALUE module) {
1320
1309
 
1321
1310
  /*
1322
1311
  * 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
1312
+ * EnumDescriptor.file_descriptor
1342
1313
  *
1343
1314
  * Returns the FileDescriptor object this enum belongs to.
1344
1315
  */
1345
1316
  VALUE EnumDescriptor_file_descriptor(VALUE _self) {
1346
1317
  DEFINE_SELF(EnumDescriptor, self, _self);
1347
- return get_def_obj(upb_def_file(self->enumdef));
1318
+ return get_filedef_obj(self->descriptor_pool,
1319
+ upb_enumdef_file(self->enumdef));
1348
1320
  }
1349
1321
 
1350
1322
  /*
@@ -1358,40 +1330,6 @@ VALUE EnumDescriptor_name(VALUE _self) {
1358
1330
  return rb_str_maybe_null(upb_enumdef_fullname(self->enumdef));
1359
1331
  }
1360
1332
 
1361
- /*
1362
- * call-seq:
1363
- * EnumDescriptor.name = name
1364
- *
1365
- * Sets the name of this enum type. Cannot be called if the enum type has
1366
- * already been added to a pool.
1367
- */
1368
- VALUE EnumDescriptor_name_set(VALUE _self, VALUE str) {
1369
- DEFINE_SELF(EnumDescriptor, self, _self);
1370
- upb_enumdef* mut_def = check_enum_notfrozen(self->enumdef);
1371
- const char* name = get_str(str);
1372
- CHECK_UPB(upb_enumdef_setfullname(mut_def, name, &status),
1373
- "Error setting EnumDescriptor name");
1374
- return Qnil;
1375
- }
1376
-
1377
- /*
1378
- * call-seq:
1379
- * EnumDescriptor.add_value(key, value)
1380
- *
1381
- * Adds a new key => value mapping to this enum type. Key must be given as a
1382
- * Ruby symbol. Cannot be called if the enum type has already been added to a
1383
- * pool. Will raise an exception if the key or value is already in use.
1384
- */
1385
- VALUE EnumDescriptor_add_value(VALUE _self, VALUE name, VALUE number) {
1386
- DEFINE_SELF(EnumDescriptor, self, _self);
1387
- upb_enumdef* mut_def = check_enum_notfrozen(self->enumdef);
1388
- const char* name_str = rb_id2name(SYM2ID(name));
1389
- int32_t val = NUM2INT(number);
1390
- CHECK_UPB(upb_enumdef_addval(mut_def, name_str, val, &status),
1391
- "Error adding value to enum");
1392
- return Qnil;
1393
- }
1394
-
1395
1333
  /*
1396
1334
  * call-seq:
1397
1335
  * EnumDescriptor.lookup_name(name) => value
@@ -1454,18 +1392,12 @@ VALUE EnumDescriptor_each(VALUE _self) {
1454
1392
  * call-seq:
1455
1393
  * EnumDescriptor.enummodule => module
1456
1394
  *
1457
- * Returns the Ruby module corresponding to this enum type. Cannot be called
1458
- * until the enum descriptor has been added to a pool.
1395
+ * Returns the Ruby module corresponding to this enum type.
1459
1396
  */
1460
1397
  VALUE EnumDescriptor_enummodule(VALUE _self) {
1461
1398
  DEFINE_SELF(EnumDescriptor, self, _self);
1462
- if (!upb_def_isfrozen((const upb_def*)self->enumdef)) {
1463
- rb_raise(rb_eRuntimeError,
1464
- "Cannot fetch enum module from an EnumDescriptor not yet "
1465
- "in a pool.");
1466
- }
1467
1399
  if (self->module == Qnil) {
1468
- self->module = build_module_from_enumdesc(self);
1400
+ self->module = build_module_from_enumdesc(_self);
1469
1401
  }
1470
1402
  return self->module;
1471
1403
  }
@@ -1479,8 +1411,7 @@ DEFINE_CLASS(MessageBuilderContext,
1479
1411
 
1480
1412
  void MessageBuilderContext_mark(void* _self) {
1481
1413
  MessageBuilderContext* self = _self;
1482
- rb_gc_mark(self->descriptor);
1483
- rb_gc_mark(self->builder);
1414
+ rb_gc_mark(self->file_builder);
1484
1415
  }
1485
1416
 
1486
1417
  void MessageBuilderContext_free(void* _self) {
@@ -1492,8 +1423,7 @@ VALUE MessageBuilderContext_alloc(VALUE klass) {
1492
1423
  MessageBuilderContext* self = ALLOC(MessageBuilderContext);
1493
1424
  VALUE ret = TypedData_Wrap_Struct(
1494
1425
  klass, &_MessageBuilderContext_type, self);
1495
- self->descriptor = Qnil;
1496
- self->builder = Qnil;
1426
+ self->file_builder = Qnil;
1497
1427
  return ret;
1498
1428
  }
1499
1429
 
@@ -1504,6 +1434,7 @@ void MessageBuilderContext_register(VALUE module) {
1504
1434
  rb_define_method(klass, "initialize",
1505
1435
  MessageBuilderContext_initialize, 2);
1506
1436
  rb_define_method(klass, "optional", MessageBuilderContext_optional, -1);
1437
+ rb_define_method(klass, "proto3_optional", MessageBuilderContext_proto3_optional, -1);
1507
1438
  rb_define_method(klass, "required", MessageBuilderContext_required, -1);
1508
1439
  rb_define_method(klass, "repeated", MessageBuilderContext_repeated, -1);
1509
1440
  rb_define_method(klass, "map", MessageBuilderContext_map, -1);
@@ -1514,65 +1445,115 @@ void MessageBuilderContext_register(VALUE module) {
1514
1445
 
1515
1446
  /*
1516
1447
  * call-seq:
1517
- * MessageBuilderContext.new(desc, builder) => context
1448
+ * MessageBuilderContext.new(file_builder, name) => context
1518
1449
  *
1519
1450
  * Create a new message builder context around the given message descriptor and
1520
1451
  * builder context. This class is intended to serve as a DSL context to be used
1521
1452
  * with #instance_eval.
1522
1453
  */
1523
1454
  VALUE MessageBuilderContext_initialize(VALUE _self,
1524
- VALUE msgdef,
1525
- VALUE builder) {
1455
+ VALUE _file_builder,
1456
+ VALUE name) {
1526
1457
  DEFINE_SELF(MessageBuilderContext, self, _self);
1527
- self->descriptor = msgdef;
1528
- self->builder = builder;
1458
+ FileBuilderContext* file_builder = ruby_to_FileBuilderContext(_file_builder);
1459
+ google_protobuf_FileDescriptorProto* file_proto = file_builder->file_proto;
1460
+
1461
+ self->file_builder = _file_builder;
1462
+ self->msg_proto = google_protobuf_FileDescriptorProto_add_message_type(
1463
+ file_proto, file_builder->arena);
1464
+
1465
+ google_protobuf_DescriptorProto_set_name(
1466
+ self->msg_proto, FileBuilderContext_strdup(_file_builder, name));
1467
+
1529
1468
  return Qnil;
1530
1469
  }
1531
1470
 
1532
- static VALUE msgdef_add_field(VALUE msgdef_rb,
1533
- const char* label, VALUE name,
1534
- VALUE type, VALUE number,
1535
- VALUE type_class,
1536
- VALUE options) {
1537
- VALUE fielddef_rb = rb_class_new_instance(0, NULL, cFieldDescriptor);
1538
- VALUE name_str = rb_str_new2(rb_id2name(SYM2ID(name)));
1471
+ static void msgdef_add_field(VALUE msgbuilder_rb, upb_label_t label, VALUE name,
1472
+ VALUE type, VALUE number, VALUE type_class,
1473
+ VALUE options, int oneof_index,
1474
+ bool proto3_optional) {
1475
+ DEFINE_SELF(MessageBuilderContext, self, msgbuilder_rb);
1476
+ FileBuilderContext* file_context =
1477
+ ruby_to_FileBuilderContext(self->file_builder);
1478
+ google_protobuf_FieldDescriptorProto* field_proto;
1479
+ VALUE name_str;
1480
+
1481
+ field_proto = google_protobuf_DescriptorProto_add_field(self->msg_proto,
1482
+ file_context->arena);
1539
1483
 
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);
1484
+ Check_Type(name, T_SYMBOL);
1485
+ name_str = rb_id2str(SYM2ID(name));
1486
+
1487
+ google_protobuf_FieldDescriptorProto_set_name(
1488
+ field_proto, FileBuilderContext_strdup(self->file_builder, name_str));
1489
+ google_protobuf_FieldDescriptorProto_set_number(field_proto, NUM2INT(number));
1490
+ google_protobuf_FieldDescriptorProto_set_label(field_proto, (int)label);
1491
+ google_protobuf_FieldDescriptorProto_set_type(
1492
+ field_proto, (int)ruby_to_descriptortype(type));
1493
+
1494
+ if (proto3_optional) {
1495
+ google_protobuf_FieldDescriptorProto_set_proto3_optional(field_proto, true);
1496
+ }
1544
1497
 
1545
1498
  if (type_class != Qnil) {
1546
1499
  Check_Type(type_class, T_STRING);
1547
1500
 
1548
1501
  // Make it an absolute type name by prepending a dot.
1549
1502
  type_class = rb_str_append(rb_str_new2("."), type_class);
1550
- rb_funcall(fielddef_rb, rb_intern("submsg_name="), 1, type_class);
1503
+ google_protobuf_FieldDescriptorProto_set_type_name(
1504
+ field_proto, FileBuilderContext_strdup(self->file_builder, type_class));
1551
1505
  }
1552
1506
 
1553
1507
  if (options != Qnil) {
1554
1508
  Check_Type(options, T_HASH);
1555
1509
 
1556
1510
  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
- }
1511
+ ID2SYM(rb_intern("default"))) == Qtrue) {
1512
+ VALUE default_value =
1513
+ rb_hash_lookup(options, ID2SYM(rb_intern("default")));
1562
1514
 
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
- }
1515
+ /* Call #to_s since all defaults are strings in the descriptor. */
1516
+ default_value = rb_funcall(default_value, rb_intern("to_s"), 0);
1568
1517
 
1569
- rb_funcall(fielddef_rb, rb_intern("default="), 1,
1570
- rb_hash_lookup(options, ID2SYM(rb_intern("default"))));
1518
+ google_protobuf_FieldDescriptorProto_set_default_value(
1519
+ field_proto,
1520
+ FileBuilderContext_strdup(self->file_builder, default_value));
1571
1521
  }
1572
1522
  }
1573
1523
 
1574
- rb_funcall(msgdef_rb, rb_intern("add_field"), 1, fielddef_rb);
1575
- return fielddef_rb;
1524
+ if (oneof_index >= 0) {
1525
+ google_protobuf_FieldDescriptorProto_set_oneof_index(field_proto,
1526
+ oneof_index);
1527
+ }
1528
+ }
1529
+
1530
+ static VALUE make_mapentry(VALUE _message_builder, VALUE types, int argc,
1531
+ VALUE* argv) {
1532
+ DEFINE_SELF(MessageBuilderContext, message_builder, _message_builder);
1533
+ VALUE type_class = rb_ary_entry(types, 2);
1534
+ FileBuilderContext* file_context =
1535
+ ruby_to_FileBuilderContext(message_builder->file_builder);
1536
+ google_protobuf_MessageOptions* options =
1537
+ google_protobuf_DescriptorProto_mutable_options(
1538
+ message_builder->msg_proto, file_context->arena);
1539
+
1540
+ google_protobuf_MessageOptions_set_map_entry(options, true);
1541
+
1542
+ // optional <type> key = 1;
1543
+ rb_funcall(_message_builder, rb_intern("optional"), 3,
1544
+ ID2SYM(rb_intern("key")), rb_ary_entry(types, 0), INT2NUM(1));
1545
+
1546
+ // optional <type> value = 2;
1547
+ if (type_class == Qnil) {
1548
+ rb_funcall(_message_builder, rb_intern("optional"), 3,
1549
+ ID2SYM(rb_intern("value")), rb_ary_entry(types, 1), INT2NUM(2));
1550
+ } else {
1551
+ rb_funcall(_message_builder, rb_intern("optional"), 4,
1552
+ ID2SYM(rb_intern("value")), rb_ary_entry(types, 1), INT2NUM(2),
1553
+ type_class);
1554
+ }
1555
+
1556
+ return Qnil;
1576
1557
  }
1577
1558
 
1578
1559
  /*
@@ -1586,7 +1567,6 @@ static VALUE msgdef_add_field(VALUE msgdef_rb,
1586
1567
  * string, if present (as accepted by FieldDescriptor#submsg_name=).
1587
1568
  */
1588
1569
  VALUE MessageBuilderContext_optional(int argc, VALUE* argv, VALUE _self) {
1589
- DEFINE_SELF(MessageBuilderContext, self, _self);
1590
1570
  VALUE name, type, number;
1591
1571
  VALUE type_class, options = Qnil;
1592
1572
 
@@ -1599,8 +1579,41 @@ VALUE MessageBuilderContext_optional(int argc, VALUE* argv, VALUE _self) {
1599
1579
  type_class = Qnil;
1600
1580
  }
1601
1581
 
1602
- return msgdef_add_field(self->descriptor, "optional",
1603
- name, type, number, type_class, options);
1582
+ msgdef_add_field(_self, UPB_LABEL_OPTIONAL, name, type, number, type_class,
1583
+ options, -1, false);
1584
+
1585
+ return Qnil;
1586
+ }
1587
+
1588
+ /*
1589
+ * call-seq:
1590
+ * MessageBuilderContext.proto3_optional(name, type, number,
1591
+ * type_class = nil, options = nil)
1592
+ *
1593
+ * Defines a true proto3 optional field (that tracks presence) on this message
1594
+ * type with the given type, tag number, and type class (for message and enum
1595
+ * fields). The type must be a Ruby symbol (as accepted by
1596
+ * FieldDescriptor#type=) and the type_class must be a string, if present (as
1597
+ * accepted by FieldDescriptor#submsg_name=).
1598
+ */
1599
+ VALUE MessageBuilderContext_proto3_optional(int argc, VALUE* argv,
1600
+ VALUE _self) {
1601
+ VALUE name, type, number;
1602
+ VALUE type_class, options = Qnil;
1603
+
1604
+ rb_scan_args(argc, argv, "32", &name, &type, &number, &type_class, &options);
1605
+
1606
+ // Allow passing (name, type, number, options) or
1607
+ // (name, type, number, type_class, options)
1608
+ if (argc == 4 && RB_TYPE_P(type_class, T_HASH)) {
1609
+ options = type_class;
1610
+ type_class = Qnil;
1611
+ }
1612
+
1613
+ msgdef_add_field(_self, UPB_LABEL_OPTIONAL, name, type, number, type_class,
1614
+ options, -1, true);
1615
+
1616
+ return Qnil;
1604
1617
  }
1605
1618
 
1606
1619
  /*
@@ -1618,7 +1631,6 @@ VALUE MessageBuilderContext_optional(int argc, VALUE* argv, VALUE _self) {
1618
1631
  * pool will currently result in an error.
1619
1632
  */
1620
1633
  VALUE MessageBuilderContext_required(int argc, VALUE* argv, VALUE _self) {
1621
- DEFINE_SELF(MessageBuilderContext, self, _self);
1622
1634
  VALUE name, type, number;
1623
1635
  VALUE type_class, options = Qnil;
1624
1636
 
@@ -1631,8 +1643,10 @@ VALUE MessageBuilderContext_required(int argc, VALUE* argv, VALUE _self) {
1631
1643
  type_class = Qnil;
1632
1644
  }
1633
1645
 
1634
- return msgdef_add_field(self->descriptor, "required",
1635
- name, type, number, type_class, options);
1646
+ msgdef_add_field(_self, UPB_LABEL_REQUIRED, name, type, number, type_class,
1647
+ options, -1, false);
1648
+
1649
+ return Qnil;
1636
1650
  }
1637
1651
 
1638
1652
  /*
@@ -1645,7 +1659,6 @@ VALUE MessageBuilderContext_required(int argc, VALUE* argv, VALUE _self) {
1645
1659
  * string, if present (as accepted by FieldDescriptor#submsg_name=).
1646
1660
  */
1647
1661
  VALUE MessageBuilderContext_repeated(int argc, VALUE* argv, VALUE _self) {
1648
- DEFINE_SELF(MessageBuilderContext, self, _self);
1649
1662
  VALUE name, type, number, type_class;
1650
1663
 
1651
1664
  if (argc < 3) {
@@ -1656,8 +1669,10 @@ VALUE MessageBuilderContext_repeated(int argc, VALUE* argv, VALUE _self) {
1656
1669
  number = argv[2];
1657
1670
  type_class = (argc > 3) ? argv[3] : Qnil;
1658
1671
 
1659
- return msgdef_add_field(self->descriptor, "repeated",
1660
- name, type, number, type_class, Qnil);
1672
+ msgdef_add_field(_self, UPB_LABEL_REPEATED, name, type, number, type_class,
1673
+ Qnil, -1, false);
1674
+
1675
+ return Qnil;
1661
1676
  }
1662
1677
 
1663
1678
  /*
@@ -1675,7 +1690,9 @@ VALUE MessageBuilderContext_repeated(int argc, VALUE* argv, VALUE _self) {
1675
1690
  VALUE MessageBuilderContext_map(int argc, VALUE* argv, VALUE _self) {
1676
1691
  DEFINE_SELF(MessageBuilderContext, self, _self);
1677
1692
  VALUE name, key_type, value_type, number, type_class;
1678
- VALUE mapentry_desc, mapentry_desc_name;
1693
+ VALUE mapentry_desc_name;
1694
+ FileBuilderContext* file_builder;
1695
+ upb_strview msg_name;
1679
1696
 
1680
1697
  if (argc < 4) {
1681
1698
  rb_raise(rb_eArgError, "Expected at least 4 arguments.");
@@ -1698,77 +1715,44 @@ VALUE MessageBuilderContext_map(int argc, VALUE* argv, VALUE _self) {
1698
1715
  "type.");
1699
1716
  }
1700
1717
 
1701
- Descriptor* descriptor = ruby_to_Descriptor(self->descriptor);
1702
- if (upb_msgdef_syntax(descriptor->msgdef) == UPB_SYNTAX_PROTO2) {
1718
+ file_builder = ruby_to_FileBuilderContext(self->file_builder);
1719
+
1720
+ // TODO(haberman): remove this restriction, maps are supported in proto2.
1721
+ if (upb_strview_eql(
1722
+ google_protobuf_FileDescriptorProto_syntax(file_builder->file_proto),
1723
+ upb_strview_makez("proto2"))) {
1703
1724
  rb_raise(rb_eArgError,
1704
- "Cannot add a native map field using proto2 syntax.");
1725
+ "Cannot add a native map field using proto2 syntax.");
1705
1726
  }
1706
1727
 
1707
1728
  // Create a new message descriptor for the map entry message, and create a
1708
1729
  // repeated submessage field here with that type.
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);
1712
- mapentry_desc_name = rb_funcall(self->descriptor, rb_intern("name"), 0);
1730
+ msg_name = google_protobuf_DescriptorProto_name(self->msg_proto);
1731
+ mapentry_desc_name = rb_str_new(msg_name.data, msg_name.size);
1713
1732
  mapentry_desc_name = rb_str_cat2(mapentry_desc_name, "_MapEntry_");
1714
- mapentry_desc_name = rb_str_cat2(mapentry_desc_name,
1715
- rb_id2name(SYM2ID(name)));
1716
- Descriptor_name_set(mapentry_desc, mapentry_desc_name);
1717
-
1718
- {
1719
- // The 'mapentry' attribute has no Ruby setter because we do not want the
1720
- // user attempting to DIY the setup below; we want to ensure that the fields
1721
- // are correct. So we reach into the msgdef here to set the bit manually.
1722
- Descriptor* mapentry_desc_self = ruby_to_Descriptor(mapentry_desc);
1723
- upb_msgdef_setmapentry((upb_msgdef*)mapentry_desc_self->msgdef, true);
1724
- }
1733
+ mapentry_desc_name =
1734
+ rb_str_cat2(mapentry_desc_name, rb_id2name(SYM2ID(name)));
1725
1735
 
1726
1736
  {
1727
- // optional <type> key = 1;
1728
- VALUE key_field = rb_class_new_instance(0, NULL, cFieldDescriptor);
1729
- FieldDescriptor_name_set(key_field, rb_str_new2("key"));
1730
- FieldDescriptor_label_set(key_field, ID2SYM(rb_intern("optional")));
1731
- FieldDescriptor_number_set(key_field, INT2NUM(1));
1732
- FieldDescriptor_type_set(key_field, key_type);
1733
- Descriptor_add_field(mapentry_desc, key_field);
1734
- }
1735
-
1736
- {
1737
- // optional <type> value = 2;
1738
- VALUE value_field = rb_class_new_instance(0, NULL, cFieldDescriptor);
1739
- FieldDescriptor_name_set(value_field, rb_str_new2("value"));
1740
- FieldDescriptor_label_set(value_field, ID2SYM(rb_intern("optional")));
1741
- FieldDescriptor_number_set(value_field, INT2NUM(2));
1742
- FieldDescriptor_type_set(value_field, value_type);
1743
- if (type_class != Qnil) {
1744
- VALUE submsg_name = rb_str_new2("."); // prepend '.' to make absolute.
1745
- submsg_name = rb_str_append(submsg_name, type_class);
1746
- FieldDescriptor_submsg_name_set(value_field, submsg_name);
1747
- }
1748
- Descriptor_add_field(mapentry_desc, value_field);
1737
+ // message <msgname>_MapEntry_ { /* ... */ }
1738
+ VALUE args[1] = {mapentry_desc_name};
1739
+ VALUE types = rb_ary_new3(3, key_type, value_type, type_class);
1740
+ rb_block_call(self->file_builder, rb_intern("add_message"), 1, args,
1741
+ make_mapentry, types);
1749
1742
  }
1750
1743
 
1751
- {
1752
- // Add the map-entry message type to the current builder, and use the type
1753
- // to create the map field itself.
1754
- Builder* builder = ruby_to_Builder(self->builder);
1755
- rb_ary_push(builder->pending_list, mapentry_desc);
1744
+ // If this file is in a package, we need to qualify the map entry type.
1745
+ if (google_protobuf_FileDescriptorProto_has_package(file_builder->file_proto)) {
1746
+ upb_strview package_view =
1747
+ google_protobuf_FileDescriptorProto_package(file_builder->file_proto);
1748
+ VALUE package = rb_str_new(package_view.data, package_view.size);
1749
+ package = rb_str_cat2(package, ".");
1750
+ mapentry_desc_name = rb_str_concat(package, mapentry_desc_name);
1756
1751
  }
1757
1752
 
1758
- {
1759
- VALUE map_field = rb_class_new_instance(0, NULL, cFieldDescriptor);
1760
- VALUE name_str = rb_str_new2(rb_id2name(SYM2ID(name)));
1761
- VALUE submsg_name;
1762
-
1763
- FieldDescriptor_name_set(map_field, name_str);
1764
- FieldDescriptor_number_set(map_field, number);
1765
- FieldDescriptor_label_set(map_field, ID2SYM(rb_intern("repeated")));
1766
- FieldDescriptor_type_set(map_field, ID2SYM(rb_intern("message")));
1767
- submsg_name = rb_str_new2("."); // prepend '.' to make name absolute.
1768
- submsg_name = rb_str_append(submsg_name, mapentry_desc_name);
1769
- FieldDescriptor_submsg_name_set(map_field, submsg_name);
1770
- Descriptor_add_field(self->descriptor, map_field);
1771
- }
1753
+ // repeated MapEntry <name> = <number>;
1754
+ rb_funcall(_self, rb_intern("repeated"), 4, name,
1755
+ ID2SYM(rb_intern("message")), number, mapentry_desc_name);
1772
1756
 
1773
1757
  return Qnil;
1774
1758
  }
@@ -1786,18 +1770,81 @@ VALUE MessageBuilderContext_map(int argc, VALUE* argv, VALUE _self) {
1786
1770
  */
1787
1771
  VALUE MessageBuilderContext_oneof(VALUE _self, VALUE name) {
1788
1772
  DEFINE_SELF(MessageBuilderContext, self, _self);
1789
- VALUE oneofdef = rb_class_new_instance(0, NULL, cOneofDescriptor);
1790
- VALUE args[2] = { oneofdef, self->builder };
1791
- VALUE ctx = rb_class_new_instance(2, args, cOneofBuilderContext);
1792
- VALUE block = rb_block_proc();
1793
- VALUE name_str = rb_str_new2(rb_id2name(SYM2ID(name)));
1794
- rb_funcall(oneofdef, rb_intern("name="), 1, name_str);
1795
- rb_funcall_with_block(ctx, rb_intern("instance_eval"), 0, NULL, block);
1796
- Descriptor_add_oneof(self->descriptor, oneofdef);
1773
+ size_t oneof_count;
1774
+ FileBuilderContext* file_context =
1775
+ ruby_to_FileBuilderContext(self->file_builder);
1776
+ google_protobuf_OneofDescriptorProto* oneof_proto;
1777
+
1778
+ // Existing oneof_count becomes oneof_index.
1779
+ google_protobuf_DescriptorProto_oneof_decl(self->msg_proto, &oneof_count);
1780
+
1781
+ // Create oneof_proto and set its name.
1782
+ oneof_proto = google_protobuf_DescriptorProto_add_oneof_decl(
1783
+ self->msg_proto, file_context->arena);
1784
+ google_protobuf_OneofDescriptorProto_set_name(
1785
+ oneof_proto, FileBuilderContext_strdup_sym(self->file_builder, name));
1786
+
1787
+ // Evaluate the block with the builder as argument.
1788
+ {
1789
+ VALUE args[2] = { INT2NUM(oneof_count), _self };
1790
+ VALUE ctx = rb_class_new_instance(2, args, cOneofBuilderContext);
1791
+ VALUE block = rb_block_proc();
1792
+ rb_funcall_with_block(ctx, rb_intern("instance_eval"), 0, NULL, block);
1793
+ }
1797
1794
 
1798
1795
  return Qnil;
1799
1796
  }
1800
1797
 
1798
+ void MessageBuilderContext_add_synthetic_oneofs(VALUE _self) {
1799
+ DEFINE_SELF(MessageBuilderContext, self, _self);
1800
+ FileBuilderContext* file_context =
1801
+ ruby_to_FileBuilderContext(self->file_builder);
1802
+ size_t field_count, oneof_count;
1803
+ google_protobuf_FieldDescriptorProto** fields =
1804
+ google_protobuf_DescriptorProto_mutable_field(self->msg_proto, &field_count);
1805
+ const google_protobuf_OneofDescriptorProto*const* oneofs =
1806
+ google_protobuf_DescriptorProto_oneof_decl(self->msg_proto, &oneof_count);
1807
+ VALUE names = rb_hash_new();
1808
+ VALUE underscore = rb_str_new2("_");
1809
+ size_t i;
1810
+
1811
+ // We have to build a set of all names, to ensure that synthetic oneofs are
1812
+ // not creating conflicts.
1813
+ for (i = 0; i < field_count; i++) {
1814
+ upb_strview name = google_protobuf_FieldDescriptorProto_name(fields[i]);
1815
+ rb_hash_aset(names, rb_str_new(name.data, name.size), Qtrue);
1816
+ }
1817
+ for (i = 0; i < oneof_count; i++) {
1818
+ upb_strview name = google_protobuf_OneofDescriptorProto_name(oneofs[i]);
1819
+ rb_hash_aset(names, rb_str_new(name.data, name.size), Qtrue);
1820
+ }
1821
+
1822
+ for (i = 0; i < field_count; i++) {
1823
+ google_protobuf_OneofDescriptorProto* oneof_proto;
1824
+ VALUE oneof_name;
1825
+ upb_strview field_name;
1826
+
1827
+ if (!google_protobuf_FieldDescriptorProto_proto3_optional(fields[i])) {
1828
+ continue;
1829
+ }
1830
+
1831
+ // Prepend '_' until we are no longer conflicting.
1832
+ field_name = google_protobuf_FieldDescriptorProto_name(fields[i]);
1833
+ oneof_name = rb_str_new(field_name.data, field_name.size);
1834
+ while (rb_hash_lookup(names, oneof_name) != Qnil) {
1835
+ oneof_name = rb_str_plus(underscore, oneof_name);
1836
+ }
1837
+
1838
+ rb_hash_aset(names, oneof_name, Qtrue);
1839
+ google_protobuf_FieldDescriptorProto_set_oneof_index(fields[i],
1840
+ oneof_count++);
1841
+ oneof_proto = google_protobuf_DescriptorProto_add_oneof_decl(
1842
+ self->msg_proto, file_context->arena);
1843
+ google_protobuf_OneofDescriptorProto_set_name(
1844
+ oneof_proto, FileBuilderContext_strdup(self->file_builder, oneof_name));
1845
+ }
1846
+ }
1847
+
1801
1848
  // -----------------------------------------------------------------------------
1802
1849
  // OneofBuilderContext.
1803
1850
  // -----------------------------------------------------------------------------
@@ -1807,21 +1854,19 @@ DEFINE_CLASS(OneofBuilderContext,
1807
1854
 
1808
1855
  void OneofBuilderContext_mark(void* _self) {
1809
1856
  OneofBuilderContext* self = _self;
1810
- rb_gc_mark(self->descriptor);
1811
- rb_gc_mark(self->builder);
1857
+ rb_gc_mark(self->message_builder);
1812
1858
  }
1813
1859
 
1814
1860
  void OneofBuilderContext_free(void* _self) {
1815
- OneofBuilderContext* self = _self;
1816
- xfree(self);
1861
+ xfree(_self);
1817
1862
  }
1818
1863
 
1819
1864
  VALUE OneofBuilderContext_alloc(VALUE klass) {
1820
1865
  OneofBuilderContext* self = ALLOC(OneofBuilderContext);
1821
1866
  VALUE ret = TypedData_Wrap_Struct(
1822
1867
  klass, &_OneofBuilderContext_type, self);
1823
- self->descriptor = Qnil;
1824
- self->builder = Qnil;
1868
+ self->oneof_index = 0;
1869
+ self->message_builder = Qnil;
1825
1870
  return ret;
1826
1871
  }
1827
1872
 
@@ -1838,18 +1883,18 @@ void OneofBuilderContext_register(VALUE module) {
1838
1883
 
1839
1884
  /*
1840
1885
  * call-seq:
1841
- * OneofBuilderContext.new(desc, builder) => context
1886
+ * OneofBuilderContext.new(oneof_index, message_builder) => context
1842
1887
  *
1843
1888
  * Create a new oneof builder context around the given oneof descriptor and
1844
1889
  * builder context. This class is intended to serve as a DSL context to be used
1845
1890
  * with #instance_eval.
1846
1891
  */
1847
1892
  VALUE OneofBuilderContext_initialize(VALUE _self,
1848
- VALUE oneofdef,
1849
- VALUE builder) {
1893
+ VALUE oneof_index,
1894
+ VALUE message_builder) {
1850
1895
  DEFINE_SELF(OneofBuilderContext, self, _self);
1851
- self->descriptor = oneofdef;
1852
- self->builder = builder;
1896
+ self->oneof_index = NUM2INT(oneof_index);
1897
+ self->message_builder = message_builder;
1853
1898
  return Qnil;
1854
1899
  }
1855
1900
 
@@ -1870,8 +1915,10 @@ VALUE OneofBuilderContext_optional(int argc, VALUE* argv, VALUE _self) {
1870
1915
 
1871
1916
  rb_scan_args(argc, argv, "32", &name, &type, &number, &type_class, &options);
1872
1917
 
1873
- return msgdef_add_field(self->descriptor, "optional",
1874
- name, type, number, type_class, options);
1918
+ msgdef_add_field(self->message_builder, UPB_LABEL_OPTIONAL, name, type,
1919
+ number, type_class, options, self->oneof_index, false);
1920
+
1921
+ return Qnil;
1875
1922
  }
1876
1923
 
1877
1924
  // -----------------------------------------------------------------------------
@@ -1883,19 +1930,19 @@ DEFINE_CLASS(EnumBuilderContext,
1883
1930
 
1884
1931
  void EnumBuilderContext_mark(void* _self) {
1885
1932
  EnumBuilderContext* self = _self;
1886
- rb_gc_mark(self->enumdesc);
1933
+ rb_gc_mark(self->file_builder);
1887
1934
  }
1888
1935
 
1889
1936
  void EnumBuilderContext_free(void* _self) {
1890
- EnumBuilderContext* self = _self;
1891
- xfree(self);
1937
+ xfree(_self);
1892
1938
  }
1893
1939
 
1894
1940
  VALUE EnumBuilderContext_alloc(VALUE klass) {
1895
1941
  EnumBuilderContext* self = ALLOC(EnumBuilderContext);
1896
1942
  VALUE ret = TypedData_Wrap_Struct(
1897
1943
  klass, &_EnumBuilderContext_type, self);
1898
- self->enumdesc = Qnil;
1944
+ self->enum_proto = NULL;
1945
+ self->file_builder = Qnil;
1899
1946
  return ret;
1900
1947
  }
1901
1948
 
@@ -1903,8 +1950,7 @@ void EnumBuilderContext_register(VALUE module) {
1903
1950
  VALUE klass = rb_define_class_under(
1904
1951
  module, "EnumBuilderContext", rb_cObject);
1905
1952
  rb_define_alloc_func(klass, EnumBuilderContext_alloc);
1906
- rb_define_method(klass, "initialize",
1907
- EnumBuilderContext_initialize, 1);
1953
+ rb_define_method(klass, "initialize", EnumBuilderContext_initialize, 2);
1908
1954
  rb_define_method(klass, "value", EnumBuilderContext_value, 2);
1909
1955
  rb_gc_register_address(&cEnumBuilderContext);
1910
1956
  cEnumBuilderContext = klass;
@@ -1912,20 +1958,24 @@ void EnumBuilderContext_register(VALUE module) {
1912
1958
 
1913
1959
  /*
1914
1960
  * call-seq:
1915
- * EnumBuilderContext.new(enumdesc) => context
1961
+ * EnumBuilderContext.new(file_builder) => context
1916
1962
  *
1917
1963
  * Create a new builder context around the given enum descriptor. This class is
1918
1964
  * intended to serve as a DSL context to be used with #instance_eval.
1919
1965
  */
1920
- VALUE EnumBuilderContext_initialize(VALUE _self, VALUE enumdef) {
1966
+ VALUE EnumBuilderContext_initialize(VALUE _self, VALUE _file_builder,
1967
+ VALUE name) {
1921
1968
  DEFINE_SELF(EnumBuilderContext, self, _self);
1922
- self->enumdesc = enumdef;
1923
- return Qnil;
1924
- }
1969
+ FileBuilderContext* file_builder = ruby_to_FileBuilderContext(_file_builder);
1970
+ google_protobuf_FileDescriptorProto* file_proto = file_builder->file_proto;
1971
+
1972
+ self->file_builder = _file_builder;
1973
+ self->enum_proto = google_protobuf_FileDescriptorProto_add_enum_type(
1974
+ file_proto, file_builder->arena);
1975
+
1976
+ google_protobuf_EnumDescriptorProto_set_name(
1977
+ self->enum_proto, FileBuilderContext_strdup(_file_builder, name));
1925
1978
 
1926
- static VALUE enumdef_add_value(VALUE enumdef,
1927
- VALUE name, VALUE number) {
1928
- rb_funcall(enumdef, rb_intern("add_value"), 2, name, number);
1929
1979
  return Qnil;
1930
1980
  }
1931
1981
 
@@ -1938,7 +1988,19 @@ static VALUE enumdef_add_value(VALUE enumdef,
1938
1988
  */
1939
1989
  VALUE EnumBuilderContext_value(VALUE _self, VALUE name, VALUE number) {
1940
1990
  DEFINE_SELF(EnumBuilderContext, self, _self);
1941
- return enumdef_add_value(self->enumdesc, name, number);
1991
+ FileBuilderContext* file_builder =
1992
+ ruby_to_FileBuilderContext(self->file_builder);
1993
+ google_protobuf_EnumValueDescriptorProto* enum_value;
1994
+
1995
+ enum_value = google_protobuf_EnumDescriptorProto_add_value(
1996
+ self->enum_proto, file_builder->arena);
1997
+
1998
+ google_protobuf_EnumValueDescriptorProto_set_name(
1999
+ enum_value, FileBuilderContext_strdup_sym(self->file_builder, name));
2000
+ google_protobuf_EnumValueDescriptorProto_set_number(enum_value,
2001
+ NUM2INT(number));
2002
+
2003
+ return Qnil;
1942
2004
  }
1943
2005
 
1944
2006
 
@@ -1947,33 +2009,55 @@ VALUE EnumBuilderContext_value(VALUE _self, VALUE name, VALUE number) {
1947
2009
  // -----------------------------------------------------------------------------
1948
2010
 
1949
2011
  DEFINE_CLASS(FileBuilderContext,
1950
- "Google::Protobuf::Internal::FileBuilderContext");
2012
+ "Google::Protobuf::Internal::FileBuilderContext");
1951
2013
 
1952
2014
  void FileBuilderContext_mark(void* _self) {
1953
2015
  FileBuilderContext* self = _self;
1954
- rb_gc_mark(self->pending_list);
1955
- rb_gc_mark(self->file_descriptor);
1956
- rb_gc_mark(self->builder);
2016
+ rb_gc_mark(self->descriptor_pool);
1957
2017
  }
1958
2018
 
1959
2019
  void FileBuilderContext_free(void* _self) {
1960
2020
  FileBuilderContext* self = _self;
2021
+ upb_arena_free(self->arena);
1961
2022
  xfree(self);
1962
2023
  }
1963
2024
 
2025
+ upb_strview FileBuilderContext_strdup2(VALUE _self, const char *str) {
2026
+ DEFINE_SELF(FileBuilderContext, self, _self);
2027
+ upb_strview ret;
2028
+ char *data;
2029
+
2030
+ ret.size = strlen(str);
2031
+ data = upb_malloc(upb_arena_alloc(self->arena), ret.size + 1);
2032
+ ret.data = data;
2033
+ memcpy(data, str, ret.size);
2034
+ /* Null-terminate required by rewrite_enum_defaults() above. */
2035
+ data[ret.size] = '\0';
2036
+ return ret;
2037
+ }
2038
+
2039
+ upb_strview FileBuilderContext_strdup(VALUE _self, VALUE rb_str) {
2040
+ return FileBuilderContext_strdup2(_self, get_str(rb_str));
2041
+ }
2042
+
2043
+ upb_strview FileBuilderContext_strdup_sym(VALUE _self, VALUE rb_sym) {
2044
+ Check_Type(rb_sym, T_SYMBOL);
2045
+ return FileBuilderContext_strdup(_self, rb_id2str(SYM2ID(rb_sym)));
2046
+ }
2047
+
1964
2048
  VALUE FileBuilderContext_alloc(VALUE klass) {
1965
2049
  FileBuilderContext* self = ALLOC(FileBuilderContext);
1966
2050
  VALUE ret = TypedData_Wrap_Struct(klass, &_FileBuilderContext_type, self);
1967
- self->pending_list = Qnil;
1968
- self->file_descriptor = Qnil;
1969
- self->builder = Qnil;
2051
+ self->arena = upb_arena_new();
2052
+ self->file_proto = google_protobuf_FileDescriptorProto_new(self->arena);
2053
+ self->descriptor_pool = Qnil;
1970
2054
  return ret;
1971
2055
  }
1972
2056
 
1973
2057
  void FileBuilderContext_register(VALUE module) {
1974
2058
  VALUE klass = rb_define_class_under(module, "FileBuilderContext", rb_cObject);
1975
2059
  rb_define_alloc_func(klass, FileBuilderContext_alloc);
1976
- rb_define_method(klass, "initialize", FileBuilderContext_initialize, 2);
2060
+ rb_define_method(klass, "initialize", FileBuilderContext_initialize, 3);
1977
2061
  rb_define_method(klass, "add_message", FileBuilderContext_add_message, 1);
1978
2062
  rb_define_method(klass, "add_enum", FileBuilderContext_add_enum, 1);
1979
2063
  rb_gc_register_address(&cFileBuilderContext);
@@ -1982,18 +2066,41 @@ void FileBuilderContext_register(VALUE module) {
1982
2066
 
1983
2067
  /*
1984
2068
  * call-seq:
1985
- * FileBuilderContext.new(file_descriptor, builder) => context
2069
+ * FileBuilderContext.new(descriptor_pool) => context
1986
2070
  *
1987
2071
  * Create a new file builder context for the given file descriptor and
1988
2072
  * builder context. This class is intended to serve as a DSL context to be used
1989
2073
  * with #instance_eval.
1990
2074
  */
1991
- VALUE FileBuilderContext_initialize(VALUE _self, VALUE file_descriptor,
1992
- VALUE builder) {
2075
+ VALUE FileBuilderContext_initialize(VALUE _self, VALUE descriptor_pool,
2076
+ VALUE name, VALUE options) {
1993
2077
  DEFINE_SELF(FileBuilderContext, self, _self);
1994
- self->pending_list = rb_ary_new();
1995
- self->file_descriptor = file_descriptor;
1996
- self->builder = builder;
2078
+ self->descriptor_pool = descriptor_pool;
2079
+
2080
+ google_protobuf_FileDescriptorProto_set_name(
2081
+ self->file_proto, FileBuilderContext_strdup(_self, name));
2082
+
2083
+ // Default syntax for Ruby is proto3.
2084
+ google_protobuf_FileDescriptorProto_set_syntax(
2085
+ self->file_proto,
2086
+ FileBuilderContext_strdup(_self, rb_str_new2("proto3")));
2087
+
2088
+ if (options != Qnil) {
2089
+ VALUE syntax;
2090
+
2091
+ Check_Type(options, T_HASH);
2092
+ syntax = rb_hash_lookup2(options, ID2SYM(rb_intern("syntax")), Qnil);
2093
+
2094
+ if (syntax != Qnil) {
2095
+ VALUE syntax_str;
2096
+
2097
+ Check_Type(syntax, T_SYMBOL);
2098
+ syntax_str = rb_id2str(SYM2ID(syntax));
2099
+ google_protobuf_FileDescriptorProto_set_syntax(
2100
+ self->file_proto, FileBuilderContext_strdup(_self, syntax_str));
2101
+ }
2102
+ }
2103
+
1997
2104
  return Qnil;
1998
2105
  }
1999
2106
 
@@ -2009,14 +2116,11 @@ VALUE FileBuilderContext_initialize(VALUE _self, VALUE file_descriptor,
2009
2116
  * This is the recommended, idiomatic way to build message definitions.
2010
2117
  */
2011
2118
  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 };
2119
+ VALUE args[2] = { _self, name };
2015
2120
  VALUE ctx = rb_class_new_instance(2, args, cMessageBuilderContext);
2016
2121
  VALUE block = rb_block_proc();
2017
- rb_funcall(msgdef, rb_intern("name="), 1, name);
2018
2122
  rb_funcall_with_block(ctx, rb_intern("instance_eval"), 0, NULL, block);
2019
- rb_ary_push(self->pending_list, msgdef);
2123
+ MessageBuilderContext_add_synthetic_oneofs(ctx);
2020
2124
  return Qnil;
2021
2125
  }
2022
2126
 
@@ -2031,20 +2135,26 @@ VALUE FileBuilderContext_add_message(VALUE _self, VALUE name) {
2031
2135
  * This is the recommended, idiomatic way to build enum definitions.
2032
2136
  */
2033
2137
  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);
2138
+ VALUE args[2] = { _self, name };
2139
+ VALUE ctx = rb_class_new_instance(2, args, cEnumBuilderContext);
2038
2140
  VALUE block = rb_block_proc();
2039
- rb_funcall(enumdef, rb_intern("name="), 1, name);
2040
2141
  rb_funcall_with_block(ctx, rb_intern("instance_eval"), 0, NULL, block);
2041
- rb_ary_push(self->pending_list, enumdef);
2042
2142
  return Qnil;
2043
2143
  }
2044
2144
 
2045
- VALUE FileBuilderContext_pending_descriptors(VALUE _self) {
2145
+ void FileBuilderContext_build(VALUE _self) {
2046
2146
  DEFINE_SELF(FileBuilderContext, self, _self);
2047
- return self->pending_list;
2147
+ DescriptorPool* pool = ruby_to_DescriptorPool(self->descriptor_pool);
2148
+ upb_status status;
2149
+
2150
+ rewrite_enum_defaults(pool->symtab, self->file_proto);
2151
+ rewrite_names(_self, self->file_proto);
2152
+
2153
+ upb_status_clear(&status);
2154
+ if (!upb_symtab_addfile(pool->symtab, self->file_proto, &status)) {
2155
+ rb_raise(cTypeError, "Unable to add defs to DescriptorPool: %s",
2156
+ upb_status_errmsg(&status));
2157
+ }
2048
2158
  }
2049
2159
 
2050
2160
  // -----------------------------------------------------------------------------
@@ -2055,58 +2165,46 @@ DEFINE_CLASS(Builder, "Google::Protobuf::Internal::Builder");
2055
2165
 
2056
2166
  void Builder_mark(void* _self) {
2057
2167
  Builder* self = _self;
2058
- rb_gc_mark(self->pending_list);
2059
- rb_gc_mark(self->default_file_descriptor);
2168
+ rb_gc_mark(self->descriptor_pool);
2169
+ rb_gc_mark(self->default_file_builder);
2060
2170
  }
2061
2171
 
2062
2172
  void Builder_free(void* _self) {
2063
- Builder* self = _self;
2064
- xfree(self->defs);
2065
- xfree(self);
2173
+ xfree(_self);
2066
2174
  }
2067
2175
 
2068
- /*
2069
- * call-seq:
2070
- * Builder.new => builder
2071
- *
2072
- * Creates a new Builder. A Builder can accumulate a set of new message and enum
2073
- * descriptors and atomically register them into a pool in a way that allows for
2074
- * (co)recursive type references.
2075
- */
2076
2176
  VALUE Builder_alloc(VALUE klass) {
2077
2177
  Builder* self = ALLOC(Builder);
2078
2178
  VALUE ret = TypedData_Wrap_Struct(
2079
2179
  klass, &_Builder_type, self);
2080
- self->pending_list = Qnil;
2081
- self->defs = NULL;
2082
- self->default_file_descriptor = Qnil;
2180
+ self->descriptor_pool = Qnil;
2181
+ self->default_file_builder = Qnil;
2083
2182
  return ret;
2084
2183
  }
2085
2184
 
2086
2185
  void Builder_register(VALUE module) {
2087
2186
  VALUE klass = rb_define_class_under(module, "Builder", rb_cObject);
2088
- rb_define_alloc_func(klass, Builder_alloc);
2089
- rb_define_method(klass, "initialize", Builder_initialize, 0);
2187
+ rb_define_alloc_func(klass, Builder_alloc);
2188
+ rb_define_method(klass, "initialize", Builder_initialize, 1);
2090
2189
  rb_define_method(klass, "add_file", Builder_add_file, -1);
2091
2190
  rb_define_method(klass, "add_message", Builder_add_message, 1);
2092
2191
  rb_define_method(klass, "add_enum", Builder_add_enum, 1);
2093
- rb_define_method(klass, "finalize_to_pool", Builder_finalize_to_pool, 1);
2094
2192
  rb_gc_register_address(&cBuilder);
2095
2193
  cBuilder = klass;
2096
2194
  }
2097
2195
 
2098
2196
  /*
2099
2197
  * call-seq:
2100
- * Builder.new
2198
+ * Builder.new(descriptor_pool) => builder
2101
2199
  *
2102
- * Initializes a new builder.
2200
+ * Creates a new Builder. A Builder can accumulate a set of new message and enum
2201
+ * descriptors and atomically register them into a pool in a way that allows for
2202
+ * (co)recursive type references.
2103
2203
  */
2104
- VALUE Builder_initialize(VALUE _self) {
2204
+ VALUE Builder_initialize(VALUE _self, VALUE pool) {
2105
2205
  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);
2206
+ self->descriptor_pool = pool;
2207
+ self->default_file_builder = Qnil; // Created lazily if needed.
2110
2208
  return Qnil;
2111
2209
  }
2112
2210
 
@@ -2123,17 +2221,38 @@ VALUE Builder_initialize(VALUE _self) {
2123
2221
  */
2124
2222
  VALUE Builder_add_file(int argc, VALUE* argv, VALUE _self) {
2125
2223
  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();
2224
+ VALUE name, options;
2225
+ VALUE ctx;
2226
+ VALUE block;
2227
+
2228
+ rb_scan_args(argc, argv, "11", &name, &options);
2229
+
2230
+ {
2231
+ VALUE args[3] = { self->descriptor_pool, name, options };
2232
+ ctx = rb_class_new_instance(3, args, cFileBuilderContext);
2233
+ }
2234
+
2235
+ block = rb_block_proc();
2130
2236
  rb_funcall_with_block(ctx, rb_intern("instance_eval"), 0, NULL, block);
2237
+ FileBuilderContext_build(ctx);
2131
2238
 
2132
- rb_ary_concat(self->pending_list,
2133
- FileBuilderContext_pending_descriptors(ctx));
2134
2239
  return Qnil;
2135
2240
  }
2136
2241
 
2242
+ static VALUE Builder_get_default_file(VALUE _self) {
2243
+ DEFINE_SELF(Builder, self, _self);
2244
+
2245
+ /* Lazily create only if legacy builder-level methods are called. */
2246
+ if (self->default_file_builder == Qnil) {
2247
+ VALUE name = rb_str_new2("ruby_default_file.proto");
2248
+ VALUE args [3] = { self->descriptor_pool, name, rb_hash_new() };
2249
+ self->default_file_builder =
2250
+ rb_class_new_instance(3, args, cFileBuilderContext);
2251
+ }
2252
+
2253
+ return self->default_file_builder;
2254
+ }
2255
+
2137
2256
  /*
2138
2257
  * call-seq:
2139
2258
  * Builder.add_message(name, &block)
@@ -2146,15 +2265,9 @@ VALUE Builder_add_file(int argc, VALUE* argv, VALUE _self) {
2146
2265
  * Descriptors created this way get assigned to a default empty FileDescriptor.
2147
2266
  */
2148
2267
  VALUE Builder_add_message(VALUE _self, VALUE name) {
2149
- DEFINE_SELF(Builder, self, _self);
2150
- VALUE msgdef =
2151
- rb_class_new_instance(1, &self->default_file_descriptor, cDescriptor);
2152
- VALUE args[2] = { msgdef, _self };
2153
- VALUE ctx = rb_class_new_instance(2, args, cMessageBuilderContext);
2154
- VALUE block = rb_block_proc();
2155
- rb_funcall(msgdef, rb_intern("name="), 1, name);
2156
- rb_funcall_with_block(ctx, rb_intern("instance_eval"), 0, NULL, block);
2157
- rb_ary_push(self->pending_list, msgdef);
2268
+ VALUE file_builder = Builder_get_default_file(_self);
2269
+ rb_funcall_with_block(file_builder, rb_intern("add_message"), 1, &name,
2270
+ rb_block_proc());
2158
2271
  return Qnil;
2159
2272
  }
2160
2273
 
@@ -2171,87 +2284,83 @@ VALUE Builder_add_message(VALUE _self, VALUE name) {
2171
2284
  * FileDescriptor.
2172
2285
  */
2173
2286
  VALUE Builder_add_enum(VALUE _self, VALUE name) {
2174
- DEFINE_SELF(Builder, self, _self);
2175
- VALUE enumdef =
2176
- rb_class_new_instance(1, &self->default_file_descriptor, cEnumDescriptor);
2177
- VALUE ctx = rb_class_new_instance(1, &enumdef, cEnumBuilderContext);
2178
- VALUE block = rb_block_proc();
2179
- rb_funcall(enumdef, rb_intern("name="), 1, name);
2180
- rb_funcall_with_block(ctx, rb_intern("instance_eval"), 0, NULL, block);
2181
- rb_ary_push(self->pending_list, enumdef);
2287
+ VALUE file_builder = Builder_get_default_file(_self);
2288
+ rb_funcall_with_block(file_builder, rb_intern("add_enum"), 1, &name,
2289
+ rb_block_proc());
2182
2290
  return Qnil;
2183
2291
  }
2184
2292
 
2185
- static void proto3_validate_msgdef(const upb_msgdef* msgdef) {
2186
- // Verify that no required fields exist. proto3 does not support these.
2187
- upb_msg_field_iter it;
2188
- for (upb_msg_field_begin(&it, msgdef);
2189
- !upb_msg_field_done(&it);
2190
- upb_msg_field_next(&it)) {
2191
- const upb_fielddef* field = upb_msg_iter_field(&it);
2192
- if (upb_fielddef_label(field) == UPB_LABEL_REQUIRED) {
2193
- rb_raise(cTypeError, "Required fields are unsupported in proto3.");
2194
- }
2195
- }
2196
- }
2293
+ /* This method is hidden from Ruby, and only called directly from
2294
+ * DescriptorPool_build(). */
2295
+ VALUE Builder_build(VALUE _self) {
2296
+ DEFINE_SELF(Builder, self, _self);
2197
2297
 
2198
- static void proto3_validate_enumdef(const upb_enumdef* enumdef) {
2199
- // Verify that an entry exists with integer value 0. (This is the default
2200
- // value.)
2201
- const char* lookup = upb_enumdef_iton(enumdef, 0);
2202
- if (lookup == NULL) {
2203
- rb_raise(cTypeError,
2204
- "Enum definition does not contain a value for '0'.");
2298
+ if (self->default_file_builder != Qnil) {
2299
+ FileBuilderContext_build(self->default_file_builder);
2300
+ self->default_file_builder = Qnil;
2205
2301
  }
2206
- }
2207
-
2208
- /*
2209
- * call-seq:
2210
- * Builder.finalize_to_pool(pool)
2211
- *
2212
- * Adds all accumulated message and enum descriptors created in this builder
2213
- * context to the given pool. The operation occurs atomically, and all
2214
- * descriptors can refer to each other (including in cycles). This is the only
2215
- * way to build (co)recursive message definitions.
2216
- *
2217
- * This method is usually called automatically by DescriptorPool#build after it
2218
- * invokes the given user block in the context of the builder. The user should
2219
- * not normally need to call this manually because a Builder is not normally
2220
- * created manually.
2221
- */
2222
- VALUE Builder_finalize_to_pool(VALUE _self, VALUE pool_rb) {
2223
- DEFINE_SELF(Builder, self, _self);
2224
2302
 
2225
- DescriptorPool* pool = ruby_to_DescriptorPool(pool_rb);
2303
+ return Qnil;
2304
+ }
2226
2305
 
2227
- REALLOC_N(self->defs, upb_def*, RARRAY_LEN(self->pending_list));
2306
+ static VALUE get_def_obj(VALUE _descriptor_pool, const void* ptr, VALUE klass) {
2307
+ DEFINE_SELF(DescriptorPool, descriptor_pool, _descriptor_pool);
2308
+ VALUE key = ULL2NUM((intptr_t)ptr);
2309
+ VALUE def;
2228
2310
 
2229
- for (int i = 0; i < RARRAY_LEN(self->pending_list); i++) {
2230
- VALUE def_rb = rb_ary_entry(self->pending_list, i);
2231
- if (CLASS_OF(def_rb) == cDescriptor) {
2232
- self->defs[i] = (upb_def*)ruby_to_Descriptor(def_rb)->msgdef;
2311
+ def = rb_hash_aref(descriptor_pool->def_to_descriptor, key);
2233
2312
 
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
- }
2237
- } else if (CLASS_OF(def_rb) == cEnumDescriptor) {
2238
- self->defs[i] = (upb_def*)ruby_to_EnumDescriptor(def_rb)->enumdef;
2313
+ if (ptr == NULL) {
2314
+ return Qnil;
2315
+ }
2239
2316
 
2240
- if (upb_filedef_syntax(upb_def_file(self->defs[i])) == UPB_SYNTAX_PROTO3) {
2241
- proto3_validate_enumdef((const upb_enumdef*)self->defs[i]);
2317
+ if (def == Qnil) {
2318
+ // Lazily create wrapper object.
2319
+ VALUE args[3] = { c_only_cookie, _descriptor_pool, key };
2320
+ def = rb_class_new_instance(3, args, klass);
2321
+ rb_hash_aset(descriptor_pool->def_to_descriptor, key, def);
2322
+
2323
+ // For message defs, we now eagerly get/create descriptors for all
2324
+ // submessages. We will need these anyway to parse or serialize this
2325
+ // message type. But more importantly, we must do this now so that
2326
+ // add_handlers_for_message() (which calls get_msgdef_obj()) does *not*
2327
+ // need to create a Ruby object or insert into a Ruby Hash. We need to
2328
+ // avoid triggering GC, which can switch Ruby threads and re-enter our
2329
+ // C extension from a different thread. This wreaks havoc on our state
2330
+ // if we were in the middle of building handlers.
2331
+ if (klass == cDescriptor) {
2332
+ const upb_msgdef *m = ptr;
2333
+ upb_msg_field_iter it;
2334
+ for (upb_msg_field_begin(&it, m);
2335
+ !upb_msg_field_done(&it);
2336
+ upb_msg_field_next(&it)) {
2337
+ const upb_fielddef* f = upb_msg_iter_field(&it);
2338
+ if (upb_fielddef_issubmsg(f)) {
2339
+ get_msgdef_obj(_descriptor_pool, upb_fielddef_msgsubdef(f));
2340
+ }
2242
2341
  }
2243
2342
  }
2244
2343
  }
2245
2344
 
2246
- CHECK_UPB(upb_symtab_add(pool->symtab, (upb_def**)self->defs,
2247
- RARRAY_LEN(self->pending_list), NULL, &status),
2248
- "Unable to add defs to DescriptorPool");
2345
+ return def;
2346
+ }
2249
2347
 
2250
- for (int i = 0; i < RARRAY_LEN(self->pending_list); i++) {
2251
- VALUE def_rb = rb_ary_entry(self->pending_list, i);
2252
- add_def_obj(self->defs[i], def_rb);
2253
- }
2348
+ VALUE get_msgdef_obj(VALUE descriptor_pool, const upb_msgdef* def) {
2349
+ return get_def_obj(descriptor_pool, def, cDescriptor);
2350
+ }
2254
2351
 
2255
- self->pending_list = rb_ary_new();
2256
- return Qnil;
2352
+ VALUE get_enumdef_obj(VALUE descriptor_pool, const upb_enumdef* def) {
2353
+ return get_def_obj(descriptor_pool, def, cEnumDescriptor);
2354
+ }
2355
+
2356
+ VALUE get_fielddef_obj(VALUE descriptor_pool, const upb_fielddef* def) {
2357
+ return get_def_obj(descriptor_pool, def, cFieldDescriptor);
2358
+ }
2359
+
2360
+ VALUE get_filedef_obj(VALUE descriptor_pool, const upb_filedef* def) {
2361
+ return get_def_obj(descriptor_pool, def, cFileDescriptor);
2362
+ }
2363
+
2364
+ VALUE get_oneofdef_obj(VALUE descriptor_pool, const upb_oneofdef* def) {
2365
+ return get_def_obj(descriptor_pool, def, cOneofDescriptor);
2257
2366
  }