google-protobuf 3.7.0 → 3.16.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.

Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/ext/google/protobuf_c/convert.c +349 -0
  3. data/ext/google/protobuf_c/convert.h +72 -0
  4. data/ext/google/protobuf_c/defs.c +1555 -1228
  5. data/ext/google/protobuf_c/defs.h +107 -0
  6. data/ext/google/protobuf_c/extconf.rb +4 -7
  7. data/ext/google/protobuf_c/map.c +310 -470
  8. data/ext/google/protobuf_c/map.h +66 -0
  9. data/ext/google/protobuf_c/message.c +931 -346
  10. data/ext/google/protobuf_c/message.h +101 -0
  11. data/ext/google/protobuf_c/protobuf.c +384 -51
  12. data/ext/google/protobuf_c/protobuf.h +44 -544
  13. data/ext/google/protobuf_c/repeated_field.c +311 -308
  14. data/ext/google/protobuf_c/repeated_field.h +62 -0
  15. data/ext/google/protobuf_c/ruby-upb.c +8914 -0
  16. data/ext/google/protobuf_c/ruby-upb.h +4452 -0
  17. data/ext/google/protobuf_c/third_party/wyhash/wyhash.h +145 -0
  18. data/lib/google/protobuf/any_pb.rb +1 -1
  19. data/lib/google/protobuf/api_pb.rb +3 -3
  20. data/lib/google/protobuf/duration_pb.rb +1 -1
  21. data/lib/google/protobuf/empty_pb.rb +1 -1
  22. data/lib/google/protobuf/field_mask_pb.rb +1 -1
  23. data/lib/google/protobuf/source_context_pb.rb +1 -1
  24. data/lib/google/protobuf/struct_pb.rb +4 -4
  25. data/lib/google/protobuf/timestamp_pb.rb +1 -1
  26. data/lib/google/protobuf/type_pb.rb +8 -8
  27. data/lib/google/protobuf/well_known_types.rb +8 -2
  28. data/lib/google/protobuf/wrappers_pb.rb +9 -9
  29. data/lib/google/protobuf.rb +70 -0
  30. data/tests/basic.rb +315 -72
  31. data/tests/generated_code_test.rb +0 -0
  32. data/tests/stress.rb +0 -0
  33. metadata +27 -16
  34. data/ext/google/protobuf_c/encode_decode.c +0 -1574
  35. data/ext/google/protobuf_c/storage.c +0 -1019
  36. data/ext/google/protobuf_c/upb.c +0 -17318
  37. data/ext/google/protobuf_c/upb.h +0 -9755
@@ -28,8 +28,37 @@
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>
33
+ #include <ruby/version.h>
34
+
35
+ #include "convert.h"
36
+ #include "message.h"
31
37
  #include "protobuf.h"
32
38
 
39
+ static VALUE Builder_build(VALUE _self);
40
+
41
+ static VALUE cMessageBuilderContext;
42
+ static VALUE cOneofBuilderContext;
43
+ static VALUE cEnumBuilderContext;
44
+ static VALUE cBuilder;
45
+
46
+ // -----------------------------------------------------------------------------
47
+ // Global map from upb {msg,enum}defs to wrapper Descriptor/EnumDescriptor
48
+ // instances.
49
+ // -----------------------------------------------------------------------------
50
+
51
+ static VALUE get_msgdef_obj(VALUE descriptor_pool, const upb_msgdef* def);
52
+ static VALUE get_enumdef_obj(VALUE descriptor_pool, const upb_enumdef* def);
53
+ static VALUE get_fielddef_obj(VALUE descriptor_pool, const upb_fielddef* def);
54
+ static VALUE get_filedef_obj(VALUE descriptor_pool, const upb_filedef* def);
55
+ static VALUE get_oneofdef_obj(VALUE descriptor_pool, const upb_oneofdef* def);
56
+
57
+ // A distinct object that is not accessible from Ruby. We use this as a
58
+ // constructor argument to enforce that certain objects cannot be created from
59
+ // Ruby.
60
+ VALUE c_only_cookie = Qnil;
61
+
33
62
  // -----------------------------------------------------------------------------
34
63
  // Common utilities.
35
64
  // -----------------------------------------------------------------------------
@@ -46,129 +75,229 @@ static VALUE rb_str_maybe_null(const char* s) {
46
75
  return rb_str_new2(s);
47
76
  }
48
77
 
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.");
78
+ // -----------------------------------------------------------------------------
79
+ // Backward compatibility code.
80
+ // -----------------------------------------------------------------------------
81
+
82
+ static void rewrite_enum_default(const upb_symtab* symtab,
83
+ google_protobuf_FileDescriptorProto* file,
84
+ google_protobuf_FieldDescriptorProto* field) {
85
+ upb_strview defaultval;
86
+ const char *type_name_str;
87
+ char *end;
88
+ long val;
89
+ const upb_enumdef *e;
90
+ upb_strview type_name;
91
+
92
+ /* Look for TYPE_ENUM fields that have a default. */
93
+ if (google_protobuf_FieldDescriptorProto_type(field) !=
94
+ google_protobuf_FieldDescriptorProto_TYPE_ENUM ||
95
+ !google_protobuf_FieldDescriptorProto_has_default_value(field) ||
96
+ !google_protobuf_FieldDescriptorProto_has_type_name(field)) {
97
+ return;
54
98
  }
55
- return (upb_def*)def;
56
- }
57
99
 
58
- static upb_msgdef* check_msg_notfrozen(const upb_msgdef* def) {
59
- return upb_downcast_msgdef_mutable(check_notfrozen((const upb_def*)def));
100
+ defaultval = google_protobuf_FieldDescriptorProto_default_value(field);
101
+ type_name = google_protobuf_FieldDescriptorProto_type_name(field);
102
+
103
+ if (defaultval.size == 0 || !isdigit(defaultval.data[0])) {
104
+ return;
105
+ }
106
+
107
+ if (type_name.size == 0 || type_name.data[0] != '.') {
108
+ return;
109
+ }
110
+
111
+ type_name_str = type_name.data + 1;
112
+
113
+ errno = 0;
114
+ val = strtol(defaultval.data, &end, 10);
115
+
116
+ if (errno != 0 || *end != 0 || val < INT32_MIN || val > INT32_MAX) {
117
+ return;
118
+ }
119
+
120
+ /* Now find the corresponding enum definition. */
121
+ e = upb_symtab_lookupenum(symtab, type_name_str);
122
+ if (e) {
123
+ /* Look in previously loaded files. */
124
+ const char *label = upb_enumdef_iton(e, val);
125
+ if (!label) {
126
+ return;
127
+ }
128
+ google_protobuf_FieldDescriptorProto_set_default_value(
129
+ field, upb_strview_makez(label));
130
+ } else {
131
+ /* Look in enums defined in this file. */
132
+ const google_protobuf_EnumDescriptorProto* matching_enum = NULL;
133
+ size_t i, n;
134
+ const google_protobuf_EnumDescriptorProto* const* enums =
135
+ google_protobuf_FileDescriptorProto_enum_type(file, &n);
136
+ const google_protobuf_EnumValueDescriptorProto* const* values;
137
+
138
+ for (i = 0; i < n; i++) {
139
+ if (upb_strview_eql(google_protobuf_EnumDescriptorProto_name(enums[i]),
140
+ upb_strview_makez(type_name_str))) {
141
+ matching_enum = enums[i];
142
+ break;
143
+ }
144
+ }
145
+
146
+ if (!matching_enum) {
147
+ return;
148
+ }
149
+
150
+ values = google_protobuf_EnumDescriptorProto_value(matching_enum, &n);
151
+ for (i = 0; i < n; i++) {
152
+ if (google_protobuf_EnumValueDescriptorProto_number(values[i]) == val) {
153
+ google_protobuf_FieldDescriptorProto_set_default_value(
154
+ field, google_protobuf_EnumValueDescriptorProto_name(values[i]));
155
+ return;
156
+ }
157
+ }
158
+
159
+ /* We failed to find an enum default. But we'll just leave the enum
160
+ * untouched and let the normal def-building code catch it. */
161
+ }
60
162
  }
61
163
 
