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