google-protobuf 3.7.0 → 3.13.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of google-protobuf might be problematic. Click here for more details.

@@ -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
@@ -1026,34 +1041,18 @@ VALUE FieldDescriptor_number_set(VALUE _self, VALUE number) {
1026
1041
  * name will be resolved within the context of the pool to which the containing
1027
1042
  * message type is added.
1028
1043
  */
1029
- VALUE FieldDescriptor_submsg_name(VALUE _self) {
1030
- 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) {
1044
+ VALUE FieldDescriptor_submsg_name(VALUE _self) {
1048
1045
  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;
1539
1480
 
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);
1481
+ field_proto = google_protobuf_DescriptorProto_add_field(self->msg_proto,
1482
+ file_context->arena);
1483
+
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
- }
1725
-
1726
- {
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
- }
1733
+ mapentry_desc_name =
1734
+ rb_str_cat2(mapentry_desc_name, rb_id2name(SYM2ID(name)));
1735
1735
 
1736
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
2187
  rb_define_alloc_func(klass, Builder_alloc);
2089
- rb_define_method(klass, "initialize", Builder_initialize, 0);
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
2302
 
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);
2303
+ return Qnil;
2304
+ }
2224
2305
 
2225
- DescriptorPool* pool = ruby_to_DescriptorPool(pool_rb);
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;
2226
2310
 
2227
- REALLOC_N(self->defs, upb_def*, RARRAY_LEN(self->pending_list));
2311
+ def = rb_hash_aref(descriptor_pool->def_to_descriptor, key);
2228
2312
 
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;
2233
-
2234
- if (upb_filedef_syntax(upb_def_file(self->defs[i])) == UPB_SYNTAX_PROTO3) {
2235
- proto3_validate_msgdef((const upb_msgdef*)self->defs[i]);
2236
- }
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
  }