62
- static upb_fielddef* check_field_notfrozen(const upb_fielddef* def) {
63
- return upb_downcast_fielddef_mutable(check_notfrozen((const upb_def*)def));
164
+ /* Historically we allowed enum defaults to be specified as a number. In
165
+ * retrospect this was a mistake as descriptors require defaults to be
166
+ * specified as a label. This can make a difference if multiple labels have the
167
+ * same number.
168
+ *
169
+ * Here we do a pass over all enum defaults and rewrite numeric defaults by
170
+ * looking up their labels. This is complicated by the fact that the enum
171
+ * definition can live in either the symtab or the file_proto.
172
+ * */
173
+ static void rewrite_enum_defaults(
174
+ const upb_symtab* symtab, google_protobuf_FileDescriptorProto* file_proto) {
175
+ size_t i, n;
176
+ google_protobuf_DescriptorProto** msgs =
177
+ google_protobuf_FileDescriptorProto_mutable_message_type(file_proto, &n);
178
+
179
+ for (i = 0; i < n; i++) {
180
+ size_t j, m;
181
+ google_protobuf_FieldDescriptorProto** fields =
182
+ google_protobuf_DescriptorProto_mutable_field(msgs[i], &m);
183
+ for (j = 0; j < m; j++) {
184
+ rewrite_enum_default(symtab, file_proto, fields[j]);
185
+ }
186
+ }
64
187
  }
65
188
 
66
- static upb_oneofdef* check_oneof_notfrozen(const upb_oneofdef* def) {
67
- return (upb_oneofdef*)check_notfrozen((const upb_def*)def);
189
+ static void remove_path(upb_strview *name) {
190
+ const char* last = strrchr(name->data, '.');
191
+ if (last) {
192
+ size_t remove = last - name->data + 1;
193
+ name->data += remove;
194
+ name->size -= remove;
195
+ }
68
196
  }
69
197
 
70
- static upb_enumdef* check_enum_notfrozen(const upb_enumdef* def) {
71
- return (upb_enumdef*)check_notfrozen((const upb_def*)def);
198
+ static void rewrite_nesting(VALUE msg_ent, google_protobuf_DescriptorProto* msg,
199
+ google_protobuf_DescriptorProto* const* msgs,
200
+ google_protobuf_EnumDescriptorProto* const* enums,
201
+ upb_arena *arena) {
202
+ VALUE submsgs = rb_hash_aref(msg_ent, ID2SYM(rb_intern("msgs")));
203
+ VALUE enum_pos = rb_hash_aref(msg_ent, ID2SYM(rb_intern("enums")));
204
+ int submsg_count;
205
+ int enum_count;
206
+ int i;
207
+ google_protobuf_DescriptorProto** msg_msgs;
208
+ google_protobuf_EnumDescriptorProto** msg_enums;
209
+
210
+ Check_Type(submsgs, T_ARRAY);
211
+ Check_Type(enum_pos, T_ARRAY);
212
+
213
+ submsg_count = RARRAY_LEN(submsgs);
214
+ enum_count = RARRAY_LEN(enum_pos);
215
+
216
+ msg_msgs = google_protobuf_DescriptorProto_resize_nested_type(
217
+ msg, submsg_count, arena);
218
+ msg_enums =
219
+ google_protobuf_DescriptorProto_resize_enum_type(msg, enum_count, arena);
220
+
221
+ for (i = 0; i < submsg_count; i++) {
222
+ VALUE submsg_ent = RARRAY_PTR(submsgs)[i];
223
+ VALUE pos = rb_hash_aref(submsg_ent, ID2SYM(rb_intern("pos")));
224
+ upb_strview name;
225
+
226
+ msg_msgs[i] = msgs[NUM2INT(pos)];
227
+ name = google_protobuf_DescriptorProto_name(msg_msgs[i]);
228
+ remove_path(&name);
229
+ google_protobuf_DescriptorProto_set_name(msg_msgs[i], name);
230
+ rewrite_nesting(submsg_ent, msg_msgs[i], msgs, enums, arena);
231
+ }
232
+
233
+ for (i = 0; i < enum_count; i++) {
234
+ VALUE pos = RARRAY_PTR(enum_pos)[i];
235
+ msg_enums[i] = enums[NUM2INT(pos)];
236
+ }
72
237
  }
73
238
 
74
239
  // -----------------------------------------------------------------------------
75
240
  // DescriptorPool.
76
241
  // -----------------------------------------------------------------------------
77
242
 
78
- #define DEFINE_CLASS(name, string_name) \
79
- VALUE c ## name = Qnil; \
80
- const rb_data_type_t _ ## name ## _type = { \
81
- string_name, \
82
- { name ## _mark, name ## _free, NULL }, \
83
- }; \
84
- name* ruby_to_ ## name(VALUE val) { \
85
- name* ret; \
86
- TypedData_Get_Struct(val, name, &_ ## name ## _type, ret); \
87
- return ret; \
88
- } \
89
-
90
- #define DEFINE_SELF(type, var, rb_var) \
91
- type* var = ruby_to_ ## type(rb_var)
243
+ typedef struct {
244
+ VALUE def_to_descriptor; // Hash table of def* -> Ruby descriptor.
245
+ upb_symtab* symtab;
246
+ } DescriptorPool;
247
+
248
+ VALUE cDescriptorPool = Qnil;
92
249
 
93
250
  // Global singleton DescriptorPool. The user is free to create others, but this
94
251
  // is used by generated code.
95
- VALUE generated_pool;
252
+ VALUE generated_pool = Qnil;
96
253
 
97
- DEFINE_CLASS(DescriptorPool, "Google::Protobuf::DescriptorPool");
98
-
99
- void DescriptorPool_mark(void* _self) {
254
+ static void DescriptorPool_mark(void* _self) {
255
+ DescriptorPool* self = _self;
256
+ rb_gc_mark(self->def_to_descriptor);
100
257
  }
101
258
 
102
- void DescriptorPool_free(void* _self) {
259
+ static void DescriptorPool_free(void* _self) {
103
260
  DescriptorPool* self = _self;
104
261
  upb_symtab_free(self->symtab);
105
262
  xfree(self);
106
263
  }
107
264
 
265
+ static const rb_data_type_t DescriptorPool_type = {
266
+ "Google::Protobuf::DescriptorPool",
267
+ {DescriptorPool_mark, DescriptorPool_free, NULL},
268
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY,
269
+ };
270
+
271
+ static DescriptorPool* ruby_to_DescriptorPool(VALUE val) {
272
+ DescriptorPool* ret;
273
+ TypedData_Get_Struct(val, DescriptorPool, &DescriptorPool_type, ret);
274
+ return ret;
275
+ }
276
+
277
+ // Exposed to other modules in defs.h.
278
+ const upb_symtab *DescriptorPool_GetSymtab(VALUE desc_pool_rb) {
279
+ DescriptorPool *pool = ruby_to_DescriptorPool(desc_pool_rb);
280
+ return pool->symtab;
281
+ }
282
+
108
283
  /*
109
284
  * call-seq:
110
285
  * DescriptorPool.new => pool
111
286
  *
112
287
  * Creates a new, empty, descriptor pool.
113
288
  */
114
- VALUE DescriptorPool_alloc(VALUE klass) {
289
+ static VALUE DescriptorPool_alloc(VALUE klass) {
115
290
  DescriptorPool* self = ALLOC(DescriptorPool);
116
- self->symtab = upb_symtab_new();
117
- return TypedData_Wrap_Struct(klass, &_DescriptorPool_type, self);
118
- }
119
-
120
- void DescriptorPool_register(VALUE module) {
121
- VALUE klass = rb_define_class_under(
122
- module, "DescriptorPool", rb_cObject);
123
- rb_define_alloc_func(klass, DescriptorPool_alloc);
124
- rb_define_method(klass, "add", DescriptorPool_add, 1);
125
- rb_define_method(klass, "build", DescriptorPool_build, -1);
126
- rb_define_method(klass, "lookup", DescriptorPool_lookup, 1);
127
- rb_define_singleton_method(klass, "generated_pool",
128
- DescriptorPool_generated_pool, 0);
129
- rb_gc_register_address(&cDescriptorPool);
130
- cDescriptorPool = klass;
131
-
132
- rb_gc_register_address(&generated_pool);
133
- generated_pool = rb_class_new_instance(0, NULL, klass);
134
- }
291
+ VALUE ret;
135
292
 
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
- }
293
+ self->def_to_descriptor = Qnil;
294
+ ret = TypedData_Wrap_Struct(klass, &DescriptorPool_type, self);
143
295
 
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
- }
296
+ self->def_to_descriptor = rb_hash_new();
297
+ self->symtab = upb_symtab_new();
298
+ ObjectCache_Add(self->symtab, ret);
151
299
 
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;
300
+ return ret;
172
301
  }
173
302
 
174
303
  /*
@@ -181,11 +310,11 @@ VALUE DescriptorPool_add(VALUE _self, VALUE def) {
181
310
  * Builder#add_enum within the block as appropriate. This is the recommended,
182
311
  * idiomatic way to define new message and enum types.
183
312
  */
184
- VALUE DescriptorPool_build(int argc, VALUE* argv, VALUE _self) {
185
- VALUE ctx = rb_class_new_instance(0, NULL, cBuilder);
313
+ static VALUE DescriptorPool_build(int argc, VALUE* argv, VALUE _self) {
314
+ VALUE ctx = rb_class_new_instance(1, &_self, cBuilder);
186
315
  VALUE block = rb_block_proc();
187
316
  rb_funcall_with_block(ctx, rb_intern("instance_eval"), 0, NULL, block);
188
- rb_funcall(ctx, rb_intern("finalize_to_pool"), 1, _self);
317
+ Builder_build(ctx);
189
318
  return Qnil;
190
319
  }
191
320
 
@@ -196,14 +325,23 @@ VALUE DescriptorPool_build(int argc, VALUE* argv, VALUE _self) {
196
325
  * Finds a Descriptor or EnumDescriptor by name and returns it, or nil if none
197
326
  * exists with the given name.
198
327
  */
199
- VALUE DescriptorPool_lookup(VALUE _self, VALUE name) {
200
- DEFINE_SELF(DescriptorPool, self, _self);
328
+ static VALUE DescriptorPool_lookup(VALUE _self, VALUE name) {
329
+ DescriptorPool* self = ruby_to_DescriptorPool(_self);
201
330
  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;
331
+ const upb_msgdef* msgdef;
332
+ const upb_enumdef* enumdef;
333
+
334
+ msgdef = upb_symtab_lookupmsg(self->symtab, name_str);
335
+ if (msgdef) {
336
+ return get_msgdef_obj(_self, msgdef);
337
+ }
338
+
339
+ enumdef = upb_symtab_lookupenum(self->symtab, name_str);
340
+ if (enumdef) {
341
+ return get_enumdef_obj(_self, enumdef);
205
342
  }
206
- return get_def_obj(def);
343
+
344
+ return Qnil;
207
345
  }
208
346
 
209
347
  /*
@@ -215,50 +353,53 @@ VALUE DescriptorPool_lookup(VALUE _self, VALUE name) {
215
353
  * register types in this pool for convenience so that they do not have to hold
216
354
  * a reference to a private pool instance.
217
355
  */
218
- VALUE DescriptorPool_generated_pool(VALUE _self) {
356
+ static VALUE DescriptorPool_generated_pool(VALUE _self) {
219
357
  return generated_pool;
220
358
  }
221
359
 
360
+ static void DescriptorPool_register(VALUE module) {
361
+ VALUE klass = rb_define_class_under(
362
+ module, "DescriptorPool", rb_cObject);
363
+ rb_define_alloc_func(klass, DescriptorPool_alloc);
364
+ rb_define_method(klass, "build", DescriptorPool_build, -1);
365
+ rb_define_method(klass, "lookup", DescriptorPool_lookup, 1);
366
+ rb_define_singleton_method(klass, "generated_pool",
367
+ DescriptorPool_generated_pool, 0);
368
+ rb_gc_register_address(&cDescriptorPool);
369
+ cDescriptorPool = klass;
370
+
371
+ rb_gc_register_address(&generated_pool);
372
+ generated_pool = rb_class_new_instance(0, NULL, klass);
373
+ }
374
+
222
375
  // -----------------------------------------------------------------------------
223
376
  // Descriptor.
224
377
  // -----------------------------------------------------------------------------
225
378
 
226
- DEFINE_CLASS(Descriptor, "Google::Protobuf::Descriptor");
379
+ typedef struct {
380
+ const upb_msgdef* msgdef;
381
+ VALUE klass;
382
+ VALUE descriptor_pool;
383
+ } Descriptor;
227
384
 
228
- void Descriptor_mark(void* _self) {
385
+ VALUE cDescriptor = Qnil;
386
+
387
+ static void Descriptor_mark(void* _self) {
229
388
  Descriptor* self = _self;
230
389
  rb_gc_mark(self->klass);
390
+ rb_gc_mark(self->descriptor_pool);
231
391
  }
232
392
 
233
- void Descriptor_free(void* _self) {
234
- Descriptor* self = _self;
235
- upb_msgdef_unref(self->msgdef, &self->msgdef);
236
- if (self->layout) {
237
- free_layout(self->layout);
238
- }
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
- xfree(self);
393
+ static const rb_data_type_t Descriptor_type = {
394
+ "Google::Protobuf::Descriptor",
395
+ {Descriptor_mark, RUBY_DEFAULT_FREE, NULL},
396
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY,
397
+ };
398
+
399
+ static Descriptor* ruby_to_Descriptor(VALUE val) {
400
+ Descriptor* ret;
401
+ TypedData_Get_Struct(val, Descriptor, &Descriptor_type, ret);
402
+ return ret;
262
403
  }
263
404
 
264
405
  /*
@@ -270,56 +411,32 @@ void Descriptor_free(void* _self) {
270
411
  * it is added to a pool, after which it becomes immutable (as part of a
271
412
  * finalization process).
272
413
  */
273
- VALUE Descriptor_alloc(VALUE klass) {
414
+ static VALUE Descriptor_alloc(VALUE klass) {
274
415
  Descriptor* self = ALLOC(Descriptor);
275
- VALUE ret = TypedData_Wrap_Struct(klass, &_Descriptor_type, self);
276
- self->msgdef = upb_msgdef_new(&self->msgdef);
416
+ VALUE ret = TypedData_Wrap_Struct(klass, &Descriptor_type, self);
417
+ self->msgdef = NULL;
277
418
  self->klass = Qnil;
278
- 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;
419
+ self->descriptor_pool = Qnil;
285
420
  return ret;
286
421
  }
287
422
 
288
- void Descriptor_register(VALUE module) {
289
- VALUE klass = rb_define_class_under(
290
- module, "Descriptor", rb_cObject);
291
- rb_define_alloc_func(klass, Descriptor_alloc);
292
- rb_define_method(klass, "initialize", Descriptor_initialize, 1);
293
- rb_define_method(klass, "each", Descriptor_each, 0);
294
- 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
- rb_define_method(klass, "each_oneof", Descriptor_each_oneof, 0);
298
- rb_define_method(klass, "lookup_oneof", Descriptor_lookup_oneof, 1);
299
- rb_define_method(klass, "msgclass", Descriptor_msgclass, 0);
300
- rb_define_method(klass, "name", Descriptor_name, 0);
301
- rb_define_method(klass, "name=", Descriptor_name_set, 1);
302
- rb_define_method(klass, "file_descriptor", Descriptor_file_descriptor, 0);
303
- rb_include_module(klass, rb_mEnumerable);
304
- rb_gc_register_address(&cDescriptor);
305
- cDescriptor = klass;
306
- }
307
-
308
423
  /*
309
424
  * call-seq:
310
- * Descriptor.new(file_descriptor)
425
+ * Descriptor.new(c_only_cookie, ptr) => Descriptor
311
426
  *
312
- * Initializes a new descriptor and assigns a file descriptor to it.
427
+ * Creates a descriptor wrapper object. May only be called from C.
313
428
  */
314
- VALUE Descriptor_initialize(VALUE _self, VALUE file_descriptor_rb) {
315
- DEFINE_SELF(Descriptor, self, _self);
429
+ static VALUE Descriptor_initialize(VALUE _self, VALUE cookie,
430
+ VALUE descriptor_pool, VALUE ptr) {
431
+ Descriptor* self = ruby_to_Descriptor(_self);
316
432
 
317
- FileDescriptor* file_descriptor = ruby_to_FileDescriptor(file_descriptor_rb);
433
+ if (cookie != c_only_cookie) {
434
+ rb_raise(rb_eRuntimeError,
435
+ "Descriptor objects may not be created from Ruby.");
436
+ }
318
437
 
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);
438
+ self->descriptor_pool = descriptor_pool;
439
+ self->msgdef = (const upb_msgdef*)NUM2ULL(ptr);
323
440
 
324
441
  return Qnil;
325
442
  }
@@ -330,55 +447,38 @@ VALUE Descriptor_initialize(VALUE _self, VALUE file_descriptor_rb) {
330
447
  *
331
448
  * Returns the FileDescriptor object this message belongs to.
332
449
  */
333
- VALUE Descriptor_file_descriptor(VALUE _self) {
334
- DEFINE_SELF(Descriptor, self, _self);
335
- return get_def_obj(upb_def_file(self->msgdef));
450
+ static VALUE Descriptor_file_descriptor(VALUE _self) {
451
+ Descriptor* self = ruby_to_Descriptor(_self);
452
+ return get_filedef_obj(self->descriptor_pool, upb_msgdef_file(self->msgdef));
336
453
  }
337
454
 
338
455
  /*
339
456
  * call-seq:
340
457
  * Descriptor.name => name
341
458
  *
342
- * Returns the name of this message type as a fully-qualfied string (e.g.,
459
+ * Returns the name of this message type as a fully-qualified string (e.g.,
343
460
  * My.Package.MessageType).
344
461
  */
345
- VALUE Descriptor_name(VALUE _self) {
346
- DEFINE_SELF(Descriptor, self, _self);
462
+ static VALUE Descriptor_name(VALUE _self) {
463
+ Descriptor* self = ruby_to_Descriptor(_self);
347
464
  return rb_str_maybe_null(upb_msgdef_fullname(self->msgdef));
348
465
  }
349
466
 
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
467
  /*
368
468
  * call-seq:
369
469
  * Descriptor.each(&block)
370
470
  *
371
471
  * Iterates over fields in this message type, yielding to the block on each one.
372
472
  */
373
- VALUE Descriptor_each(VALUE _self) {
374
- DEFINE_SELF(Descriptor, self, _self);
473
+ static VALUE Descriptor_each(VALUE _self) {
474
+ Descriptor* self = ruby_to_Descriptor(_self);
375
475
 
376
476
  upb_msg_field_iter it;
377
477
  for (upb_msg_field_begin(&it, self->msgdef);
378
478
  !upb_msg_field_done(&it);
379
479
  upb_msg_field_next(&it)) {
380
480
  const upb_fielddef* field = upb_msg_iter_field(&it);
381
- VALUE obj = get_def_obj(field);
481
+ VALUE obj = get_fielddef_obj(self->descriptor_pool, field);
382
482
  rb_yield(obj);
383
483
  }
384
484
  return Qnil;
@@ -391,58 +491,14 @@ VALUE Descriptor_each(VALUE _self) {
391
491
  * Returns the field descriptor for the field with the given name, if present,
392
492
  * or nil if none.
393
493
  */
394
- VALUE Descriptor_lookup(VALUE _self, VALUE name) {
395
- DEFINE_SELF(Descriptor, self, _self);
494
+ static VALUE Descriptor_lookup(VALUE _self, VALUE name) {
495
+ Descriptor* self = ruby_to_Descriptor(_self);
396
496
  const char* s = get_str(name);
397
497
  const upb_fielddef* field = upb_msgdef_ntofz(self->msgdef, s);
398
498
  if (field == NULL) {
399
499
  return Qnil;
400
500
  }
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;
501
+ return get_fielddef_obj(self->descriptor_pool, field);
446
502
  }
447
503
 
448
504
  /*
@@ -452,15 +508,15 @@ VALUE Descriptor_add_oneof(VALUE _self, VALUE obj) {
452
508
  * Invokes the given block for each oneof in this message type, passing the
453
509
  * corresponding OneofDescriptor.
454
510
  */
455
- VALUE Descriptor_each_oneof(VALUE _self) {
456
- DEFINE_SELF(Descriptor, self, _self);
511
+ static VALUE Descriptor_each_oneof(VALUE _self) {
512
+ Descriptor* self = ruby_to_Descriptor(_self);
457
513
 
458
514
  upb_msg_oneof_iter it;
459
515
  for (upb_msg_oneof_begin(&it, self->msgdef);
460
516
  !upb_msg_oneof_done(&it);
461
517
  upb_msg_oneof_next(&it)) {
462
518
  const upb_oneofdef* oneof = upb_msg_iter_oneof(&it);
463
- VALUE obj = get_def_obj(oneof);
519
+ VALUE obj = get_oneofdef_obj(self->descriptor_pool, oneof);
464
520
  rb_yield(obj);
465
521
  }
466
522
  return Qnil;
@@ -473,111 +529,101 @@ VALUE Descriptor_each_oneof(VALUE _self) {
473
529
  * Returns the oneof descriptor for the oneof with the given name, if present,
474
530
  * or nil if none.
475
531
  */
476
- VALUE Descriptor_lookup_oneof(VALUE _self, VALUE name) {
477
- DEFINE_SELF(Descriptor, self, _self);
532
+ static VALUE Descriptor_lookup_oneof(VALUE _self, VALUE name) {
533
+ Descriptor* self = ruby_to_Descriptor(_self);
478
534
  const char* s = get_str(name);
479
535
  const upb_oneofdef* oneof = upb_msgdef_ntooz(self->msgdef, s);
480
536
  if (oneof == NULL) {
481
537
  return Qnil;
482
538
  }
483
- return get_def_obj(oneof);
539
+ return get_oneofdef_obj(self->descriptor_pool, oneof);
484
540
  }
485
541
 
486
542
  /*
487
543
  * call-seq:
488
544
  * Descriptor.msgclass => message_klass
489
545
  *
490
- * Returns the Ruby class created for this message type. Valid only once the
491
- * message type has been added to a pool.
546
+ * Returns the Ruby class created for this message type.
492
547
  */
493
- VALUE Descriptor_msgclass(VALUE _self) {
494
- 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
- }
548
+ static VALUE Descriptor_msgclass(VALUE _self) {
549
+ Descriptor* self = ruby_to_Descriptor(_self);
499
550
  if (self->klass == Qnil) {
500
- self->klass = build_class_from_descriptor(self);
551
+ self->klass = build_class_from_descriptor(_self);
501
552
  }
502
553
  return self->klass;
503
554
  }
504
555
 
556
+ static void Descriptor_register(VALUE module) {
557
+ VALUE klass = rb_define_class_under(
558
+ module, "Descriptor", rb_cObject);
559
+ rb_define_alloc_func(klass, Descriptor_alloc);
560
+ rb_define_method(klass, "initialize", Descriptor_initialize, 3);
561
+ rb_define_method(klass, "each", Descriptor_each, 0);
562
+ rb_define_method(klass, "lookup", Descriptor_lookup, 1);
563
+ rb_define_method(klass, "each_oneof", Descriptor_each_oneof, 0);
564
+ rb_define_method(klass, "lookup_oneof", Descriptor_lookup_oneof, 1);
565
+ rb_define_method(klass, "msgclass", Descriptor_msgclass, 0);
566
+ rb_define_method(klass, "name", Descriptor_name, 0);
567
+ rb_define_method(klass, "file_descriptor", Descriptor_file_descriptor, 0);
568
+ rb_include_module(klass, rb_mEnumerable);
569
+ rb_gc_register_address(&cDescriptor);
570
+ cDescriptor = klass;
571
+ }
572
+
505
573
  // -----------------------------------------------------------------------------
506
574
  // FileDescriptor.
507
575
  // -----------------------------------------------------------------------------
508
576
 
509
- DEFINE_CLASS(FileDescriptor, "Google::Protobuf::FileDescriptor");
577
+ typedef struct {
578
+ const upb_filedef* filedef;
579
+ VALUE descriptor_pool; // Owns the upb_filedef.
580
+ } FileDescriptor;
510
581
 
511
- void FileDescriptor_mark(void* _self) {
512
- }
582
+ static VALUE cFileDescriptor = Qnil;
513
583
 
514
- void FileDescriptor_free(void* _self) {
584
+ static void FileDescriptor_mark(void* _self) {
515
585
  FileDescriptor* self = _self;
516
- upb_filedef_unref(self->filedef, &self->filedef);
517
- xfree(self);
586
+ rb_gc_mark(self->descriptor_pool);
518
587
  }
519
588
 
520
- /*
521
- * call-seq:
522
- * FileDescriptor.new => file
523
- *
524
- * Returns a new file descriptor. The syntax must be set before it's passed
525
- * to a builder.
526
- */
527
- VALUE FileDescriptor_alloc(VALUE klass) {
528
- FileDescriptor* self = ALLOC(FileDescriptor);
529
- VALUE ret = TypedData_Wrap_Struct(klass, &_FileDescriptor_type, self);
530
- upb_filedef* filedef = upb_filedef_new(&self->filedef);
531
- self->filedef = filedef;
589
+ static const rb_data_type_t FileDescriptor_type = {
590
+ "Google::Protobuf::FileDescriptor",
591
+ {FileDescriptor_mark, RUBY_DEFAULT_FREE, NULL},
592
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY,
593
+ };
594
+
595
+ static FileDescriptor* ruby_to_FileDescriptor(VALUE val) {
596
+ FileDescriptor* ret;
597
+ TypedData_Get_Struct(val, FileDescriptor, &FileDescriptor_type, ret);
532
598
  return ret;
533
599
  }
534
600
 
535
- void FileDescriptor_register(VALUE module) {
536
- VALUE klass = rb_define_class_under(
537
- module, "FileDescriptor", rb_cObject);
538
- rb_define_alloc_func(klass, FileDescriptor_alloc);
539
- rb_define_method(klass, "initialize", FileDescriptor_initialize, -1);
540
- rb_define_method(klass, "name", FileDescriptor_name, 0);
541
- rb_define_method(klass, "syntax", FileDescriptor_syntax, 0);
542
- rb_define_method(klass, "syntax=", FileDescriptor_syntax_set, 1);
543
- rb_gc_register_address(&cFileDescriptor);
544
- cFileDescriptor = klass;
601
+ static VALUE FileDescriptor_alloc(VALUE klass) {
602
+ FileDescriptor* self = ALLOC(FileDescriptor);
603
+ VALUE ret = TypedData_Wrap_Struct(klass, &FileDescriptor_type, self);
604
+ self->descriptor_pool = Qnil;
605
+ self->filedef = NULL;
606
+ return ret;
545
607
  }
546
608
 
547
609
  /*
548
610
  * call-seq:
549
- * FileDescriptor.new(name, options = nil) => file
611
+ * FileDescriptor.new => file
550
612
  *
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)
613
+ * Returns a new file descriptor. The syntax must be set before it's passed
614
+ * to a builder.
555
615
  */
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);
616
+ static VALUE FileDescriptor_initialize(VALUE _self, VALUE cookie,
617
+ VALUE descriptor_pool, VALUE ptr) {
618
+ FileDescriptor* self = ruby_to_FileDescriptor(_self);
562
619
 
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");
620
+ if (cookie != c_only_cookie) {
621
+ rb_raise(rb_eRuntimeError,
622
+ "Descriptor objects may not be created from Ruby.");
568
623
  }
569
624
 
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);
625
+ self->descriptor_pool = descriptor_pool;
626
+ self->filedef = (const upb_filedef*)NUM2ULL(ptr);
581
627
 
582
628
  return Qnil;
583
629
  }
@@ -588,8 +634,8 @@ VALUE FileDescriptor_initialize(int argc, VALUE* argv, VALUE _self) {
588
634
  *
589
635
  * Returns the name of the file.
590
636
  */
591
- VALUE FileDescriptor_name(VALUE _self) {
592
- DEFINE_SELF(FileDescriptor, self, _self);
637
+ static VALUE FileDescriptor_name(VALUE _self) {
638
+ FileDescriptor* self = ruby_to_FileDescriptor(_self);
593
639
  const char* name = upb_filedef_name(self->filedef);
594
640
  return name == NULL ? Qnil : rb_str_new2(name);
595
641
  }
@@ -603,8 +649,8 @@ VALUE FileDescriptor_name(VALUE _self) {
603
649
  * Valid syntax versions are:
604
650
  * :proto2 or :proto3.
605
651
  */
606
- VALUE FileDescriptor_syntax(VALUE _self) {
607
- DEFINE_SELF(FileDescriptor, self, _self);
652
+ static VALUE FileDescriptor_syntax(VALUE _self) {
653
+ FileDescriptor* self = ruby_to_FileDescriptor(_self);
608
654
 
609
655
  switch (upb_filedef_syntax(self->filedef)) {
610
656
  case UPB_SYNTAX_PROTO3: return ID2SYM(rb_intern("proto3"));
@@ -613,44 +659,43 @@ VALUE FileDescriptor_syntax(VALUE _self) {
613
659
  }
614
660
  }
615
661
 
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;
662
+ static void FileDescriptor_register(VALUE module) {
663
+ VALUE klass = rb_define_class_under(
664
+ module, "FileDescriptor", rb_cObject);
665
+ rb_define_alloc_func(klass, FileDescriptor_alloc);
666
+ rb_define_method(klass, "initialize", FileDescriptor_initialize, 3);
667
+ rb_define_method(klass, "name", FileDescriptor_name, 0);
668
+ rb_define_method(klass, "syntax", FileDescriptor_syntax, 0);
669
+ rb_gc_register_address(&cFileDescriptor);
670
+ cFileDescriptor = klass;
639
671
  }
640
672
 
641
673
  // -----------------------------------------------------------------------------
642
674
  // FieldDescriptor.
643
675
  // -----------------------------------------------------------------------------
644
676
 
645
- DEFINE_CLASS(FieldDescriptor, "Google::Protobuf::FieldDescriptor");
677
+ typedef struct {
678
+ const upb_fielddef* fielddef;
679
+ VALUE descriptor_pool; // Owns the upb_fielddef.
680
+ } FieldDescriptor;
646
681
 
647
- void FieldDescriptor_mark(void* _self) {
648
- }
682
+ static VALUE cFieldDescriptor = Qnil;
649
683
 
650
- void FieldDescriptor_free(void* _self) {
684
+ static void FieldDescriptor_mark(void* _self) {
651
685
  FieldDescriptor* self = _self;
652
- upb_fielddef_unref(self->fielddef, &self->fielddef);
653
- xfree(self);
686
+ rb_gc_mark(self->descriptor_pool);
687
+ }
688
+
689
+ static const rb_data_type_t FieldDescriptor_type = {
690
+ "Google::Protobuf::FieldDescriptor",
691
+ {FieldDescriptor_mark, RUBY_DEFAULT_FREE, NULL},
692
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY,
693
+ };
694
+
695
+ static FieldDescriptor* ruby_to_FieldDescriptor(VALUE val) {
696
+ FieldDescriptor* ret;
697
+ TypedData_Get_Struct(val, FieldDescriptor, &FieldDescriptor_type, ret);
698
+ return ret;
654
699
  }
655
700
 
656
701
  /*
@@ -660,67 +705,46 @@ void FieldDescriptor_free(void* _self) {
660
705
  * Returns a new field descriptor. Its name, type, etc. must be set before it is
661
706
  * added to a message type.
662
707
  */
663
- VALUE FieldDescriptor_alloc(VALUE klass) {
708
+ static VALUE FieldDescriptor_alloc(VALUE klass) {
664
709
  FieldDescriptor* self = ALLOC(FieldDescriptor);
665
- 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;
710
+ VALUE ret = TypedData_Wrap_Struct(klass, &FieldDescriptor_type, self);
711
+ self->fielddef = NULL;
669
712
  return ret;
670
713
  }
671
714
 
672
- void FieldDescriptor_register(VALUE module) {
673
- VALUE klass = rb_define_class_under(
674
- module, "FieldDescriptor", rb_cObject);
675
- rb_define_alloc_func(klass, FieldDescriptor_alloc);
676
- rb_define_method(klass, "name", FieldDescriptor_name, 0);
677
- rb_define_method(klass, "name=", FieldDescriptor_name_set, 1);
678
- rb_define_method(klass, "type", FieldDescriptor_type, 0);
679
- rb_define_method(klass, "type=", FieldDescriptor_type_set, 1);
680
- rb_define_method(klass, "default", FieldDescriptor_default, 0);
681
- rb_define_method(klass, "default=", FieldDescriptor_default_set, 1);
682
- rb_define_method(klass, "label", FieldDescriptor_label, 0);
683
- rb_define_method(klass, "label=", FieldDescriptor_label_set, 1);
684
- rb_define_method(klass, "number", FieldDescriptor_number, 0);
685
- rb_define_method(klass, "number=", FieldDescriptor_number_set, 1);
686
- rb_define_method(klass, "submsg_name", FieldDescriptor_submsg_name, 0);
687
- rb_define_method(klass, "submsg_name=", FieldDescriptor_submsg_name_set, 1);
688
- rb_define_method(klass, "subtype", FieldDescriptor_subtype, 0);
689
- rb_define_method(klass, "has?", FieldDescriptor_has, 1);
690
- rb_define_method(klass, "clear", FieldDescriptor_clear, 1);
691
- rb_define_method(klass, "get", FieldDescriptor_get, 1);
692
- rb_define_method(klass, "set", FieldDescriptor_set, 2);
693
- rb_gc_register_address(&cFieldDescriptor);
694
- cFieldDescriptor = klass;
695
- }
696
-
697
715
  /*
698
716
  * call-seq:
699
- * FieldDescriptor.name => name
717
+ * EnumDescriptor.new(c_only_cookie, pool, ptr) => EnumDescriptor
700
718
  *
701
- * Returns the name of this field.
719
+ * Creates a descriptor wrapper object. May only be called from C.
702
720
  */
703
- VALUE FieldDescriptor_name(VALUE _self) {
704
- DEFINE_SELF(FieldDescriptor, self, _self);
705
- return rb_str_maybe_null(upb_fielddef_name(self->fielddef));
721
+ static VALUE FieldDescriptor_initialize(VALUE _self, VALUE cookie,
722
+ VALUE descriptor_pool, VALUE ptr) {
723
+ FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
724
+
725
+ if (cookie != c_only_cookie) {
726
+ rb_raise(rb_eRuntimeError,
727
+ "Descriptor objects may not be created from Ruby.");
728
+ }
729
+
730
+ self->descriptor_pool = descriptor_pool;
731
+ self->fielddef = (const upb_fielddef*)NUM2ULL(ptr);
732
+
733
+ return Qnil;
706
734
  }
707
735
 
708
736
  /*
709
737
  * call-seq:
710
- * FieldDescriptor.name = name
738
+ * FieldDescriptor.name => name
711
739
  *
712
- * Sets the name of this field. Cannot be called once the containing message
713
- * type, if any, is added to a pool.
740
+ * Returns the name of this field.
714
741
  */
715
- VALUE FieldDescriptor_name_set(VALUE _self, VALUE str) {
716
- 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;
742
+ static VALUE FieldDescriptor_name(VALUE _self) {
743
+ FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
744
+ return rb_str_maybe_null(upb_fielddef_name(self->fielddef));
722
745
  }
723
746
 
747
+ // Non-static, exposed to other .c files.
724
748
  upb_fieldtype_t ruby_to_fieldtype(VALUE type) {
725
749
  if (TYPE(type) != T_SYMBOL) {
726
750
  rb_raise(rb_eArgError, "Expected symbol for field type.");
@@ -749,27 +773,7 @@ upb_fieldtype_t ruby_to_fieldtype(VALUE type) {
749
773
  return 0;
750
774
  }
751
775
 
752
- VALUE fieldtype_to_ruby(upb_fieldtype_t type) {
753
- switch (type) {
754
- #define CONVERT(upb, ruby) \
755
- case UPB_TYPE_ ## upb : return ID2SYM(rb_intern( # ruby ));
756
- CONVERT(FLOAT, float);
757
- CONVERT(DOUBLE, double);
758
- CONVERT(BOOL, bool);
759
- CONVERT(STRING, string);
760
- CONVERT(BYTES, bytes);
761
- CONVERT(MESSAGE, message);
762
- CONVERT(ENUM, enum);
763
- CONVERT(INT32, int32);
764
- CONVERT(INT64, int64);
765
- CONVERT(UINT32, uint32);
766
- CONVERT(UINT64, uint64);
767
- #undef CONVERT
768
- }
769
- return Qnil;
770
- }
771
-
772
- upb_descriptortype_t ruby_to_descriptortype(VALUE type) {
776
+ static upb_descriptortype_t ruby_to_descriptortype(VALUE type) {
773
777
  if (TYPE(type) != T_SYMBOL) {
774
778
  rb_raise(rb_eArgError, "Expected symbol for field type.");
775
779
  }
@@ -804,7 +808,7 @@ upb_descriptortype_t ruby_to_descriptortype(VALUE type) {
804
808
  return 0;
805
809
  }
806
810
 
807
- VALUE descriptortype_to_ruby(upb_descriptortype_t type) {
811
+ static VALUE descriptortype_to_ruby(upb_descriptortype_t type) {
808
812
  switch (type) {
809
813
  #define CONVERT(upb, ruby) \
810
814
  case UPB_DESCRIPTOR_TYPE_ ## upb : return ID2SYM(rb_intern( # ruby ));
@@ -841,91 +845,41 @@ VALUE descriptortype_to_ruby(upb_descriptortype_t type) {
841
845
  * :int32, :int64, :uint32, :uint64, :float, :double, :bool, :string,
842
846
  * :bytes, :message.
843
847
  */
844
- VALUE FieldDescriptor_type(VALUE _self) {
845
- DEFINE_SELF(FieldDescriptor, self, _self);
846
- if (!upb_fielddef_typeisset(self->fielddef)) {
847
- return Qnil;
848
- }
848
+ static VALUE FieldDescriptor__type(VALUE _self) {
849
+ FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
849
850
  return descriptortype_to_ruby(upb_fielddef_descriptortype(self->fielddef));
850
851
  }
851
852
 
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
853
  /*
867
854
  * call-seq:
868
855
  * FieldDescriptor.default => default
869
856
  *
870
857
  * Returns this field's default, as a Ruby object, or nil if not yet set.
871
858
  */
872
- VALUE FieldDescriptor_default(VALUE _self) {
873
- DEFINE_SELF(FieldDescriptor, self, _self);
874
- return layout_get_default(self->fielddef);
859
+ static VALUE FieldDescriptor_default(VALUE _self) {
860
+ FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
861
+ const upb_fielddef *f = self->fielddef;
862
+ upb_msgval default_val = {0};
863
+ if (upb_fielddef_issubmsg(f)) {
864
+ return Qnil;
865
+ } else if (!upb_fielddef_isseq(f)) {
866
+ default_val = upb_fielddef_default(f);
867
+ }
868
+ return Convert_UpbToRuby(default_val, TypeInfo_get(self->fielddef), Qnil);
875
869
  }
876
870
 
871
+
877
872
  /*
878
873
  * call-seq:
879
- * FieldDescriptor.default = default
874
+ * FieldDescriptor.json_name => json_name
880
875
  *
881
- * Sets this field's default value. Raises an exception when calling with
882
- * proto syntax 3.
876
+ * Returns this field's json_name, as a Ruby string, or nil if not yet set.
883
877
  */
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;
878
+ static VALUE FieldDescriptor_json_name(VALUE _self) {
879
+ FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
880
+ const upb_fielddef *f = self->fielddef;
881
+ const char *json_name = upb_fielddef_jsonname(f);
882
+ return rb_str_new2(json_name);
929
883
  }
930
884
 
931
885
  /*
@@ -937,8 +891,8 @@ VALUE FieldDescriptor_default_set(VALUE _self, VALUE default_value) {
937
891
  * Valid field labels are:
938
892
  * :optional, :repeated
939
893
  */
940
- VALUE FieldDescriptor_label(VALUE _self) {
941
- DEFINE_SELF(FieldDescriptor, self, _self);
894
+ static VALUE FieldDescriptor_label(VALUE _self) {
895
+ FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
942
896
  switch (upb_fielddef_label(self->fielddef)) {
943
897
  #define CONVERT(upb, ruby) \
944
898
  case UPB_LABEL_ ## upb : return ID2SYM(rb_intern( # ruby ));
@@ -953,70 +907,17 @@ VALUE FieldDescriptor_label(VALUE _self) {
953
907
  return Qnil;
954
908
  }
955
909
 
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
910
  /*
995
911
  * call-seq:
996
912
  * FieldDescriptor.number => number
997
913
  *
998
914
  * Returns the tag number for this field.
999
915
  */
1000
- VALUE FieldDescriptor_number(VALUE _self) {
1001
- DEFINE_SELF(FieldDescriptor, self, _self);
916
+ static VALUE FieldDescriptor_number(VALUE _self) {
917
+ FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
1002
918
  return INT2NUM(upb_fielddef_number(self->fielddef));
1003
919
  }
1004
920
 
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
921
  /*
1021
922
  * call-seq:
1022
923
  * FieldDescriptor.submsg_name => submsg_name
@@ -1026,34 +927,18 @@ VALUE FieldDescriptor_number_set(VALUE _self, VALUE number) {
1026
927
  * name will be resolved within the context of the pool to which the containing
1027
928
  * message type is added.
1028
929
  */
1029
- VALUE FieldDescriptor_submsg_name(VALUE _self) {
1030
- DEFINE_SELF(FieldDescriptor, self, _self);
1031
- if (!upb_fielddef_hassubdef(self->fielddef)) {
1032
- return Qnil;
930
+ static VALUE FieldDescriptor_submsg_name(VALUE _self) {
931
+ FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
932
+ switch (upb_fielddef_type(self->fielddef)) {
933
+ case UPB_TYPE_ENUM:
934
+ return rb_str_new2(
935
+ upb_enumdef_fullname(upb_fielddef_enumsubdef(self->fielddef)));
936
+ case UPB_TYPE_MESSAGE:
937
+ return rb_str_new2(
938
+ upb_msgdef_fullname(upb_fielddef_msgsubdef(self->fielddef)));
939
+ default:
940
+ return Qnil;
1033
941
  }
1034
- return rb_str_maybe_null(upb_fielddef_subdefname(self->fielddef));
1035
- }
1036
-
1037
- /*
1038
- * call-seq:
1039
- * FieldDescriptor.submsg_name = submsg_name
1040
- *
1041
- * Sets the name of the message or enum type corresponding to this field, if it
1042
- * is a message or enum field (respectively). This type name will be resolved
1043
- * within the context of the pool to which the containing message type is added.
1044
- * Cannot be called on field that are not of message or enum type, or on fields
1045
- * that are part of a message type already added to a pool.
1046
- */
1047
- VALUE FieldDescriptor_submsg_name_set(VALUE _self, VALUE value) {
1048
- DEFINE_SELF(FieldDescriptor, self, _self);
1049
- upb_fielddef* mut_def = check_field_notfrozen(self->fielddef);
1050
- const char* str = get_str(value);
1051
- if (!upb_fielddef_hassubdef(self->fielddef)) {
1052
- rb_raise(cTypeError, "FieldDescriptor does not have subdef.");
1053
- }
1054
- CHECK_UPB(upb_fielddef_setsubdefname(mut_def, str, &status),
1055
- "Error setting submessage name");
1056
- return Qnil;
1057
942
  }
1058
943
 
1059
944
  /*
@@ -1065,18 +950,18 @@ VALUE FieldDescriptor_submsg_name_set(VALUE _self, VALUE value) {
1065
950
  * called *until* the containing message type is added to a pool (and thus
1066
951
  * resolved).
1067
952
  */
1068
- VALUE FieldDescriptor_subtype(VALUE _self) {
1069
- 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;
953
+ static VALUE FieldDescriptor_subtype(VALUE _self) {
954
+ FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
955
+ switch (upb_fielddef_type(self->fielddef)) {
956
+ case UPB_TYPE_ENUM:
957
+ return get_enumdef_obj(self->descriptor_pool,
958
+ upb_fielddef_enumsubdef(self->fielddef));
959
+ case UPB_TYPE_MESSAGE:
960
+ return get_msgdef_obj(self->descriptor_pool,
961
+ upb_fielddef_msgsubdef(self->fielddef));
962
+ default:
963
+ return Qnil;
1078
964
  }
1079
- return get_def_obj(def);
1080
965
  }
1081
966
 
1082
967
  /*
@@ -1086,14 +971,17 @@ VALUE FieldDescriptor_subtype(VALUE _self) {
1086
971
  * Returns the value set for this field on the given message. Raises an
1087
972
  * exception if message is of the wrong type.
1088
973
  */
1089
- VALUE FieldDescriptor_get(VALUE _self, VALUE msg_rb) {
1090
- DEFINE_SELF(FieldDescriptor, self, _self);
1091
- MessageHeader* msg;
1092
- TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg);
1093
- if (msg->descriptor->msgdef != upb_fielddef_containingtype(self->fielddef)) {
974
+ static VALUE FieldDescriptor_get(VALUE _self, VALUE msg_rb) {
975
+ FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
976
+ const upb_msgdef *m;
977
+
978
+ Message_Get(msg_rb, &m);
979
+
980
+ if (m != upb_fielddef_containingtype(self->fielddef)) {
1094
981
  rb_raise(cTypeError, "get method called on wrong message type");
1095
982
  }
1096
- return layout_get(msg->descriptor->layout, Message_data(msg), self->fielddef);
983
+
984
+ return Message_getfield(msg_rb, self->fielddef);
1097
985
  }
1098
986
 
1099
987
  /*
@@ -1101,19 +989,20 @@ VALUE FieldDescriptor_get(VALUE _self, VALUE msg_rb) {
1101
989
  * FieldDescriptor.has?(message) => boolean
1102
990
  *
1103
991
  * Returns whether the value is set on the given message. Raises an
1104
- * exception when calling with proto syntax 3.
992
+ * exception when calling for fields that do not have presence.
1105
993
  */
1106
- VALUE FieldDescriptor_has(VALUE _self, VALUE msg_rb) {
1107
- DEFINE_SELF(FieldDescriptor, self, _self);
1108
- MessageHeader* msg;
1109
- TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg);
1110
- if (msg->descriptor->msgdef != upb_fielddef_containingtype(self->fielddef)) {
994
+ static VALUE FieldDescriptor_has(VALUE _self, VALUE msg_rb) {
995
+ FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
996
+ const upb_msgdef *m;
997
+ const upb_msgdef *msg = Message_Get(msg_rb, &m);
998
+
999
+ if (m != upb_fielddef_containingtype(self->fielddef)) {
1111
1000
  rb_raise(cTypeError, "has method called on wrong message type");
1112
1001
  } else if (!upb_fielddef_haspresence(self->fielddef)) {
1113
1002
  rb_raise(rb_eArgError, "does not track presence");
1114
1003
  }
1115
1004
 
1116
- return layout_has(msg->descriptor->layout, Message_data(msg), self->fielddef);
1005
+ return upb_msg_has(msg, self->fielddef) ? Qtrue : Qfalse;
1117
1006
  }
1118
1007
 
1119
1008
  /*
@@ -1122,15 +1011,16 @@ VALUE FieldDescriptor_has(VALUE _self, VALUE msg_rb) {
1122
1011
  *
1123
1012
  * Clears the field from the message if it's set.
1124
1013
  */
1125
- VALUE FieldDescriptor_clear(VALUE _self, VALUE msg_rb) {
1126
- DEFINE_SELF(FieldDescriptor, self, _self);
1127
- MessageHeader* msg;
1128
- TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg);
1129
- if (msg->descriptor->msgdef != upb_fielddef_containingtype(self->fielddef)) {
1014
+ static VALUE FieldDescriptor_clear(VALUE _self, VALUE msg_rb) {
1015
+ FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
1016
+ const upb_msgdef *m;
1017
+ upb_msgdef *msg = Message_GetMutable(msg_rb, &m);
1018
+
1019
+ if (m != upb_fielddef_containingtype(self->fielddef)) {
1130
1020
  rb_raise(cTypeError, "has method called on wrong message type");
1131
1021
  }
1132
1022
 
1133
- layout_clear(msg->descriptor->layout, Message_data(msg), self->fielddef);
1023
+ upb_msg_clearfield(msg, self->fielddef);
1134
1024
  return Qnil;
1135
1025
  }
1136
1026
 
@@ -1142,30 +1032,70 @@ VALUE FieldDescriptor_clear(VALUE _self, VALUE msg_rb) {
1142
1032
  * message. Raises an exception if message is of the wrong type. Performs the
1143
1033
  * ordinary type-checks for field setting.
1144
1034
  */
1145
- VALUE FieldDescriptor_set(VALUE _self, VALUE msg_rb, VALUE value) {
1146
- DEFINE_SELF(FieldDescriptor, self, _self);
1147
- MessageHeader* msg;
1148
- TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg);
1149
- if (msg->descriptor->msgdef != upb_fielddef_containingtype(self->fielddef)) {
1035
+ static VALUE FieldDescriptor_set(VALUE _self, VALUE msg_rb, VALUE value) {
1036
+ FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
1037
+ const upb_msgdef *m;
1038
+ upb_msgdef *msg = Message_GetMutable(msg_rb, &m);
1039
+ upb_arena *arena = Arena_get(Message_GetArena(msg_rb));
1040
+ upb_msgval msgval;
1041
+
1042
+ if (m != upb_fielddef_containingtype(self->fielddef)) {
1150
1043
  rb_raise(cTypeError, "set method called on wrong message type");
1151
1044
  }
1152
- layout_set(msg->descriptor->layout, Message_data(msg), self->fielddef, value);
1045
+
1046
+ msgval = Convert_RubyToUpb(value, upb_fielddef_name(self->fielddef),
1047
+ TypeInfo_get(self->fielddef), arena);
1048
+ upb_msg_set(msg, self->fielddef, msgval, arena);
1153
1049
  return Qnil;
1154
1050
  }
1155
1051
 
1052
+ static void FieldDescriptor_register(VALUE module) {
1053
+ VALUE klass = rb_define_class_under(
1054
+ module, "FieldDescriptor", rb_cObject);
1055
+ rb_define_alloc_func(klass, FieldDescriptor_alloc);
1056
+ rb_define_method(klass, "initialize", FieldDescriptor_initialize, 3);
1057
+ rb_define_method(klass, "name", FieldDescriptor_name, 0);
1058
+ rb_define_method(klass, "type", FieldDescriptor__type, 0);
1059
+ rb_define_method(klass, "default", FieldDescriptor_default, 0);
1060
+ rb_define_method(klass, "json_name", FieldDescriptor_json_name, 0);
1061
+ rb_define_method(klass, "label", FieldDescriptor_label, 0);
1062
+ rb_define_method(klass, "number", FieldDescriptor_number, 0);
1063
+ rb_define_method(klass, "submsg_name", FieldDescriptor_submsg_name, 0);
1064
+ rb_define_method(klass, "subtype", FieldDescriptor_subtype, 0);
1065
+ rb_define_method(klass, "has?", FieldDescriptor_has, 1);
1066
+ rb_define_method(klass, "clear", FieldDescriptor_clear, 1);
1067
+ rb_define_method(klass, "get", FieldDescriptor_get, 1);
1068
+ rb_define_method(klass, "set", FieldDescriptor_set, 2);
1069
+ rb_gc_register_address(&cFieldDescriptor);
1070
+ cFieldDescriptor = klass;
1071
+ }
1072
+
1156
1073
  // -----------------------------------------------------------------------------
1157
1074
  // OneofDescriptor.
1158
1075
  // -----------------------------------------------------------------------------
1159
1076
 
1160
- DEFINE_CLASS(OneofDescriptor, "Google::Protobuf::OneofDescriptor");
1077
+ typedef struct {
1078
+ const upb_oneofdef* oneofdef;
1079
+ VALUE descriptor_pool; // Owns the upb_oneofdef.
1080
+ } OneofDescriptor;
1161
1081
 
1162
- void OneofDescriptor_mark(void* _self) {
1163
- }
1082
+ static VALUE cOneofDescriptor = Qnil;
1164
1083
 
1165
- void OneofDescriptor_free(void* _self) {
1084
+ static void OneofDescriptor_mark(void* _self) {
1166
1085
  OneofDescriptor* self = _self;
1167
- upb_oneofdef_unref(self->oneofdef, &self->oneofdef);
1168
- xfree(self);
1086
+ rb_gc_mark(self->descriptor_pool);
1087
+ }
1088
+
1089
+ static const rb_data_type_t OneofDescriptor_type = {
1090
+ "Google::Protobuf::OneofDescriptor",
1091
+ {OneofDescriptor_mark, RUBY_DEFAULT_FREE, NULL},
1092
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY,
1093
+ };
1094
+
1095
+ static OneofDescriptor* ruby_to_OneofDescriptor(VALUE val) {
1096
+ OneofDescriptor* ret;
1097
+ TypedData_Get_Struct(val, OneofDescriptor, &OneofDescriptor_type, ret);
1098
+ return ret;
1169
1099
  }
1170
1100
 
1171
1101
  /*
@@ -1175,77 +1105,44 @@ void OneofDescriptor_free(void* _self) {
1175
1105
  * Creates a new, empty, oneof descriptor. The oneof may only be modified prior
1176
1106
  * to being added to a message descriptor which is subsequently added to a pool.
1177
1107
  */
1178
- VALUE OneofDescriptor_alloc(VALUE klass) {
1108
+ static VALUE OneofDescriptor_alloc(VALUE klass) {
1179
1109
  OneofDescriptor* self = ALLOC(OneofDescriptor);
1180
- VALUE ret = TypedData_Wrap_Struct(klass, &_OneofDescriptor_type, self);
1181
- self->oneofdef = upb_oneofdef_new(&self->oneofdef);
1110
+ VALUE ret = TypedData_Wrap_Struct(klass, &OneofDescriptor_type, self);
1111
+ self->oneofdef = NULL;
1112
+ self->descriptor_pool = Qnil;
1182
1113
  return ret;
1183
1114
  }
1184
1115
 
1185
- void OneofDescriptor_register(VALUE module) {
1186
- VALUE klass = rb_define_class_under(
1187
- module, "OneofDescriptor", rb_cObject);
1188
- rb_define_alloc_func(klass, OneofDescriptor_alloc);
1189
- 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
- rb_define_method(klass, "each", OneofDescriptor_each, 0);
1193
- rb_include_module(klass, rb_mEnumerable);
1194
- rb_gc_register_address(&cOneofDescriptor);
1195
- cOneofDescriptor = klass;
1196
- }
1197
-
1198
1116
  /*
1199
1117
  * call-seq:
1200
- * OneofDescriptor.name => name
1118
+ * OneofDescriptor.new(c_only_cookie, pool, ptr) => OneofDescriptor
1201
1119
  *
1202
- * Returns the name of this oneof.
1120
+ * Creates a descriptor wrapper object. May only be called from C.
1203
1121
  */
1204
- VALUE OneofDescriptor_name(VALUE _self) {
1205
- DEFINE_SELF(OneofDescriptor, self, _self);
1206
- return rb_str_maybe_null(upb_oneofdef_name(self->oneofdef));
1207
- }
1122
+ static VALUE OneofDescriptor_initialize(VALUE _self, VALUE cookie,
1123
+ VALUE descriptor_pool, VALUE ptr) {
1124
+ OneofDescriptor* self = ruby_to_OneofDescriptor(_self);
1125
+
1126
+ if (cookie != c_only_cookie) {
1127
+ rb_raise(rb_eRuntimeError,
1128
+ "Descriptor objects may not be created from Ruby.");
1129
+ }
1130
+
1131
+ self->descriptor_pool = descriptor_pool;
1132
+ self->oneofdef = (const upb_oneofdef*)NUM2ULL(ptr);
1208
1133
 
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");
1222
1134
  return Qnil;
1223
1135
  }
1224
1136
 
1225
1137
  /*
1226
1138
  * 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.
1139
+ * OneofDescriptor.name => name
1233
1140
  *
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.
1141
+ * Returns the name of this oneof.
1238
1142
  */
1239
- VALUE OneofDescriptor_add_field(VALUE _self, VALUE obj) {
1240
- 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;
1143
+ static VALUE OneofDescriptor_name(VALUE _self) {
1144
+ OneofDescriptor* self = ruby_to_OneofDescriptor(_self);
1145
+ return rb_str_maybe_null(upb_oneofdef_name(self->oneofdef));
1249
1146
  }
1250
1147
 
1251
1148
  /*
@@ -1254,97 +1151,107 @@ VALUE OneofDescriptor_add_field(VALUE _self, VALUE obj) {
1254
1151
  *
1255
1152
  * Iterates through fields in this oneof, yielding to the block on each one.
1256
1153
  */
1257
- VALUE OneofDescriptor_each(VALUE _self, VALUE field) {
1258
- DEFINE_SELF(OneofDescriptor, self, _self);
1154
+ static VALUE OneofDescriptor_each(VALUE _self) {
1155
+ OneofDescriptor* self = ruby_to_OneofDescriptor(_self);
1259
1156
  upb_oneof_iter it;
1260
1157
  for (upb_oneof_begin(&it, self->oneofdef);
1261
1158
  !upb_oneof_done(&it);
1262
1159
  upb_oneof_next(&it)) {
1263
1160
  const upb_fielddef* f = upb_oneof_iter_field(&it);
1264
- VALUE obj = get_def_obj(f);
1161
+ VALUE obj = get_fielddef_obj(self->descriptor_pool, f);
1265
1162
  rb_yield(obj);
1266
1163
  }
1267
1164
  return Qnil;
1268
1165
  }
1269
1166
 
1167
+ static void OneofDescriptor_register(VALUE module) {
1168
+ VALUE klass = rb_define_class_under(
1169
+ module, "OneofDescriptor", rb_cObject);
1170
+ rb_define_alloc_func(klass, OneofDescriptor_alloc);
1171
+ rb_define_method(klass, "initialize", OneofDescriptor_initialize, 3);
1172
+ rb_define_method(klass, "name", OneofDescriptor_name, 0);
1173
+ rb_define_method(klass, "each", OneofDescriptor_each, 0);
1174
+ rb_include_module(klass, rb_mEnumerable);
1175
+ rb_gc_register_address(&cOneofDescriptor);
1176
+ cOneofDescriptor = klass;
1177
+ }
1178
+
1270
1179
  // -----------------------------------------------------------------------------
1271
1180
  // EnumDescriptor.
1272
1181
  // -----------------------------------------------------------------------------
1273
1182
 
1274
- DEFINE_CLASS(EnumDescriptor, "Google::Protobuf::EnumDescriptor");
1183
+ typedef struct {
1184
+ const upb_enumdef* enumdef;
1185
+ VALUE module; // begins as nil
1186
+ VALUE descriptor_pool; // Owns the upb_enumdef.
1187
+ } EnumDescriptor;
1275
1188
 
1276
- void EnumDescriptor_mark(void* _self) {
1189
+ static VALUE cEnumDescriptor = Qnil;
1190
+
1191
+ static void EnumDescriptor_mark(void* _self) {
1277
1192
  EnumDescriptor* self = _self;
1278
1193
  rb_gc_mark(self->module);
1194
+ rb_gc_mark(self->descriptor_pool);
1279
1195
  }
1280
1196
 
1281
- void EnumDescriptor_free(void* _self) {
1282
- EnumDescriptor* self = _self;
1283
- upb_enumdef_unref(self->enumdef, &self->enumdef);
1284
- xfree(self);
1197
+ static const rb_data_type_t EnumDescriptor_type = {
1198
+ "Google::Protobuf::EnumDescriptor",
1199
+ {EnumDescriptor_mark, RUBY_DEFAULT_FREE, NULL},
1200
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY,
1201
+ };
1202
+
1203
+ static EnumDescriptor* ruby_to_EnumDescriptor(VALUE val) {
1204
+ EnumDescriptor* ret;
1205
+ TypedData_Get_Struct(val, EnumDescriptor, &EnumDescriptor_type, ret);
1206
+ return ret;
1285
1207
  }
1286
1208
 
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
- VALUE EnumDescriptor_alloc(VALUE klass) {
1209
+ static VALUE EnumDescriptor_alloc(VALUE klass) {
1296
1210
  EnumDescriptor* self = ALLOC(EnumDescriptor);
1297
- VALUE ret = TypedData_Wrap_Struct(klass, &_EnumDescriptor_type, self);
1298
- self->enumdef = upb_enumdef_new(&self->enumdef);
1211
+ VALUE ret = TypedData_Wrap_Struct(klass, &EnumDescriptor_type, self);
1212
+ self->enumdef = NULL;
1299
1213
  self->module = Qnil;
1214
+ self->descriptor_pool = Qnil;
1300
1215
  return ret;
1301
1216
  }
1302
1217
 
1303
- void EnumDescriptor_register(VALUE module) {
1304
- VALUE klass = rb_define_class_under(
1305
- module, "EnumDescriptor", rb_cObject);
1306
- rb_define_alloc_func(klass, EnumDescriptor_alloc);
1307
- rb_define_method(klass, "initialize", EnumDescriptor_initialize, 1);
1308
- 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
- rb_define_method(klass, "lookup_name", EnumDescriptor_lookup_name, 1);
1312
- rb_define_method(klass, "lookup_value", EnumDescriptor_lookup_value, 1);
1313
- rb_define_method(klass, "each", EnumDescriptor_each, 0);
1314
- rb_define_method(klass, "enummodule", EnumDescriptor_enummodule, 0);
1315
- rb_define_method(klass, "file_descriptor", EnumDescriptor_file_descriptor, 0);
1316
- rb_include_module(klass, rb_mEnumerable);
1317
- rb_gc_register_address(&cEnumDescriptor);
1318
- cEnumDescriptor = klass;
1218
+ // Exposed to other modules in defs.h.
1219
+ const upb_enumdef *EnumDescriptor_GetEnumDef(VALUE enum_desc_rb) {
1220
+ EnumDescriptor *desc = ruby_to_EnumDescriptor(enum_desc_rb);
1221
+ return desc->enumdef;
1319
1222
  }
1320
1223
 
1321
1224
  /*
1322
1225
  * call-seq:
1323
- * Descriptor.new(file_descriptor)
1226
+ * EnumDescriptor.new(c_only_cookie, ptr) => EnumDescriptor
1324
1227
  *
1325
- * Initializes a new descriptor and assigns a file descriptor to it.
1228
+ * Creates a descriptor wrapper object. May only be called from C.
1326
1229
  */
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);
1230
+ static VALUE EnumDescriptor_initialize(VALUE _self, VALUE cookie,
1231
+ VALUE descriptor_pool, VALUE ptr) {
1232
+ EnumDescriptor* self = ruby_to_EnumDescriptor(_self);
1233
+
1234
+ if (cookie != c_only_cookie) {
1235
+ rb_raise(rb_eRuntimeError,
1236
+ "Descriptor objects may not be created from Ruby.");
1237
+ }
1238
+
1239
+ self->descriptor_pool = descriptor_pool;
1240
+ self->enumdef = (const upb_enumdef*)NUM2ULL(ptr);
1335
1241
 
1336
1242
  return Qnil;
1337
1243
  }
1338
1244
 
1339
1245
  /*
1340
1246
  * call-seq:
1341
- * Descriptor.file_descriptor
1247
+ * EnumDescriptor.file_descriptor
1342
1248
  *
1343
1249
  * Returns the FileDescriptor object this enum belongs to.
1344
1250
  */
1345
- VALUE EnumDescriptor_file_descriptor(VALUE _self) {
1346
- DEFINE_SELF(EnumDescriptor, self, _self);
1347
- return get_def_obj(upb_def_file(self->enumdef));
1251
+ static VALUE EnumDescriptor_file_descriptor(VALUE _self) {
1252
+ EnumDescriptor* self = ruby_to_EnumDescriptor(_self);
1253
+ return get_filedef_obj(self->descriptor_pool,
1254
+ upb_enumdef_file(self->enumdef));
1348
1255
  }
1349
1256
 
1350
1257
  /*
@@ -1353,45 +1260,11 @@ VALUE EnumDescriptor_file_descriptor(VALUE _self) {
1353
1260
  *
1354
1261
  * Returns the name of this enum type.
1355
1262
  */
1356
- VALUE EnumDescriptor_name(VALUE _self) {
1357
- DEFINE_SELF(EnumDescriptor, self, _self);
1263
+ static VALUE EnumDescriptor_name(VALUE _self) {
1264
+ EnumDescriptor* self = ruby_to_EnumDescriptor(_self);
1358
1265
  return rb_str_maybe_null(upb_enumdef_fullname(self->enumdef));
1359
1266
  }
1360
1267
 
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
1268
  /*
1396
1269
  * call-seq:
1397
1270
  * EnumDescriptor.lookup_name(name) => value
@@ -1399,8 +1272,8 @@ VALUE EnumDescriptor_add_value(VALUE _self, VALUE name, VALUE number) {
1399
1272
  * Returns the numeric value corresponding to the given key name (as a Ruby
1400
1273
  * symbol), or nil if none.
1401
1274
  */
1402
- VALUE EnumDescriptor_lookup_name(VALUE _self, VALUE name) {
1403
- DEFINE_SELF(EnumDescriptor, self, _self);
1275
+ static VALUE EnumDescriptor_lookup_name(VALUE _self, VALUE name) {
1276
+ EnumDescriptor* self = ruby_to_EnumDescriptor(_self);
1404
1277
  const char* name_str= rb_id2name(SYM2ID(name));
1405
1278
  int32_t val = 0;
1406
1279
  if (upb_enumdef_ntoiz(self->enumdef, name_str, &val)) {
@@ -1417,8 +1290,8 @@ VALUE EnumDescriptor_lookup_name(VALUE _self, VALUE name) {
1417
1290
  * Returns the key name (as a Ruby symbol) corresponding to the integer value,
1418
1291
  * or nil if none.
1419
1292
  */
1420
- VALUE EnumDescriptor_lookup_value(VALUE _self, VALUE number) {
1421
- DEFINE_SELF(EnumDescriptor, self, _self);
1293
+ static VALUE EnumDescriptor_lookup_value(VALUE _self, VALUE number) {
1294
+ EnumDescriptor* self = ruby_to_EnumDescriptor(_self);
1422
1295
  int32_t val = NUM2INT(number);
1423
1296
  const char* name = upb_enumdef_iton(self->enumdef, val);
1424
1297
  if (name != NULL) {
@@ -1435,8 +1308,8 @@ VALUE EnumDescriptor_lookup_value(VALUE _self, VALUE number) {
1435
1308
  * Iterates over key => value mappings in this enum's definition, yielding to
1436
1309
  * the block with (key, value) arguments for each one.
1437
1310
  */
1438
- VALUE EnumDescriptor_each(VALUE _self) {
1439
- DEFINE_SELF(EnumDescriptor, self, _self);
1311
+ static VALUE EnumDescriptor_each(VALUE _self) {
1312
+ EnumDescriptor* self = ruby_to_EnumDescriptor(_self);
1440
1313
 
1441
1314
  upb_enum_iter it;
1442
1315
  for (upb_enum_begin(&it, self->enumdef);
@@ -1454,139 +1327,509 @@ VALUE EnumDescriptor_each(VALUE _self) {
1454
1327
  * call-seq:
1455
1328
  * EnumDescriptor.enummodule => module
1456
1329
  *
1457
- * Returns the Ruby module corresponding to this enum type. Cannot be called
1458
- * until the enum descriptor has been added to a pool.
1330
+ * Returns the Ruby module corresponding to this enum type.
1459
1331
  */
1460
- VALUE EnumDescriptor_enummodule(VALUE _self) {
1461
- 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
- }
1332
+ static VALUE EnumDescriptor_enummodule(VALUE _self) {
1333
+ EnumDescriptor* self = ruby_to_EnumDescriptor(_self);
1467
1334
  if (self->module == Qnil) {
1468
- self->module = build_module_from_enumdesc(self);
1335
+ self->module = build_module_from_enumdesc(_self);
1469
1336
  }
1470
1337
  return self->module;
1471
1338
  }
1472
1339
 
1340
+ static void EnumDescriptor_register(VALUE module) {
1341
+ VALUE klass = rb_define_class_under(
1342
+ module, "EnumDescriptor", rb_cObject);
1343
+ rb_define_alloc_func(klass, EnumDescriptor_alloc);
1344
+ rb_define_method(klass, "initialize", EnumDescriptor_initialize, 3);
1345
+ rb_define_method(klass, "name", EnumDescriptor_name, 0);
1346
+ rb_define_method(klass, "lookup_name", EnumDescriptor_lookup_name, 1);
1347
+ rb_define_method(klass, "lookup_value", EnumDescriptor_lookup_value, 1);
1348
+ rb_define_method(klass, "each", EnumDescriptor_each, 0);
1349
+ rb_define_method(klass, "enummodule", EnumDescriptor_enummodule, 0);
1350
+ rb_define_method(klass, "file_descriptor", EnumDescriptor_file_descriptor, 0);
1351
+ rb_include_module(klass, rb_mEnumerable);
1352
+ rb_gc_register_address(&cEnumDescriptor);
1353
+ cEnumDescriptor = klass;
1354
+ }
1355
+
1473
1356
  // -----------------------------------------------------------------------------
1474
- // MessageBuilderContext.
1357
+ // FileBuilderContext.
1475
1358
  // -----------------------------------------------------------------------------
1476
1359
 
1477
- DEFINE_CLASS(MessageBuilderContext,
1478
- "Google::Protobuf::Internal::MessageBuilderContext");
1360
+ typedef struct {
1361
+ upb_arena *arena;
1362
+ google_protobuf_FileDescriptorProto* file_proto;
1363
+ VALUE descriptor_pool;
1364
+ } FileBuilderContext;
1479
1365
 
1480
- void MessageBuilderContext_mark(void* _self) {
1481
- MessageBuilderContext* self = _self;
1482
- rb_gc_mark(self->descriptor);
1483
- rb_gc_mark(self->builder);
1366
+ static VALUE cFileBuilderContext = Qnil;
1367
+
1368
+ static void FileBuilderContext_mark(void* _self) {
1369
+ FileBuilderContext* self = _self;
1370
+ rb_gc_mark(self->descriptor_pool);
1484
1371
  }
1485
1372
 
1486
- void MessageBuilderContext_free(void* _self) {
1487
- MessageBuilderContext* self = _self;
1373
+ static void FileBuilderContext_free(void* _self) {
1374
+ FileBuilderContext* self = _self;
1375
+ upb_arena_free(self->arena);
1488
1376
  xfree(self);
1489
1377
  }
1490
1378
 
1491
- VALUE MessageBuilderContext_alloc(VALUE klass) {
1492
- MessageBuilderContext* self = ALLOC(MessageBuilderContext);
1493
- VALUE ret = TypedData_Wrap_Struct(
1494
- klass, &_MessageBuilderContext_type, self);
1495
- self->descriptor = Qnil;
1496
- self->builder = Qnil;
1379
+ static const rb_data_type_t FileBuilderContext_type = {
1380
+ "Google::Protobuf::Internal::FileBuilderContext",
1381
+ {FileBuilderContext_mark, FileBuilderContext_free, NULL},
1382
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY,
1383
+ };
1384
+
1385
+ static FileBuilderContext* ruby_to_FileBuilderContext(VALUE val) {
1386
+ FileBuilderContext* ret;
1387
+ TypedData_Get_Struct(val, FileBuilderContext, &FileBuilderContext_type, ret);
1497
1388
  return ret;
1498
1389
  }
1499
1390
 
1500
- void MessageBuilderContext_register(VALUE module) {
1501
- VALUE klass = rb_define_class_under(
1502
- module, "MessageBuilderContext", rb_cObject);
1503
- rb_define_alloc_func(klass, MessageBuilderContext_alloc);
1504
- rb_define_method(klass, "initialize",
1505
- MessageBuilderContext_initialize, 2);
1506
- rb_define_method(klass, "optional", MessageBuilderContext_optional, -1);
1507
- rb_define_method(klass, "required", MessageBuilderContext_required, -1);
1508
- rb_define_method(klass, "repeated", MessageBuilderContext_repeated, -1);
1509
- rb_define_method(klass, "map", MessageBuilderContext_map, -1);
1510
- rb_define_method(klass, "oneof", MessageBuilderContext_oneof, 1);
1511
- rb_gc_register_address(&cMessageBuilderContext);
1512
- cMessageBuilderContext = klass;
1391
+ static upb_strview FileBuilderContext_strdup2(VALUE _self, const char *str) {
1392
+ FileBuilderContext* self = ruby_to_FileBuilderContext(_self);
1393
+ upb_strview ret;
1394
+ char *data;
1395
+
1396
+ ret.size = strlen(str);
1397
+ data = upb_malloc(upb_arena_alloc(self->arena), ret.size + 1);
1398
+ ret.data = data;
1399
+ memcpy(data, str, ret.size);
1400
+ /* Null-terminate required by rewrite_enum_defaults() above. */
1401
+ data[ret.size] = '\0';
1402
+ return ret;
1403
+ }
1404
+
1405
+ static upb_strview FileBuilderContext_strdup(VALUE _self, VALUE rb_str) {
1406
+ return FileBuilderContext_strdup2(_self, get_str(rb_str));
1407
+ }
1408
+
1409
+ static upb_strview FileBuilderContext_strdup_sym(VALUE _self, VALUE rb_sym) {
1410
+ Check_Type(rb_sym, T_SYMBOL);
1411
+ return FileBuilderContext_strdup(_self, rb_id2str(SYM2ID(rb_sym)));
1412
+ }
1413
+
1414
+ static VALUE FileBuilderContext_alloc(VALUE klass) {
1415
+ FileBuilderContext* self = ALLOC(FileBuilderContext);
1416
+ VALUE ret = TypedData_Wrap_Struct(klass, &FileBuilderContext_type, self);
1417
+ self->arena = upb_arena_new();
1418
+ self->file_proto = google_protobuf_FileDescriptorProto_new(self->arena);
1419
+ self->descriptor_pool = Qnil;
1420
+ return ret;
1513
1421
  }
1514
1422
 
1515
1423
  /*
1516
1424
  * call-seq:
1517
- * MessageBuilderContext.new(desc, builder) => context
1425
+ * FileBuilderContext.new(descriptor_pool) => context
1518
1426
  *
1519
- * Create a new message builder context around the given message descriptor and
1427
+ * Create a new file builder context for the given file descriptor and
1520
1428
  * builder context. This class is intended to serve as a DSL context to be used
1521
1429
  * with #instance_eval.
1522
1430
  */
1523
- VALUE MessageBuilderContext_initialize(VALUE _self,
1524
- VALUE msgdef,
1525
- VALUE builder) {
1526
- DEFINE_SELF(MessageBuilderContext, self, _self);
1527
- self->descriptor = msgdef;
1528
- self->builder = builder;
1529
- return Qnil;
1530
- }
1531
-
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)));
1539
-
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);
1431
+ static VALUE FileBuilderContext_initialize(VALUE _self, VALUE descriptor_pool,
1432
+ VALUE name, VALUE options) {
1433
+ FileBuilderContext* self = ruby_to_FileBuilderContext(_self);
1434
+ self->descriptor_pool = descriptor_pool;
1544
1435
 
1545
- if (type_class != Qnil) {
1546
- Check_Type(type_class, T_STRING);
1436
+ google_protobuf_FileDescriptorProto_set_name(
1437
+ self->file_proto, FileBuilderContext_strdup(_self, name));
1547
1438
 
1548
- // Make it an absolute type name by prepending a dot.
1549
- type_class = rb_str_append(rb_str_new2("."), type_class);
1550
- rb_funcall(fielddef_rb, rb_intern("submsg_name="), 1, type_class);
1551
- }
1439
+ // Default syntax for Ruby is proto3.
1440
+ google_protobuf_FileDescriptorProto_set_syntax(
1441
+ self->file_proto,
1442
+ FileBuilderContext_strdup(_self, rb_str_new2("proto3")));
1552
1443
 
1553
1444
  if (options != Qnil) {
1554
- Check_Type(options, T_HASH);
1445
+ VALUE syntax;
1555
1446
 
1556
- if (rb_funcall(options, rb_intern("key?"), 1,
1557
- ID2SYM(rb_intern("default"))) == Qtrue) {
1558
- Descriptor* msgdef = ruby_to_Descriptor(msgdef_rb);
1559
- if (upb_msgdef_syntax((upb_msgdef*)msgdef->msgdef) == UPB_SYNTAX_PROTO3) {
1560
- rb_raise(rb_eArgError, "Cannot set :default when using proto3 syntax.");
1561
- }
1447
+ Check_Type(options, T_HASH);
1448
+ syntax = rb_hash_lookup2(options, ID2SYM(rb_intern("syntax")), Qnil);
1562
1449
 
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
- }
1450
+ if (syntax != Qnil) {
1451
+ VALUE syntax_str;
1568
1452
 
1569
- rb_funcall(fielddef_rb, rb_intern("default="), 1,
1570
- rb_hash_lookup(options, ID2SYM(rb_intern("default"))));
1453
+ Check_Type(syntax, T_SYMBOL);
1454
+ syntax_str = rb_id2str(SYM2ID(syntax));
1455
+ google_protobuf_FileDescriptorProto_set_syntax(
1456
+ self->file_proto, FileBuilderContext_strdup(_self, syntax_str));
1571
1457
  }
1572
1458
  }
1573
1459
 
1574
- rb_funcall(msgdef_rb, rb_intern("add_field"), 1, fielddef_rb);
1575
- return fielddef_rb;
1460
+ return Qnil;
1576
1461
  }
1577
1462
 
1463
+ static void MessageBuilderContext_add_synthetic_oneofs(VALUE _self);
1464
+
1578
1465
  /*
1579
1466
  * call-seq:
1580
- * MessageBuilderContext.optional(name, type, number, type_class = nil,
1581
- * options = nil)
1467
+ * FileBuilderContext.add_message(name, &block)
1582
1468
  *
1583
- * Defines a new optional field on this message type with the given type, tag
1584
- * number, and type class (for message and enum fields). The type must be a Ruby
1585
- * symbol (as accepted by FieldDescriptor#type=) and the type_class must be a
1586
- * string, if present (as accepted by FieldDescriptor#submsg_name=).
1587
- */
1469
+ * Creates a new, empty descriptor with the given name, and invokes the block in
1470
+ * the context of a MessageBuilderContext on that descriptor. The block can then
1471
+ * call, e.g., MessageBuilderContext#optional and MessageBuilderContext#repeated
1472
+ * methods to define the message fields.
1473
+ *
1474
+ * This is the recommended, idiomatic way to build message definitions.
1475
+ */
1476
+ static VALUE FileBuilderContext_add_message(VALUE _self, VALUE name) {
1477
+ VALUE args[2] = { _self, name };
1478
+ VALUE ctx = rb_class_new_instance(2, args, cMessageBuilderContext);
1479
+ VALUE block = rb_block_proc();
1480
+ rb_funcall_with_block(ctx, rb_intern("instance_eval"), 0, NULL, block);
1481
+ MessageBuilderContext_add_synthetic_oneofs(ctx);
1482
+ return Qnil;
1483
+ }
1484
+
1485
+ /* We have to do some relatively complicated logic here for backward
1486
+ * compatibility.
1487
+ *
1488
+ * In descriptor.proto, messages are nested inside other messages if that is
1489
+ * what the original .proto file looks like. For example, suppose we have this
1490
+ * foo.proto:
1491
+ *
1492
+ * package foo;
1493
+ * message Bar {
1494
+ * message Baz {}
1495
+ * }
1496
+ *
1497
+ * The descriptor for this must look like this:
1498
+ *
1499
+ * file {
1500
+ * name: "test.proto"
1501
+ * package: "foo"
1502
+ * message_type {
1503
+ * name: "Bar"
1504
+ * nested_type {
1505
+ * name: "Baz"
1506
+ * }
1507
+ * }
1508
+ * }
1509
+ *
1510
+ * However, the Ruby generated code has always generated messages in a flat,
1511
+ * non-nested way:
1512
+ *
1513
+ * Google::Protobuf::DescriptorPool.generated_pool.build do
1514
+ * add_message "foo.Bar" do
1515
+ * end
1516
+ * add_message "foo.Bar.Baz" do
1517
+ * end
1518
+ * end
1519
+ *
1520
+ * Here we need to do a translation where we turn this generated code into the
1521
+ * above descriptor. We need to infer that "foo" is the package name, and not
1522
+ * a message itself.
1523
+ *
1524
+ * We delegate to Ruby to compute the transformation, for more concice and
1525
+ * readable code than we can do in C */
1526
+ static void rewrite_names(VALUE _file_builder,
1527
+ google_protobuf_FileDescriptorProto* file_proto) {
1528
+ FileBuilderContext* file_builder = ruby_to_FileBuilderContext(_file_builder);
1529
+ upb_arena *arena = file_builder->arena;
1530
+ // Build params (package, msg_names, enum_names).
1531
+ VALUE package = Qnil;
1532
+ VALUE msg_names = rb_ary_new();
1533
+ VALUE enum_names = rb_ary_new();
1534
+ size_t msg_count, enum_count, i;
1535
+ VALUE new_package, nesting, msg_ents, enum_ents;
1536
+ google_protobuf_DescriptorProto** msgs;
1537
+ google_protobuf_EnumDescriptorProto** enums;
1538
+
1539
+ if (google_protobuf_FileDescriptorProto_has_package(file_proto)) {
1540
+ upb_strview package_str =
1541
+ google_protobuf_FileDescriptorProto_package(file_proto);
1542
+ package = rb_str_new(package_str.data, package_str.size);
1543
+ }
1544
+
1545
+ msgs = google_protobuf_FileDescriptorProto_mutable_message_type(file_proto,
1546
+ &msg_count);
1547
+ for (i = 0; i < msg_count; i++) {
1548
+ upb_strview name = google_protobuf_DescriptorProto_name(msgs[i]);
1549
+ rb_ary_push(msg_names, rb_str_new(name.data, name.size));
1550
+ }
1551
+
1552
+ enums = google_protobuf_FileDescriptorProto_mutable_enum_type(file_proto,
1553
+ &enum_count);
1554
+ for (i = 0; i < enum_count; i++) {
1555
+ upb_strview name = google_protobuf_EnumDescriptorProto_name(enums[i]);
1556
+ rb_ary_push(enum_names, rb_str_new(name.data, name.size));
1557
+ }
1558
+
1559
+ {
1560
+ // Call Ruby code to calculate package name and nesting.
1561
+ VALUE args[3] = { package, msg_names, enum_names };
1562
+ VALUE internal = rb_eval_string("Google::Protobuf::Internal");
1563
+ VALUE ret = rb_funcallv(internal, rb_intern("fixup_descriptor"), 3, args);
1564
+
1565
+ new_package = rb_ary_entry(ret, 0);
1566
+ nesting = rb_ary_entry(ret, 1);
1567
+ }
1568
+
1569
+ // Rewrite package and names.
1570
+ if (new_package != Qnil) {
1571
+ upb_strview new_package_str =
1572
+ FileBuilderContext_strdup(_file_builder, new_package);
1573
+ google_protobuf_FileDescriptorProto_set_package(file_proto,
1574
+ new_package_str);
1575
+ }
1576
+
1577
+ for (i = 0; i < msg_count; i++) {
1578
+ upb_strview name = google_protobuf_DescriptorProto_name(msgs[i]);
1579
+ remove_path(&name);
1580
+ google_protobuf_DescriptorProto_set_name(msgs[i], name);
1581
+ }
1582
+
1583
+ for (i = 0; i < enum_count; i++) {
1584
+ upb_strview name = google_protobuf_EnumDescriptorProto_name(enums[i]);
1585
+ remove_path(&name);
1586
+ google_protobuf_EnumDescriptorProto_set_name(enums[i], name);
1587
+ }
1588
+
1589
+ // Rewrite nesting.
1590
+ msg_ents = rb_hash_aref(nesting, ID2SYM(rb_intern("msgs")));
1591
+ enum_ents = rb_hash_aref(nesting, ID2SYM(rb_intern("enums")));
1592
+
1593
+ Check_Type(msg_ents, T_ARRAY);
1594
+ Check_Type(enum_ents, T_ARRAY);
1595
+
1596
+ for (i = 0; i < (size_t)RARRAY_LEN(msg_ents); i++) {
1597
+ VALUE msg_ent = rb_ary_entry(msg_ents, i);
1598
+ VALUE pos = rb_hash_aref(msg_ent, ID2SYM(rb_intern("pos")));
1599
+ msgs[i] = msgs[NUM2INT(pos)];
1600
+ rewrite_nesting(msg_ent, msgs[i], msgs, enums, arena);
1601
+ }
1602
+
1603
+ for (i = 0; i < (size_t)RARRAY_LEN(enum_ents); i++) {
1604
+ VALUE enum_pos = rb_ary_entry(enum_ents, i);
1605
+ enums[i] = enums[NUM2INT(enum_pos)];
1606
+ }
1607
+
1608
+ google_protobuf_FileDescriptorProto_resize_message_type(
1609
+ file_proto, RARRAY_LEN(msg_ents), arena);
1610
+ google_protobuf_FileDescriptorProto_resize_enum_type(
1611
+ file_proto, RARRAY_LEN(enum_ents), arena);
1612
+ }
1613
+
1614
+ /*
1615
+ * call-seq:
1616
+ * FileBuilderContext.add_enum(name, &block)
1617
+ *
1618
+ * Creates a new, empty enum descriptor with the given name, and invokes the
1619
+ * block in the context of an EnumBuilderContext on that descriptor. The block
1620
+ * can then call EnumBuilderContext#add_value to define the enum values.
1621
+ *
1622
+ * This is the recommended, idiomatic way to build enum definitions.
1623
+ */
1624
+ static VALUE FileBuilderContext_add_enum(VALUE _self, VALUE name) {
1625
+ VALUE args[2] = { _self, name };
1626
+ VALUE ctx = rb_class_new_instance(2, args, cEnumBuilderContext);
1627
+ VALUE block = rb_block_proc();
1628
+ rb_funcall_with_block(ctx, rb_intern("instance_eval"), 0, NULL, block);
1629
+ return Qnil;
1630
+ }
1631
+
1632
+ static void FileBuilderContext_build(VALUE _self) {
1633
+ FileBuilderContext* self = ruby_to_FileBuilderContext(_self);
1634
+ DescriptorPool* pool = ruby_to_DescriptorPool(self->descriptor_pool);
1635
+ upb_status status;
1636
+
1637
+ rewrite_enum_defaults(pool->symtab, self->file_proto);
1638
+ rewrite_names(_self, self->file_proto);
1639
+
1640
+ upb_status_clear(&status);
1641
+ if (!upb_symtab_addfile(pool->symtab, self->file_proto, &status)) {
1642
+ rb_raise(cTypeError, "Unable to add defs to DescriptorPool: %s",
1643
+ upb_status_errmsg(&status));
1644
+ }
1645
+ }
1646
+
1647
+ static void FileBuilderContext_register(VALUE module) {
1648
+ VALUE klass = rb_define_class_under(module, "FileBuilderContext", rb_cObject);
1649
+ rb_define_alloc_func(klass, FileBuilderContext_alloc);
1650
+ rb_define_method(klass, "initialize", FileBuilderContext_initialize, 3);
1651
+ rb_define_method(klass, "add_message", FileBuilderContext_add_message, 1);
1652
+ rb_define_method(klass, "add_enum", FileBuilderContext_add_enum, 1);
1653
+ rb_gc_register_address(&cFileBuilderContext);
1654
+ cFileBuilderContext = klass;
1655
+ }
1656
+
1657
+ // -----------------------------------------------------------------------------
1658
+ // MessageBuilderContext.
1659
+ // -----------------------------------------------------------------------------
1660
+
1661
+ typedef struct {
1662
+ google_protobuf_DescriptorProto* msg_proto;
1663
+ VALUE file_builder;
1664
+ } MessageBuilderContext;
1665
+
1666
+ static VALUE cMessageBuilderContext = Qnil;
1667
+
1668
+ static void MessageBuilderContext_mark(void* _self) {
1669
+ MessageBuilderContext* self = _self;
1670
+ rb_gc_mark(self->file_builder);
1671
+ }
1672
+
1673
+ static const rb_data_type_t MessageBuilderContext_type = {
1674
+ "Google::Protobuf::Internal::MessageBuilderContext",
1675
+ {MessageBuilderContext_mark, RUBY_DEFAULT_FREE, NULL},
1676
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY,
1677
+ };
1678
+
1679
+ static MessageBuilderContext* ruby_to_MessageBuilderContext(VALUE val) {
1680
+ MessageBuilderContext* ret;
1681
+ TypedData_Get_Struct(val, MessageBuilderContext, &MessageBuilderContext_type,
1682
+ ret);
1683
+ return ret;
1684
+ }
1685
+
1686
+ static VALUE MessageBuilderContext_alloc(VALUE klass) {
1687
+ MessageBuilderContext* self = ALLOC(MessageBuilderContext);
1688
+ VALUE ret = TypedData_Wrap_Struct(klass, &MessageBuilderContext_type, self);
1689
+ self->file_builder = Qnil;
1690
+ return ret;
1691
+ }
1692
+
1693
+ /*
1694
+ * call-seq:
1695
+ * MessageBuilderContext.new(file_builder, name) => context
1696
+ *
1697
+ * Create a new message builder context around the given message descriptor and
1698
+ * builder context. This class is intended to serve as a DSL context to be used
1699
+ * with #instance_eval.
1700
+ */
1701
+ static VALUE MessageBuilderContext_initialize(VALUE _self, VALUE _file_builder,
1702
+ VALUE name) {
1703
+ MessageBuilderContext* self = ruby_to_MessageBuilderContext(_self);
1704
+ FileBuilderContext* file_builder = ruby_to_FileBuilderContext(_file_builder);
1705
+ google_protobuf_FileDescriptorProto* file_proto = file_builder->file_proto;
1706
+
1707
+ self->file_builder = _file_builder;
1708
+ self->msg_proto = google_protobuf_FileDescriptorProto_add_message_type(
1709
+ file_proto, file_builder->arena);
1710
+
1711
+ google_protobuf_DescriptorProto_set_name(
1712
+ self->msg_proto, FileBuilderContext_strdup(_file_builder, name));
1713
+
1714
+ return Qnil;
1715
+ }
1716
+
1717
+ static void msgdef_add_field(VALUE msgbuilder_rb, upb_label_t label, VALUE name,
1718
+ VALUE type, VALUE number, VALUE type_class,
1719
+ VALUE options, int oneof_index,
1720
+ bool proto3_optional) {
1721
+ MessageBuilderContext* self = ruby_to_MessageBuilderContext(msgbuilder_rb);
1722
+ FileBuilderContext* file_context =
1723
+ ruby_to_FileBuilderContext(self->file_builder);
1724
+ google_protobuf_FieldDescriptorProto* field_proto;
1725
+ VALUE name_str;
1726
+
1727
+ field_proto = google_protobuf_DescriptorProto_add_field(self->msg_proto,
1728
+ file_context->arena);
1729
+
1730
+ Check_Type(name, T_SYMBOL);
1731
+ name_str = rb_id2str(SYM2ID(name));
1732
+
1733
+ google_protobuf_FieldDescriptorProto_set_name(
1734
+ field_proto, FileBuilderContext_strdup(self->file_builder, name_str));
1735
+ google_protobuf_FieldDescriptorProto_set_number(field_proto, NUM2INT(number));
1736
+ google_protobuf_FieldDescriptorProto_set_label(field_proto, (int)label);
1737
+ google_protobuf_FieldDescriptorProto_set_type(
1738
+ field_proto, (int)ruby_to_descriptortype(type));
1739
+
1740
+ if (proto3_optional) {
1741
+ google_protobuf_FieldDescriptorProto_set_proto3_optional(field_proto, true);
1742
+ }
1743
+
1744
+ if (type_class != Qnil) {
1745
+ Check_Type(type_class, T_STRING);
1746
+
1747
+ // Make it an absolute type name by prepending a dot.
1748
+ type_class = rb_str_append(rb_str_new2("."), type_class);
1749
+ google_protobuf_FieldDescriptorProto_set_type_name(
1750
+ field_proto, FileBuilderContext_strdup(self->file_builder, type_class));
1751
+ }
1752
+
1753
+ if (options != Qnil) {
1754
+ Check_Type(options, T_HASH);
1755
+
1756
+ if (rb_funcall(options, rb_intern("key?"), 1,
1757
+ ID2SYM(rb_intern("default"))) == Qtrue) {
1758
+ VALUE default_value =
1759
+ rb_hash_lookup(options, ID2SYM(rb_intern("default")));
1760
+
1761
+ /* Call #to_s since all defaults are strings in the descriptor. */
1762
+ default_value = rb_funcall(default_value, rb_intern("to_s"), 0);
1763
+
1764
+ google_protobuf_FieldDescriptorProto_set_default_value(
1765
+ field_proto,
1766
+ FileBuilderContext_strdup(self->file_builder, default_value));
1767
+ }
1768
+
1769
+ if (rb_funcall(options, rb_intern("key?"), 1,
1770
+ ID2SYM(rb_intern("json_name"))) == Qtrue) {
1771
+ VALUE json_name =
1772
+ rb_hash_lookup(options, ID2SYM(rb_intern("json_name")));
1773
+
1774
+ google_protobuf_FieldDescriptorProto_set_json_name(
1775
+ field_proto,
1776
+ FileBuilderContext_strdup(self->file_builder, json_name));
1777
+ }
1778
+ }
1779
+
1780
+ if (oneof_index >= 0) {
1781
+ google_protobuf_FieldDescriptorProto_set_oneof_index(field_proto,
1782
+ oneof_index);
1783
+ }
1784
+ }
1785
+
1786
+ #if RUBY_API_VERSION_CODE >= 20700
1787
+ static VALUE make_mapentry(VALUE _message_builder, VALUE types, int argc,
1788
+ const VALUE* argv, VALUE blockarg) {
1789
+ (void)blockarg;
1790
+ #else
1791
+ static VALUE make_mapentry(VALUE _message_builder, VALUE types, int argc,
1792
+ VALUE* argv) {
1793
+ #endif
1794
+ MessageBuilderContext* message_builder =
1795
+ ruby_to_MessageBuilderContext(_message_builder);
1796
+ VALUE type_class = rb_ary_entry(types, 2);
1797
+ FileBuilderContext* file_context =
1798
+ ruby_to_FileBuilderContext(message_builder->file_builder);
1799
+ google_protobuf_MessageOptions* options =
1800
+ google_protobuf_DescriptorProto_mutable_options(
1801
+ message_builder->msg_proto, file_context->arena);
1802
+
1803
+ google_protobuf_MessageOptions_set_map_entry(options, true);
1804
+
1805
+ // optional <type> key = 1;
1806
+ rb_funcall(_message_builder, rb_intern("optional"), 3,
1807
+ ID2SYM(rb_intern("key")), rb_ary_entry(types, 0), INT2NUM(1));
1808
+
1809
+ // optional <type> value = 2;
1810
+ if (type_class == Qnil) {
1811
+ rb_funcall(_message_builder, rb_intern("optional"), 3,
1812
+ ID2SYM(rb_intern("value")), rb_ary_entry(types, 1), INT2NUM(2));
1813
+ } else {
1814
+ rb_funcall(_message_builder, rb_intern("optional"), 4,
1815
+ ID2SYM(rb_intern("value")), rb_ary_entry(types, 1), INT2NUM(2),
1816
+ type_class);
1817
+ }
1818
+
1819
+ return Qnil;
1820
+ }
1821
+
1822
+ /*
1823
+ * call-seq:
1824
+ * MessageBuilderContext.optional(name, type, number, type_class = nil,
1825
+ * options = nil)
1826
+ *
1827
+ * Defines a new optional field on this message type with the given type, tag
1828
+ * number, and type class (for message and enum fields). The type must be a Ruby
1829
+ * symbol (as accepted by FieldDescriptor#type=) and the type_class must be a
1830
+ * string, if present (as accepted by FieldDescriptor#submsg_name=).
1831
+ */
1588
1832
  VALUE MessageBuilderContext_optional(int argc, VALUE* argv, VALUE _self) {
1589
- DEFINE_SELF(MessageBuilderContext, self, _self);
1590
1833
  VALUE name, type, number;
1591
1834
  VALUE type_class, options = Qnil;
1592
1835
 
@@ -1599,8 +1842,41 @@ VALUE MessageBuilderContext_optional(int argc, VALUE* argv, VALUE _self) {
1599
1842
  type_class = Qnil;
1600
1843
  }
1601
1844
 
1602
- return msgdef_add_field(self->descriptor, "optional",
1603
- name, type, number, type_class, options);
1845
+ msgdef_add_field(_self, UPB_LABEL_OPTIONAL, name, type, number, type_class,
1846
+ options, -1, false);
1847
+
1848
+ return Qnil;
1849
+ }
1850
+
1851
+ /*
1852
+ * call-seq:
1853
+ * MessageBuilderContext.proto3_optional(name, type, number,
1854
+ * type_class = nil, options = nil)
1855
+ *
1856
+ * Defines a true proto3 optional field (that tracks presence) on this message
1857
+ * type with the given type, tag number, and type class (for message and enum
1858
+ * fields). The type must be a Ruby symbol (as accepted by
1859
+ * FieldDescriptor#type=) and the type_class must be a string, if present (as
1860
+ * accepted by FieldDescriptor#submsg_name=).
1861
+ */
1862
+ static VALUE MessageBuilderContext_proto3_optional(int argc, VALUE* argv,
1863
+ VALUE _self) {
1864
+ VALUE name, type, number;
1865
+ VALUE type_class, options = Qnil;
1866
+
1867
+ rb_scan_args(argc, argv, "32", &name, &type, &number, &type_class, &options);
1868
+
1869
+ // Allow passing (name, type, number, options) or
1870
+ // (name, type, number, type_class, options)
1871
+ if (argc == 4 && RB_TYPE_P(type_class, T_HASH)) {
1872
+ options = type_class;
1873
+ type_class = Qnil;
1874
+ }
1875
+
1876
+ msgdef_add_field(_self, UPB_LABEL_OPTIONAL, name, type, number, type_class,
1877
+ options, -1, true);
1878
+
1879
+ return Qnil;
1604
1880
  }
1605
1881
 
1606
1882
  /*
@@ -1617,8 +1893,8 @@ VALUE MessageBuilderContext_optional(int argc, VALUE* argv, VALUE _self) {
1617
1893
  * completeness. Any attempt to add a message type with required fields to a
1618
1894
  * pool will currently result in an error.
1619
1895
  */
1620
- VALUE MessageBuilderContext_required(int argc, VALUE* argv, VALUE _self) {
1621
- DEFINE_SELF(MessageBuilderContext, self, _self);
1896
+ static VALUE MessageBuilderContext_required(int argc, VALUE* argv,
1897
+ VALUE _self) {
1622
1898
  VALUE name, type, number;
1623
1899
  VALUE type_class, options = Qnil;
1624
1900
 
@@ -1631,8 +1907,10 @@ VALUE MessageBuilderContext_required(int argc, VALUE* argv, VALUE _self) {
1631
1907
  type_class = Qnil;
1632
1908
  }
1633
1909
 
1634
- return msgdef_add_field(self->descriptor, "required",
1635
- name, type, number, type_class, options);
1910
+ msgdef_add_field(_self, UPB_LABEL_REQUIRED, name, type, number, type_class,
1911
+ options, -1, false);
1912
+
1913
+ return Qnil;
1636
1914
  }
1637
1915
 
1638
1916
  /*
@@ -1644,20 +1922,24 @@ VALUE MessageBuilderContext_required(int argc, VALUE* argv, VALUE _self) {
1644
1922
  * symbol (as accepted by FieldDescriptor#type=) and the type_class must be a
1645
1923
  * string, if present (as accepted by FieldDescriptor#submsg_name=).
1646
1924
  */
1647
- VALUE MessageBuilderContext_repeated(int argc, VALUE* argv, VALUE _self) {
1648
- DEFINE_SELF(MessageBuilderContext, self, _self);
1649
- VALUE name, type, number, type_class;
1925
+ static VALUE MessageBuilderContext_repeated(int argc, VALUE* argv,
1926
+ VALUE _self) {
1927
+ VALUE name, type, number;
1928
+ VALUE type_class, options = Qnil;
1650
1929
 
1651
- if (argc < 3) {
1652
- rb_raise(rb_eArgError, "Expected at least 3 arguments.");
1930
+ rb_scan_args(argc, argv, "32", &name, &type, &number, &type_class, &options);
1931
+
1932
+ // Allow passing (name, type, number, options) or
1933
+ // (name, type, number, type_class, options)
1934
+ if (argc == 4 && RB_TYPE_P(type_class, T_HASH)) {
1935
+ options = type_class;
1936
+ type_class = Qnil;
1653
1937
  }
1654
- name = argv[0];
1655
- type = argv[1];
1656
- number = argv[2];
1657
- type_class = (argc > 3) ? argv[3] : Qnil;
1658
1938
 
1659
- return msgdef_add_field(self->descriptor, "repeated",
1660
- name, type, number, type_class, Qnil);
1939
+ msgdef_add_field(_self, UPB_LABEL_REPEATED, name, type, number, type_class,
1940
+ options, -1, false);
1941
+
1942
+ return Qnil;
1661
1943
  }
1662
1944
 
1663
1945
  /*
@@ -1672,10 +1954,12 @@ VALUE MessageBuilderContext_repeated(int argc, VALUE* argv, VALUE _self) {
1672
1954
  * type_class must be a string, if present (as accepted by
1673
1955
  * FieldDescriptor#submsg_name=).
1674
1956
  */
1675
- VALUE MessageBuilderContext_map(int argc, VALUE* argv, VALUE _self) {
1676
- DEFINE_SELF(MessageBuilderContext, self, _self);
1957
+ static VALUE MessageBuilderContext_map(int argc, VALUE* argv, VALUE _self) {
1958
+ MessageBuilderContext* self = ruby_to_MessageBuilderContext(_self);
1677
1959
  VALUE name, key_type, value_type, number, type_class;
1678
- VALUE mapentry_desc, mapentry_desc_name;
1960
+ VALUE mapentry_desc_name;
1961
+ FileBuilderContext* file_builder;
1962
+ upb_strview msg_name;
1679
1963
 
1680
1964
  if (argc < 4) {
1681
1965
  rb_raise(rb_eArgError, "Expected at least 4 arguments.");
@@ -1698,77 +1982,36 @@ VALUE MessageBuilderContext_map(int argc, VALUE* argv, VALUE _self) {
1698
1982
  "type.");
1699
1983
  }
1700
1984
 
1701
- Descriptor* descriptor = ruby_to_Descriptor(self->descriptor);
1702
- if (upb_msgdef_syntax(descriptor->msgdef) == UPB_SYNTAX_PROTO2) {
1703
- rb_raise(rb_eArgError,
1704
- "Cannot add a native map field using proto2 syntax.");
1705
- }
1985
+ file_builder = ruby_to_FileBuilderContext(self->file_builder);
1706
1986
 
1707
1987
  // Create a new message descriptor for the map entry message, and create a
1708
1988
  // 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);
1989
+ msg_name = google_protobuf_DescriptorProto_name(self->msg_proto);
1990
+ mapentry_desc_name = rb_str_new(msg_name.data, msg_name.size);
1713
1991
  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);
1992
+ mapentry_desc_name =
1993
+ rb_str_cat2(mapentry_desc_name, rb_id2name(SYM2ID(name)));
1717
1994
 
1718
1995
  {
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);
1996
+ // message <msgname>_MapEntry_ { /* ... */ }
1997
+ VALUE args[1] = {mapentry_desc_name};
1998
+ VALUE types = rb_ary_new3(3, key_type, value_type, type_class);
1999
+ rb_block_call(self->file_builder, rb_intern("add_message"), 1, args,
2000
+ make_mapentry, types);
1724
2001
  }
1725
2002
 
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);
2003
+ // If this file is in a package, we need to qualify the map entry type.
2004
+ if (google_protobuf_FileDescriptorProto_has_package(file_builder->file_proto)) {
2005
+ upb_strview package_view =
2006
+ google_protobuf_FileDescriptorProto_package(file_builder->file_proto);
2007
+ VALUE package = rb_str_new(package_view.data, package_view.size);
2008
+ package = rb_str_cat2(package, ".");
2009
+ mapentry_desc_name = rb_str_concat(package, mapentry_desc_name);
1734
2010
  }
1735
2011
 
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);
1749
- }
1750
-
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);
1756
- }
1757
-
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
- }
2012
+ // repeated MapEntry <name> = <number>;
2013
+ rb_funcall(_self, rb_intern("repeated"), 4, name,
2014
+ ID2SYM(rb_intern("message")), number, mapentry_desc_name);
1772
2015
 
1773
2016
  return Qnil;
1774
2017
  }
@@ -1784,72 +2027,149 @@ VALUE MessageBuilderContext_map(int argc, VALUE* argv, VALUE _self) {
1784
2027
  *
1785
2028
  * This is the recommended, idiomatic way to build oneof definitions.
1786
2029
  */
1787
- VALUE MessageBuilderContext_oneof(VALUE _self, VALUE name) {
1788
- 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);
2030
+ static VALUE MessageBuilderContext_oneof(VALUE _self, VALUE name) {
2031
+ MessageBuilderContext* self = ruby_to_MessageBuilderContext(_self);
2032
+ size_t oneof_count;
2033
+ FileBuilderContext* file_context =
2034
+ ruby_to_FileBuilderContext(self->file_builder);
2035
+ google_protobuf_OneofDescriptorProto* oneof_proto;
2036
+
2037
+ // Existing oneof_count becomes oneof_index.
2038
+ google_protobuf_DescriptorProto_oneof_decl(self->msg_proto, &oneof_count);
2039
+
2040
+ // Create oneof_proto and set its name.
2041
+ oneof_proto = google_protobuf_DescriptorProto_add_oneof_decl(
2042
+ self->msg_proto, file_context->arena);
2043
+ google_protobuf_OneofDescriptorProto_set_name(
2044
+ oneof_proto, FileBuilderContext_strdup_sym(self->file_builder, name));
2045
+
2046
+ // Evaluate the block with the builder as argument.
2047
+ {
2048
+ VALUE args[2] = { INT2NUM(oneof_count), _self };
2049
+ VALUE ctx = rb_class_new_instance(2, args, cOneofBuilderContext);
2050
+ VALUE block = rb_block_proc();
2051
+ rb_funcall_with_block(ctx, rb_intern("instance_eval"), 0, NULL, block);
2052
+ }
1797
2053
 
1798
2054
  return Qnil;
1799
2055
  }
1800
2056
 
2057
+ static void MessageBuilderContext_add_synthetic_oneofs(VALUE _self) {
2058
+ MessageBuilderContext* self = ruby_to_MessageBuilderContext(_self);
2059
+ FileBuilderContext* file_context =
2060
+ ruby_to_FileBuilderContext(self->file_builder);
2061
+ size_t field_count, oneof_count;
2062
+ google_protobuf_FieldDescriptorProto** fields =
2063
+ google_protobuf_DescriptorProto_mutable_field(self->msg_proto, &field_count);
2064
+ const google_protobuf_OneofDescriptorProto*const* oneofs =
2065
+ google_protobuf_DescriptorProto_oneof_decl(self->msg_proto, &oneof_count);
2066
+ VALUE names = rb_hash_new();
2067
+ VALUE underscore = rb_str_new2("_");
2068
+ size_t i;
2069
+
2070
+ // We have to build a set of all names, to ensure that synthetic oneofs are
2071
+ // not creating conflicts.
2072
+ for (i = 0; i < field_count; i++) {
2073
+ upb_strview name = google_protobuf_FieldDescriptorProto_name(fields[i]);
2074
+ rb_hash_aset(names, rb_str_new(name.data, name.size), Qtrue);
2075
+ }
2076
+ for (i = 0; i < oneof_count; i++) {
2077
+ upb_strview name = google_protobuf_OneofDescriptorProto_name(oneofs[i]);
2078
+ rb_hash_aset(names, rb_str_new(name.data, name.size), Qtrue);
2079
+ }
2080
+
2081
+ for (i = 0; i < field_count; i++) {
2082
+ google_protobuf_OneofDescriptorProto* oneof_proto;
2083
+ VALUE oneof_name;
2084
+ upb_strview field_name;
2085
+
2086
+ if (!google_protobuf_FieldDescriptorProto_proto3_optional(fields[i])) {
2087
+ continue;
2088
+ }
2089
+
2090
+ // Prepend '_' until we are no longer conflicting.
2091
+ field_name = google_protobuf_FieldDescriptorProto_name(fields[i]);
2092
+ oneof_name = rb_str_new(field_name.data, field_name.size);
2093
+ while (rb_hash_lookup(names, oneof_name) != Qnil) {
2094
+ oneof_name = rb_str_plus(underscore, oneof_name);
2095
+ }
2096
+
2097
+ rb_hash_aset(names, oneof_name, Qtrue);
2098
+ google_protobuf_FieldDescriptorProto_set_oneof_index(fields[i],
2099
+ oneof_count++);
2100
+ oneof_proto = google_protobuf_DescriptorProto_add_oneof_decl(
2101
+ self->msg_proto, file_context->arena);
2102
+ google_protobuf_OneofDescriptorProto_set_name(
2103
+ oneof_proto, FileBuilderContext_strdup(self->file_builder, oneof_name));
2104
+ }
2105
+ }
2106
+
2107
+ static void MessageBuilderContext_register(VALUE module) {
2108
+ VALUE klass = rb_define_class_under(
2109
+ module, "MessageBuilderContext", rb_cObject);
2110
+ rb_define_alloc_func(klass, MessageBuilderContext_alloc);
2111
+ rb_define_method(klass, "initialize",
2112
+ MessageBuilderContext_initialize, 2);
2113
+ rb_define_method(klass, "optional", MessageBuilderContext_optional, -1);
2114
+ rb_define_method(klass, "proto3_optional", MessageBuilderContext_proto3_optional, -1);
2115
+ rb_define_method(klass, "required", MessageBuilderContext_required, -1);
2116
+ rb_define_method(klass, "repeated", MessageBuilderContext_repeated, -1);
2117
+ rb_define_method(klass, "map", MessageBuilderContext_map, -1);
2118
+ rb_define_method(klass, "oneof", MessageBuilderContext_oneof, 1);
2119
+ rb_gc_register_address(&cMessageBuilderContext);
2120
+ cMessageBuilderContext = klass;
2121
+ }
2122
+
1801
2123
  // -----------------------------------------------------------------------------
1802
2124
  // OneofBuilderContext.
1803
2125
  // -----------------------------------------------------------------------------
1804
2126
 
1805
- DEFINE_CLASS(OneofBuilderContext,
1806
- "Google::Protobuf::Internal::OneofBuilderContext");
2127
+ typedef struct {
2128
+ int oneof_index;
2129
+ VALUE message_builder;
2130
+ } OneofBuilderContext;
2131
+
2132
+ static VALUE cOneofBuilderContext = Qnil;
1807
2133
 
1808
2134
  void OneofBuilderContext_mark(void* _self) {
1809
2135
  OneofBuilderContext* self = _self;
1810
- rb_gc_mark(self->descriptor);
1811
- rb_gc_mark(self->builder);
2136
+ rb_gc_mark(self->message_builder);
1812
2137
  }
1813
2138
 
1814
- void OneofBuilderContext_free(void* _self) {
1815
- OneofBuilderContext* self = _self;
1816
- xfree(self);
1817
- }
2139
+ static const rb_data_type_t OneofBuilderContext_type = {
2140
+ "Google::Protobuf::Internal::OneofBuilderContext",
2141
+ {OneofBuilderContext_mark, RUBY_DEFAULT_FREE, NULL},
2142
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY,
2143
+ };
1818
2144
 
1819
- VALUE OneofBuilderContext_alloc(VALUE klass) {
1820
- OneofBuilderContext* self = ALLOC(OneofBuilderContext);
1821
- VALUE ret = TypedData_Wrap_Struct(
1822
- klass, &_OneofBuilderContext_type, self);
1823
- self->descriptor = Qnil;
1824
- self->builder = Qnil;
2145
+ static OneofBuilderContext* ruby_to_OneofBuilderContext(VALUE val) {
2146
+ OneofBuilderContext* ret;
2147
+ TypedData_Get_Struct(val, OneofBuilderContext, &OneofBuilderContext_type,
2148
+ ret);
1825
2149
  return ret;
1826
2150
  }
1827
2151
 
1828
- void OneofBuilderContext_register(VALUE module) {
1829
- VALUE klass = rb_define_class_under(
1830
- module, "OneofBuilderContext", rb_cObject);
1831
- rb_define_alloc_func(klass, OneofBuilderContext_alloc);
1832
- rb_define_method(klass, "initialize",
1833
- OneofBuilderContext_initialize, 2);
1834
- rb_define_method(klass, "optional", OneofBuilderContext_optional, -1);
1835
- rb_gc_register_address(&cOneofBuilderContext);
1836
- cOneofBuilderContext = klass;
2152
+ static VALUE OneofBuilderContext_alloc(VALUE klass) {
2153
+ OneofBuilderContext* self = ALLOC(OneofBuilderContext);
2154
+ VALUE ret = TypedData_Wrap_Struct(klass, &OneofBuilderContext_type, self);
2155
+ self->oneof_index = 0;
2156
+ self->message_builder = Qnil;
2157
+ return ret;
1837
2158
  }
1838
2159
 
1839
2160
  /*
1840
2161
  * call-seq:
1841
- * OneofBuilderContext.new(desc, builder) => context
2162
+ * OneofBuilderContext.new(oneof_index, message_builder) => context
1842
2163
  *
1843
2164
  * Create a new oneof builder context around the given oneof descriptor and
1844
2165
  * builder context. This class is intended to serve as a DSL context to be used
1845
2166
  * with #instance_eval.
1846
2167
  */
1847
- VALUE OneofBuilderContext_initialize(VALUE _self,
1848
- VALUE oneofdef,
1849
- VALUE builder) {
1850
- DEFINE_SELF(OneofBuilderContext, self, _self);
1851
- self->descriptor = oneofdef;
1852
- self->builder = builder;
2168
+ static VALUE OneofBuilderContext_initialize(VALUE _self, VALUE oneof_index,
2169
+ VALUE message_builder) {
2170
+ OneofBuilderContext* self = ruby_to_OneofBuilderContext(_self);
2171
+ self->oneof_index = NUM2INT(oneof_index);
2172
+ self->message_builder = message_builder;
1853
2173
  return Qnil;
1854
2174
  }
1855
2175
 
@@ -1863,69 +2183,86 @@ VALUE OneofBuilderContext_initialize(VALUE _self,
1863
2183
  * (as accepted by FieldDescriptor#type=) and the type_class must be a string,
1864
2184
  * if present (as accepted by FieldDescriptor#submsg_name=).
1865
2185
  */
1866
- VALUE OneofBuilderContext_optional(int argc, VALUE* argv, VALUE _self) {
1867
- DEFINE_SELF(OneofBuilderContext, self, _self);
2186
+ static VALUE OneofBuilderContext_optional(int argc, VALUE* argv, VALUE _self) {
2187
+ OneofBuilderContext* self = ruby_to_OneofBuilderContext(_self);
1868
2188
  VALUE name, type, number;
1869
2189
  VALUE type_class, options = Qnil;
1870
2190
 
1871
2191
  rb_scan_args(argc, argv, "32", &name, &type, &number, &type_class, &options);
1872
2192
 
1873
- return msgdef_add_field(self->descriptor, "optional",
1874
- name, type, number, type_class, options);
2193
+ msgdef_add_field(self->message_builder, UPB_LABEL_OPTIONAL, name, type,
2194
+ number, type_class, options, self->oneof_index, false);
2195
+
2196
+ return Qnil;
2197
+ }
2198
+
2199
+ static void OneofBuilderContext_register(VALUE module) {
2200
+ VALUE klass = rb_define_class_under(
2201
+ module, "OneofBuilderContext", rb_cObject);
2202
+ rb_define_alloc_func(klass, OneofBuilderContext_alloc);
2203
+ rb_define_method(klass, "initialize",
2204
+ OneofBuilderContext_initialize, 2);
2205
+ rb_define_method(klass, "optional", OneofBuilderContext_optional, -1);
2206
+ rb_gc_register_address(&cOneofBuilderContext);
2207
+ cOneofBuilderContext = klass;
1875
2208
  }
1876
2209
 
1877
2210
  // -----------------------------------------------------------------------------
1878
2211
  // EnumBuilderContext.
1879
2212
  // -----------------------------------------------------------------------------
1880
2213
 
1881
- DEFINE_CLASS(EnumBuilderContext,
1882
- "Google::Protobuf::Internal::EnumBuilderContext");
2214
+ typedef struct {
2215
+ google_protobuf_EnumDescriptorProto* enum_proto;
2216
+ VALUE file_builder;
2217
+ } EnumBuilderContext;
2218
+
2219
+ static VALUE cEnumBuilderContext = Qnil;
1883
2220
 
1884
2221
  void EnumBuilderContext_mark(void* _self) {
1885
2222
  EnumBuilderContext* self = _self;
1886
- rb_gc_mark(self->enumdesc);
2223
+ rb_gc_mark(self->file_builder);
1887
2224
  }
1888
2225
 
1889
- void EnumBuilderContext_free(void* _self) {
1890
- EnumBuilderContext* self = _self;
1891
- xfree(self);
1892
- }
2226
+ static const rb_data_type_t EnumBuilderContext_type = {
2227
+ "Google::Protobuf::Internal::EnumBuilderContext",
2228
+ {EnumBuilderContext_mark, RUBY_DEFAULT_FREE, NULL},
2229
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY,
2230
+ };
1893
2231
 
1894
- VALUE EnumBuilderContext_alloc(VALUE klass) {
1895
- EnumBuilderContext* self = ALLOC(EnumBuilderContext);
1896
- VALUE ret = TypedData_Wrap_Struct(
1897
- klass, &_EnumBuilderContext_type, self);
1898
- self->enumdesc = Qnil;
2232
+ static EnumBuilderContext* ruby_to_EnumBuilderContext(VALUE val) {
2233
+ EnumBuilderContext* ret;
2234
+ TypedData_Get_Struct(val, EnumBuilderContext, &EnumBuilderContext_type, ret);
1899
2235
  return ret;
1900
2236
  }
1901
2237
 
1902
- void EnumBuilderContext_register(VALUE module) {
1903
- VALUE klass = rb_define_class_under(
1904
- module, "EnumBuilderContext", rb_cObject);
1905
- rb_define_alloc_func(klass, EnumBuilderContext_alloc);
1906
- rb_define_method(klass, "initialize",
1907
- EnumBuilderContext_initialize, 1);
1908
- rb_define_method(klass, "value", EnumBuilderContext_value, 2);
1909
- rb_gc_register_address(&cEnumBuilderContext);
1910
- cEnumBuilderContext = klass;
2238
+ static VALUE EnumBuilderContext_alloc(VALUE klass) {
2239
+ EnumBuilderContext* self = ALLOC(EnumBuilderContext);
2240
+ VALUE ret = TypedData_Wrap_Struct(klass, &EnumBuilderContext_type, self);
2241
+ self->enum_proto = NULL;
2242
+ self->file_builder = Qnil;
2243
+ return ret;
1911
2244
  }
1912
2245
 
1913
2246
  /*
1914
2247
  * call-seq:
1915
- * EnumBuilderContext.new(enumdesc) => context
2248
+ * EnumBuilderContext.new(file_builder) => context
1916
2249
  *
1917
2250
  * Create a new builder context around the given enum descriptor. This class is
1918
2251
  * intended to serve as a DSL context to be used with #instance_eval.
1919
2252
  */
1920
- VALUE EnumBuilderContext_initialize(VALUE _self, VALUE enumdef) {
1921
- DEFINE_SELF(EnumBuilderContext, self, _self);
1922
- self->enumdesc = enumdef;
1923
- return Qnil;
1924
- }
2253
+ static VALUE EnumBuilderContext_initialize(VALUE _self, VALUE _file_builder,
2254
+ VALUE name) {
2255
+ EnumBuilderContext* self = ruby_to_EnumBuilderContext(_self);
2256
+ FileBuilderContext* file_builder = ruby_to_FileBuilderContext(_file_builder);
2257
+ google_protobuf_FileDescriptorProto* file_proto = file_builder->file_proto;
2258
+
2259
+ self->file_builder = _file_builder;
2260
+ self->enum_proto = google_protobuf_FileDescriptorProto_add_enum_type(
2261
+ file_proto, file_builder->arena);
2262
+
2263
+ google_protobuf_EnumDescriptorProto_set_name(
2264
+ self->enum_proto, FileBuilderContext_strdup(_file_builder, name));
1925
2265
 
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
2266
  return Qnil;
1930
2267
  }
1931
2268
 
@@ -1936,177 +2273,82 @@ static VALUE enumdef_add_value(VALUE enumdef,
1936
2273
  * Adds the given name => number mapping to the enum type. Name must be a Ruby
1937
2274
  * symbol.
1938
2275
  */
1939
- VALUE EnumBuilderContext_value(VALUE _self, VALUE name, VALUE number) {
1940
- DEFINE_SELF(EnumBuilderContext, self, _self);
1941
- return enumdef_add_value(self->enumdesc, name, number);
1942
- }
2276
+ static VALUE EnumBuilderContext_value(VALUE _self, VALUE name, VALUE number) {
2277
+ EnumBuilderContext* self = ruby_to_EnumBuilderContext(_self);
2278
+ FileBuilderContext* file_builder =
2279
+ ruby_to_FileBuilderContext(self->file_builder);
2280
+ google_protobuf_EnumValueDescriptorProto* enum_value;
1943
2281
 
2282
+ enum_value = google_protobuf_EnumDescriptorProto_add_value(
2283
+ self->enum_proto, file_builder->arena);
1944
2284
 
1945
- // -----------------------------------------------------------------------------
1946
- // FileBuilderContext.
1947
- // -----------------------------------------------------------------------------
1948
-
1949
- DEFINE_CLASS(FileBuilderContext,
1950
- "Google::Protobuf::Internal::FileBuilderContext");
1951
-
1952
- void FileBuilderContext_mark(void* _self) {
1953
- FileBuilderContext* self = _self;
1954
- rb_gc_mark(self->pending_list);
1955
- rb_gc_mark(self->file_descriptor);
1956
- rb_gc_mark(self->builder);
1957
- }
2285
+ google_protobuf_EnumValueDescriptorProto_set_name(
2286
+ enum_value, FileBuilderContext_strdup_sym(self->file_builder, name));
2287
+ google_protobuf_EnumValueDescriptorProto_set_number(enum_value,
2288
+ NUM2INT(number));
1958
2289
 
1959
- void FileBuilderContext_free(void* _self) {
1960
- FileBuilderContext* self = _self;
1961
- xfree(self);
1962
- }
1963
-
1964
- VALUE FileBuilderContext_alloc(VALUE klass) {
1965
- FileBuilderContext* self = ALLOC(FileBuilderContext);
1966
- VALUE ret = TypedData_Wrap_Struct(klass, &_FileBuilderContext_type, self);
1967
- self->pending_list = Qnil;
1968
- self->file_descriptor = Qnil;
1969
- self->builder = Qnil;
1970
- return ret;
1971
- }
1972
-
1973
- void FileBuilderContext_register(VALUE module) {
1974
- VALUE klass = rb_define_class_under(module, "FileBuilderContext", rb_cObject);
1975
- rb_define_alloc_func(klass, FileBuilderContext_alloc);
1976
- rb_define_method(klass, "initialize", FileBuilderContext_initialize, 2);
1977
- rb_define_method(klass, "add_message", FileBuilderContext_add_message, 1);
1978
- rb_define_method(klass, "add_enum", FileBuilderContext_add_enum, 1);
1979
- rb_gc_register_address(&cFileBuilderContext);
1980
- cFileBuilderContext = klass;
1981
- }
1982
-
1983
- /*
1984
- * call-seq:
1985
- * FileBuilderContext.new(file_descriptor, builder) => context
1986
- *
1987
- * Create a new file builder context for the given file descriptor and
1988
- * builder context. This class is intended to serve as a DSL context to be used
1989
- * with #instance_eval.
1990
- */
1991
- VALUE FileBuilderContext_initialize(VALUE _self, VALUE file_descriptor,
1992
- VALUE builder) {
1993
- DEFINE_SELF(FileBuilderContext, self, _self);
1994
- self->pending_list = rb_ary_new();
1995
- self->file_descriptor = file_descriptor;
1996
- self->builder = builder;
1997
- return Qnil;
1998
- }
1999
-
2000
- /*
2001
- * call-seq:
2002
- * FileBuilderContext.add_message(name, &block)
2003
- *
2004
- * Creates a new, empty descriptor with the given name, and invokes the block in
2005
- * the context of a MessageBuilderContext on that descriptor. The block can then
2006
- * call, e.g., MessageBuilderContext#optional and MessageBuilderContext#repeated
2007
- * methods to define the message fields.
2008
- *
2009
- * This is the recommended, idiomatic way to build message definitions.
2010
- */
2011
- VALUE FileBuilderContext_add_message(VALUE _self, VALUE name) {
2012
- DEFINE_SELF(FileBuilderContext, self, _self);
2013
- VALUE msgdef = rb_class_new_instance(1, &self->file_descriptor, cDescriptor);
2014
- VALUE args[2] = { msgdef, self->builder };
2015
- VALUE ctx = rb_class_new_instance(2, args, cMessageBuilderContext);
2016
- VALUE block = rb_block_proc();
2017
- rb_funcall(msgdef, rb_intern("name="), 1, name);
2018
- rb_funcall_with_block(ctx, rb_intern("instance_eval"), 0, NULL, block);
2019
- rb_ary_push(self->pending_list, msgdef);
2020
- return Qnil;
2021
- }
2022
-
2023
- /*
2024
- * call-seq:
2025
- * FileBuilderContext.add_enum(name, &block)
2026
- *
2027
- * Creates a new, empty enum descriptor with the given name, and invokes the
2028
- * block in the context of an EnumBuilderContext on that descriptor. The block
2029
- * can then call EnumBuilderContext#add_value to define the enum values.
2030
- *
2031
- * This is the recommended, idiomatic way to build enum definitions.
2032
- */
2033
- VALUE FileBuilderContext_add_enum(VALUE _self, VALUE name) {
2034
- DEFINE_SELF(FileBuilderContext, self, _self);
2035
- VALUE enumdef =
2036
- rb_class_new_instance(1, &self->file_descriptor, cEnumDescriptor);
2037
- VALUE ctx = rb_class_new_instance(1, &enumdef, cEnumBuilderContext);
2038
- VALUE block = rb_block_proc();
2039
- rb_funcall(enumdef, rb_intern("name="), 1, name);
2040
- rb_funcall_with_block(ctx, rb_intern("instance_eval"), 0, NULL, block);
2041
- rb_ary_push(self->pending_list, enumdef);
2042
2290
  return Qnil;
2043
2291
  }
2044
2292
 
2045
- VALUE FileBuilderContext_pending_descriptors(VALUE _self) {
2046
- DEFINE_SELF(FileBuilderContext, self, _self);
2047
- return self->pending_list;
2293
+ static void EnumBuilderContext_register(VALUE module) {
2294
+ VALUE klass = rb_define_class_under(
2295
+ module, "EnumBuilderContext", rb_cObject);
2296
+ rb_define_alloc_func(klass, EnumBuilderContext_alloc);
2297
+ rb_define_method(klass, "initialize", EnumBuilderContext_initialize, 2);
2298
+ rb_define_method(klass, "value", EnumBuilderContext_value, 2);
2299
+ rb_gc_register_address(&cEnumBuilderContext);
2300
+ cEnumBuilderContext = klass;
2048
2301
  }
2049
2302
 
2050
2303
  // -----------------------------------------------------------------------------
2051
2304
  // Builder.
2052
2305
  // -----------------------------------------------------------------------------
2053
2306
 
2054
- DEFINE_CLASS(Builder, "Google::Protobuf::Internal::Builder");
2307
+ typedef struct {
2308
+ VALUE descriptor_pool;
2309
+ VALUE default_file_builder;
2310
+ } Builder;
2055
2311
 
2056
- void Builder_mark(void* _self) {
2057
- Builder* self = _self;
2058
- rb_gc_mark(self->pending_list);
2059
- rb_gc_mark(self->default_file_descriptor);
2060
- }
2312
+ static VALUE cBuilder = Qnil;
2061
2313
 
2062
- void Builder_free(void* _self) {
2314
+ static void Builder_mark(void* _self) {
2063
2315
  Builder* self = _self;
2064
- xfree(self->defs);
2065
- xfree(self);
2316
+ rb_gc_mark(self->descriptor_pool);
2317
+ rb_gc_mark(self->default_file_builder);
2066
2318
  }
2067
2319
 
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
- VALUE Builder_alloc(VALUE klass) {
2077
- Builder* self = ALLOC(Builder);
2078
- VALUE ret = TypedData_Wrap_Struct(
2079
- klass, &_Builder_type, self);
2080
- self->pending_list = Qnil;
2081
- self->defs = NULL;
2082
- self->default_file_descriptor = Qnil;
2320
+ static const rb_data_type_t Builder_type = {
2321
+ "Google::Protobuf::Internal::Builder",
2322
+ {Builder_mark, RUBY_DEFAULT_FREE, NULL},
2323
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY,
2324
+ };
2325
+
2326
+ static Builder* ruby_to_Builder(VALUE val) {
2327
+ Builder* ret;
2328
+ TypedData_Get_Struct(val, Builder, &Builder_type, ret);
2083
2329
  return ret;
2084
2330
  }
2085
2331
 
2086
- void Builder_register(VALUE module) {
2087
- VALUE klass = rb_define_class_under(module, "Builder", rb_cObject);
2088
- rb_define_alloc_func(klass, Builder_alloc);
2089
- rb_define_method(klass, "initialize", Builder_initialize, 0);
2090
- rb_define_method(klass, "add_file", Builder_add_file, -1);
2091
- rb_define_method(klass, "add_message", Builder_add_message, 1);
2092
- rb_define_method(klass, "add_enum", Builder_add_enum, 1);
2093
- rb_define_method(klass, "finalize_to_pool", Builder_finalize_to_pool, 1);
2094
- rb_gc_register_address(&cBuilder);
2095
- cBuilder = klass;
2332
+ static VALUE Builder_alloc(VALUE klass) {
2333
+ Builder* self = ALLOC(Builder);
2334
+ VALUE ret = TypedData_Wrap_Struct(klass, &Builder_type, self);
2335
+ self->descriptor_pool = Qnil;
2336
+ self->default_file_builder = Qnil;
2337
+ return ret;
2096
2338
  }
2097
2339
 
2098
2340
  /*
2099
2341
  * call-seq:
2100
- * Builder.new
2342
+ * Builder.new(descriptor_pool) => builder
2101
2343
  *
2102
- * Initializes a new builder.
2344
+ * Creates a new Builder. A Builder can accumulate a set of new message and enum
2345
+ * descriptors and atomically register them into a pool in a way that allows for
2346
+ * (co)recursive type references.
2103
2347
  */
2104
- VALUE Builder_initialize(VALUE _self) {
2105
- DEFINE_SELF(Builder, self, _self);
2106
- self->pending_list = rb_ary_new();
2107
- VALUE file_name = Qnil;
2108
- self->default_file_descriptor =
2109
- rb_class_new_instance(1, &file_name, cFileDescriptor);
2348
+ static VALUE Builder_initialize(VALUE _self, VALUE pool) {
2349
+ Builder* self = ruby_to_Builder(_self);
2350
+ self->descriptor_pool = pool;
2351
+ self->default_file_builder = Qnil; // Created lazily if needed.
2110
2352
  return Qnil;
2111
2353
  }
2112
2354
 
@@ -2121,19 +2363,40 @@ VALUE Builder_initialize(VALUE _self) {
2121
2363
  *
2122
2364
  * This is the recommended, idiomatic way to build file descriptors.
2123
2365
  */
2124
- VALUE Builder_add_file(int argc, VALUE* argv, VALUE _self) {
2125
- DEFINE_SELF(Builder, self, _self);
2126
- VALUE file_descriptor = rb_class_new_instance(argc, argv, cFileDescriptor);
2127
- VALUE args[2] = { file_descriptor, _self };
2128
- VALUE ctx = rb_class_new_instance(2, args, cFileBuilderContext);
2129
- VALUE block = rb_block_proc();
2366
+ static VALUE Builder_add_file(int argc, VALUE* argv, VALUE _self) {
2367
+ Builder* self = ruby_to_Builder(_self);
2368
+ VALUE name, options;
2369
+ VALUE ctx;
2370
+ VALUE block;
2371
+
2372
+ rb_scan_args(argc, argv, "11", &name, &options);
2373
+
2374
+ {
2375
+ VALUE args[3] = { self->descriptor_pool, name, options };
2376
+ ctx = rb_class_new_instance(3, args, cFileBuilderContext);
2377
+ }
2378
+
2379
+ block = rb_block_proc();
2130
2380
  rb_funcall_with_block(ctx, rb_intern("instance_eval"), 0, NULL, block);
2381
+ FileBuilderContext_build(ctx);
2131
2382
 
2132
- rb_ary_concat(self->pending_list,
2133
- FileBuilderContext_pending_descriptors(ctx));
2134
2383
  return Qnil;
2135
2384
  }
2136
2385
 
2386
+ static VALUE Builder_get_default_file(VALUE _self) {
2387
+ Builder* self = ruby_to_Builder(_self);
2388
+
2389
+ /* Lazily create only if legacy builder-level methods are called. */
2390
+ if (self->default_file_builder == Qnil) {
2391
+ VALUE name = rb_str_new2("ruby_default_file.proto");
2392
+ VALUE args [3] = { self->descriptor_pool, name, rb_hash_new() };
2393
+ self->default_file_builder =
2394
+ rb_class_new_instance(3, args, cFileBuilderContext);
2395
+ }
2396
+
2397
+ return self->default_file_builder;
2398
+ }
2399
+
2137
2400
  /*
2138
2401
  * call-seq:
2139
2402
  * Builder.add_message(name, &block)
@@ -2145,16 +2408,10 @@ VALUE Builder_add_file(int argc, VALUE* argv, VALUE _self) {
2145
2408
  * files generated by protoc which don't add messages within "add_file" block.
2146
2409
  * Descriptors created this way get assigned to a default empty FileDescriptor.
2147
2410
  */
2148
- 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);
2411
+ static VALUE Builder_add_message(VALUE _self, VALUE name) {
2412
+ VALUE file_builder = Builder_get_default_file(_self);
2413
+ rb_funcall_with_block(file_builder, rb_intern("add_message"), 1, &name,
2414
+ rb_block_proc());
2158
2415
  return Qnil;
2159
2416
  }
2160
2417
 
@@ -2170,88 +2427,158 @@ VALUE Builder_add_message(VALUE _self, VALUE name) {
2170
2427
  * Enum descriptors created this way get assigned to a default empty
2171
2428
  * FileDescriptor.
2172
2429
  */
2173
- 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);
2430
+ static VALUE Builder_add_enum(VALUE _self, VALUE name) {
2431
+ VALUE file_builder = Builder_get_default_file(_self);
2432
+ rb_funcall_with_block(file_builder, rb_intern("add_enum"), 1, &name,
2433
+ rb_block_proc());
2182
2434
  return Qnil;
2183
2435
  }
2184
2436
 
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
- }
2437
+ /* This method is hidden from Ruby, and only called directly from
2438
+ * DescriptorPool_build(). */
2439
+ static VALUE Builder_build(VALUE _self) {
2440
+ Builder* self = ruby_to_Builder(_self);
2441
+
2442
+ if (self->default_file_builder != Qnil) {
2443
+ FileBuilderContext_build(self->default_file_builder);
2444
+ self->default_file_builder = Qnil;
2195
2445
  }
2446
+
2447
+ return Qnil;
2448
+ }
2449
+
2450
+ static void Builder_register(VALUE module) {
2451
+ VALUE klass = rb_define_class_under(module, "Builder", rb_cObject);
2452
+ rb_define_alloc_func(klass, Builder_alloc);
2453
+ rb_define_method(klass, "initialize", Builder_initialize, 1);
2454
+ rb_define_method(klass, "add_file", Builder_add_file, -1);
2455
+ rb_define_method(klass, "add_message", Builder_add_message, 1);
2456
+ rb_define_method(klass, "add_enum", Builder_add_enum, 1);
2457
+ rb_gc_register_address(&cBuilder);
2458
+ cBuilder = klass;
2196
2459
  }
2197
2460
 
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'.");
2461
+ static VALUE get_def_obj(VALUE _descriptor_pool, const void* ptr, VALUE klass) {
2462
+ DescriptorPool* descriptor_pool = ruby_to_DescriptorPool(_descriptor_pool);
2463
+ VALUE key = ULL2NUM((intptr_t)ptr);
2464
+ VALUE def;
2465
+
2466
+ def = rb_hash_aref(descriptor_pool->def_to_descriptor, key);
2467
+
2468
+ if (ptr == NULL) {
2469
+ return Qnil;
2205
2470
  }
2471
+
2472
+ if (def == Qnil) {
2473
+ // Lazily create wrapper object.
2474
+ VALUE args[3] = { c_only_cookie, _descriptor_pool, key };
2475
+ def = rb_class_new_instance(3, args, klass);
2476
+ rb_hash_aset(descriptor_pool->def_to_descriptor, key, def);
2477
+ }
2478
+
2479
+ return def;
2206
2480
  }
2207
2481
 
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);
2482
+ static VALUE get_msgdef_obj(VALUE descriptor_pool, const upb_msgdef* def) {
2483
+ return get_def_obj(descriptor_pool, def, cDescriptor);
2484
+ }
2224
2485
 
2225
- DescriptorPool* pool = ruby_to_DescriptorPool(pool_rb);
2486
+ static VALUE get_enumdef_obj(VALUE descriptor_pool, const upb_enumdef* def) {
2487
+ return get_def_obj(descriptor_pool, def, cEnumDescriptor);
2488
+ }
2226
2489
 
2227
- REALLOC_N(self->defs, upb_def*, RARRAY_LEN(self->pending_list));
2490
+ static VALUE get_fielddef_obj(VALUE descriptor_pool, const upb_fielddef* def) {
2491
+ return get_def_obj(descriptor_pool, def, cFieldDescriptor);
2492
+ }
2228
2493
 
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;
2494
+ static VALUE get_filedef_obj(VALUE descriptor_pool, const upb_filedef* def) {
2495
+ return get_def_obj(descriptor_pool, def, cFileDescriptor);
2496
+ }
2239
2497
 
2240
- if (upb_filedef_syntax(upb_def_file(self->defs[i])) == UPB_SYNTAX_PROTO3) {
2241
- proto3_validate_enumdef((const upb_enumdef*)self->defs[i]);
2242
- }
2498
+ static VALUE get_oneofdef_obj(VALUE descriptor_pool, const upb_oneofdef* def) {
2499
+ return get_def_obj(descriptor_pool, def, cOneofDescriptor);
2500
+ }
2501
+
2502
+ // -----------------------------------------------------------------------------
2503
+ // Shared functions
2504
+ // -----------------------------------------------------------------------------
2505
+
2506
+ // Functions exposed to other modules in defs.h.
2507
+
2508
+ VALUE Descriptor_DefToClass(const upb_msgdef *m) {
2509
+ const upb_symtab *symtab = upb_filedef_symtab(upb_msgdef_file(m));
2510
+ VALUE pool = ObjectCache_Get(symtab);
2511
+ PBRUBY_ASSERT(pool != Qnil);
2512
+ VALUE desc_rb = get_msgdef_obj(pool, m);
2513
+ const Descriptor* desc = ruby_to_Descriptor(desc_rb);
2514
+ return desc->klass;
2515
+ }
2516
+
2517
+ const upb_msgdef *Descriptor_GetMsgDef(VALUE desc_rb) {
2518
+ const Descriptor* desc = ruby_to_Descriptor(desc_rb);
2519
+ return desc->msgdef;
2520
+ }
2521
+
2522
+ VALUE TypeInfo_InitArg(int argc, VALUE *argv, int skip_arg) {
2523
+ if (argc > skip_arg) {
2524
+ if (argc > 1 + skip_arg) {
2525
+ rb_raise(rb_eArgError, "Expected a maximum of %d arguments.", skip_arg + 1);
2243
2526
  }
2527
+ return argv[skip_arg];
2528
+ } else {
2529
+ return Qnil;
2244
2530
  }
2531
+ }
2532
+
2533
+ TypeInfo TypeInfo_FromClass(int argc, VALUE* argv, int skip_arg,
2534
+ VALUE* type_class, VALUE* init_arg) {
2535
+ TypeInfo ret = {ruby_to_fieldtype(argv[skip_arg])};
2245
2536
 
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");
2537
+ if (ret.type == UPB_TYPE_MESSAGE || ret.type == UPB_TYPE_ENUM) {
2538
+ *init_arg = TypeInfo_InitArg(argc, argv, skip_arg + 2);
2539
+
2540
+ if (argc < 2 + skip_arg) {
2541
+ rb_raise(rb_eArgError, "Expected at least %d arguments for message/enum.",
2542
+ 2 + skip_arg);
2543
+ }
2544
+
2545
+ VALUE klass = argv[1 + skip_arg];
2546
+ VALUE desc = MessageOrEnum_GetDescriptor(klass);
2547
+ *type_class = klass;
2548
+
2549
+ if (desc == Qnil) {
2550
+ rb_raise(rb_eArgError,
2551
+ "Type class has no descriptor. Please pass a "
2552
+ "class or enum as returned by the DescriptorPool.");
2553
+ }
2249
2554
 
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);
2555
+ if (ret.type == UPB_TYPE_MESSAGE) {
2556
+ ret.def.msgdef = ruby_to_Descriptor(desc)->msgdef;
2557
+ Message_CheckClass(klass);
2558
+ } else {
2559
+ PBRUBY_ASSERT(ret.type == UPB_TYPE_ENUM);
2560
+ ret.def.enumdef = ruby_to_EnumDescriptor(desc)->enumdef;
2561
+ }
2562
+ } else {
2563
+ *init_arg = TypeInfo_InitArg(argc, argv, skip_arg + 1);
2253
2564
  }
2254
2565
 
2255
- self->pending_list = rb_ary_new();
2256
- return Qnil;
2566
+ return ret;
2567
+ }
2568
+
2569
+ void Defs_register(VALUE module) {
2570
+ DescriptorPool_register(module);
2571
+ Descriptor_register(module);
2572
+ FileDescriptor_register(module);
2573
+ FieldDescriptor_register(module);
2574
+ OneofDescriptor_register(module);
2575
+ EnumDescriptor_register(module);
2576
+ FileBuilderContext_register(module);
2577
+ MessageBuilderContext_register(module);
2578
+ OneofBuilderContext_register(module);
2579
+ EnumBuilderContext_register(module);
2580
+ Builder_register(module);
2581
+
2582
+ rb_gc_register_address(&c_only_cookie);
2583
+ c_only_cookie = rb_class_new_instance(0, NULL, rb_cObject);
2257
2584
  }