xref: /aosp_15_r20/external/protobuf/ruby/ext/google/protobuf_c/defs.c (revision 1b3f573f81763fcece89efc2b6a5209149e44ab8)
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 <ruby/version.h>
34 
35 #include "convert.h"
36 #include "message.h"
37 #include "protobuf.h"
38 
39 // -----------------------------------------------------------------------------
40 // Global map from upb {msg,enum}defs to wrapper Descriptor/EnumDescriptor
41 // instances.
42 // -----------------------------------------------------------------------------
43 
44 static VALUE get_msgdef_obj(VALUE descriptor_pool, const upb_MessageDef* def);
45 static VALUE get_enumdef_obj(VALUE descriptor_pool, const upb_EnumDef* def);
46 static VALUE get_fielddef_obj(VALUE descriptor_pool, const upb_FieldDef* def);
47 static VALUE get_filedef_obj(VALUE descriptor_pool, const upb_FileDef* def);
48 static VALUE get_oneofdef_obj(VALUE descriptor_pool, const upb_OneofDef* def);
49 
50 // A distinct object that is not accessible from Ruby.  We use this as a
51 // constructor argument to enforce that certain objects cannot be created from
52 // Ruby.
53 VALUE c_only_cookie = Qnil;
54 
55 // -----------------------------------------------------------------------------
56 // Common utilities.
57 // -----------------------------------------------------------------------------
58 
get_str(VALUE str)59 static const char* get_str(VALUE str) {
60   Check_Type(str, T_STRING);
61   return RSTRING_PTR(str);
62 }
63 
rb_str_maybe_null(const char * s)64 static VALUE rb_str_maybe_null(const char* s) {
65   if (s == NULL) {
66     s = "";
67   }
68   return rb_str_new2(s);
69 }
70 
71 // -----------------------------------------------------------------------------
72 // DescriptorPool.
73 // -----------------------------------------------------------------------------
74 
75 typedef struct {
76   VALUE def_to_descriptor;  // Hash table of def* -> Ruby descriptor.
77   upb_DefPool* symtab;
78 } DescriptorPool;
79 
80 VALUE cDescriptorPool = Qnil;
81 
82 // Global singleton DescriptorPool. The user is free to create others, but this
83 // is used by generated code.
84 VALUE generated_pool = Qnil;
85 
DescriptorPool_mark(void * _self)86 static void DescriptorPool_mark(void* _self) {
87   DescriptorPool* self = _self;
88   rb_gc_mark(self->def_to_descriptor);
89 }
90 
DescriptorPool_free(void * _self)91 static void DescriptorPool_free(void* _self) {
92   DescriptorPool* self = _self;
93   upb_DefPool_Free(self->symtab);
94   xfree(self);
95 }
96 
97 static const rb_data_type_t DescriptorPool_type = {
98     "Google::Protobuf::DescriptorPool",
99     {DescriptorPool_mark, DescriptorPool_free, NULL},
100     .flags = RUBY_TYPED_FREE_IMMEDIATELY,
101 };
102 
ruby_to_DescriptorPool(VALUE val)103 static DescriptorPool* ruby_to_DescriptorPool(VALUE val) {
104   DescriptorPool* ret;
105   TypedData_Get_Struct(val, DescriptorPool, &DescriptorPool_type, ret);
106   return ret;
107 }
108 
109 // Exposed to other modules in defs.h.
DescriptorPool_GetSymtab(VALUE desc_pool_rb)110 const upb_DefPool* DescriptorPool_GetSymtab(VALUE desc_pool_rb) {
111   DescriptorPool* pool = ruby_to_DescriptorPool(desc_pool_rb);
112   return pool->symtab;
113 }
114 
115 /*
116  * call-seq:
117  *     DescriptorPool.new => pool
118  *
119  * Creates a new, empty, descriptor pool.
120  */
DescriptorPool_alloc(VALUE klass)121 static VALUE DescriptorPool_alloc(VALUE klass) {
122   DescriptorPool* self = ALLOC(DescriptorPool);
123   VALUE ret;
124 
125   self->def_to_descriptor = Qnil;
126   ret = TypedData_Wrap_Struct(klass, &DescriptorPool_type, self);
127 
128   self->def_to_descriptor = rb_hash_new();
129   self->symtab = upb_DefPool_New();
130   ObjectCache_Add(self->symtab, ret);
131 
132   return ret;
133 }
134 
135 /*
136  * call-seq:
137  *     DescriptorPool.add_serialized_file(serialized_file_proto)
138  *
139  * Adds the given serialized FileDescriptorProto to the pool.
140  */
DescriptorPool_add_serialized_file(VALUE _self,VALUE serialized_file_proto)141 VALUE DescriptorPool_add_serialized_file(VALUE _self,
142                                          VALUE serialized_file_proto) {
143   DescriptorPool* self = ruby_to_DescriptorPool(_self);
144   Check_Type(serialized_file_proto, T_STRING);
145   VALUE arena_rb = Arena_new();
146   upb_Arena* arena = Arena_get(arena_rb);
147   google_protobuf_FileDescriptorProto* file_proto =
148       google_protobuf_FileDescriptorProto_parse(
149           RSTRING_PTR(serialized_file_proto),
150           RSTRING_LEN(serialized_file_proto), arena);
151   if (!file_proto) {
152     rb_raise(rb_eArgError, "Unable to parse FileDescriptorProto");
153   }
154   upb_Status status;
155   upb_Status_Clear(&status);
156   const upb_FileDef* filedef =
157       upb_DefPool_AddFile(self->symtab, file_proto, &status);
158   if (!filedef) {
159     rb_raise(cTypeError, "Unable to build file to DescriptorPool: %s",
160              upb_Status_ErrorMessage(&status));
161   }
162   RB_GC_GUARD(arena_rb);
163   return get_filedef_obj(_self, filedef);
164 }
165 
166 /*
167  * call-seq:
168  *     DescriptorPool.lookup(name) => descriptor
169  *
170  * Finds a Descriptor or EnumDescriptor by name and returns it, or nil if none
171  * exists with the given name.
172  */
DescriptorPool_lookup(VALUE _self,VALUE name)173 static VALUE DescriptorPool_lookup(VALUE _self, VALUE name) {
174   DescriptorPool* self = ruby_to_DescriptorPool(_self);
175   const char* name_str = get_str(name);
176   const upb_MessageDef* msgdef;
177   const upb_EnumDef* enumdef;
178 
179   msgdef = upb_DefPool_FindMessageByName(self->symtab, name_str);
180   if (msgdef) {
181     return get_msgdef_obj(_self, msgdef);
182   }
183 
184   enumdef = upb_DefPool_FindEnumByName(self->symtab, name_str);
185   if (enumdef) {
186     return get_enumdef_obj(_self, enumdef);
187   }
188 
189   return Qnil;
190 }
191 
192 /*
193  * call-seq:
194  *     DescriptorPool.generated_pool => descriptor_pool
195  *
196  * Class method that returns the global DescriptorPool. This is a singleton into
197  * which generated-code message and enum types are registered. The user may also
198  * register types in this pool for convenience so that they do not have to hold
199  * a reference to a private pool instance.
200  */
DescriptorPool_generated_pool(VALUE _self)201 static VALUE DescriptorPool_generated_pool(VALUE _self) {
202   return generated_pool;
203 }
204 
DescriptorPool_register(VALUE module)205 static void DescriptorPool_register(VALUE module) {
206   VALUE klass = rb_define_class_under(module, "DescriptorPool", rb_cObject);
207   rb_define_alloc_func(klass, DescriptorPool_alloc);
208   rb_define_method(klass, "add_serialized_file",
209                    DescriptorPool_add_serialized_file, 1);
210   rb_define_method(klass, "lookup", DescriptorPool_lookup, 1);
211   rb_define_singleton_method(klass, "generated_pool",
212                              DescriptorPool_generated_pool, 0);
213   rb_gc_register_address(&cDescriptorPool);
214   cDescriptorPool = klass;
215 
216   rb_gc_register_address(&generated_pool);
217   generated_pool = rb_class_new_instance(0, NULL, klass);
218 }
219 
220 // -----------------------------------------------------------------------------
221 // Descriptor.
222 // -----------------------------------------------------------------------------
223 
224 typedef struct {
225   const upb_MessageDef* msgdef;
226   VALUE klass;
227   VALUE descriptor_pool;
228 } Descriptor;
229 
230 VALUE cDescriptor = Qnil;
231 
Descriptor_mark(void * _self)232 static void Descriptor_mark(void* _self) {
233   Descriptor* self = _self;
234   rb_gc_mark(self->klass);
235   rb_gc_mark(self->descriptor_pool);
236 }
237 
238 static const rb_data_type_t Descriptor_type = {
239     "Google::Protobuf::Descriptor",
240     {Descriptor_mark, RUBY_DEFAULT_FREE, NULL},
241     .flags = RUBY_TYPED_FREE_IMMEDIATELY,
242 };
243 
ruby_to_Descriptor(VALUE val)244 static Descriptor* ruby_to_Descriptor(VALUE val) {
245   Descriptor* ret;
246   TypedData_Get_Struct(val, Descriptor, &Descriptor_type, ret);
247   return ret;
248 }
249 
250 /*
251  * call-seq:
252  *     Descriptor.new => descriptor
253  *
254  * Creates a new, empty, message type descriptor. At a minimum, its name must be
255  * set before it is added to a pool. It cannot be used to create messages until
256  * it is added to a pool, after which it becomes immutable (as part of a
257  * finalization process).
258  */
Descriptor_alloc(VALUE klass)259 static VALUE Descriptor_alloc(VALUE klass) {
260   Descriptor* self = ALLOC(Descriptor);
261   VALUE ret = TypedData_Wrap_Struct(klass, &Descriptor_type, self);
262   self->msgdef = NULL;
263   self->klass = Qnil;
264   self->descriptor_pool = Qnil;
265   return ret;
266 }
267 
268 /*
269  * call-seq:
270  *    Descriptor.new(c_only_cookie, ptr) => Descriptor
271  *
272  * Creates a descriptor wrapper object.  May only be called from C.
273  */
Descriptor_initialize(VALUE _self,VALUE cookie,VALUE descriptor_pool,VALUE ptr)274 static VALUE Descriptor_initialize(VALUE _self, VALUE cookie,
275                                    VALUE descriptor_pool, VALUE ptr) {
276   Descriptor* self = ruby_to_Descriptor(_self);
277 
278   if (cookie != c_only_cookie) {
279     rb_raise(rb_eRuntimeError,
280              "Descriptor objects may not be created from Ruby.");
281   }
282 
283   self->descriptor_pool = descriptor_pool;
284   self->msgdef = (const upb_MessageDef*)NUM2ULL(ptr);
285 
286   return Qnil;
287 }
288 
289 /*
290  * call-seq:
291  *    Descriptor.file_descriptor
292  *
293  * Returns the FileDescriptor object this message belongs to.
294  */
Descriptor_file_descriptor(VALUE _self)295 static VALUE Descriptor_file_descriptor(VALUE _self) {
296   Descriptor* self = ruby_to_Descriptor(_self);
297   return get_filedef_obj(self->descriptor_pool,
298                          upb_MessageDef_File(self->msgdef));
299 }
300 
301 /*
302  * call-seq:
303  *     Descriptor.name => name
304  *
305  * Returns the name of this message type as a fully-qualified string (e.g.,
306  * My.Package.MessageType).
307  */
Descriptor_name(VALUE _self)308 static VALUE Descriptor_name(VALUE _self) {
309   Descriptor* self = ruby_to_Descriptor(_self);
310   return rb_str_maybe_null(upb_MessageDef_FullName(self->msgdef));
311 }
312 
313 /*
314  * call-seq:
315  *     Descriptor.each(&block)
316  *
317  * Iterates over fields in this message type, yielding to the block on each one.
318  */
Descriptor_each(VALUE _self)319 static VALUE Descriptor_each(VALUE _self) {
320   Descriptor* self = ruby_to_Descriptor(_self);
321 
322   int n = upb_MessageDef_FieldCount(self->msgdef);
323   for (int i = 0; i < n; i++) {
324     const upb_FieldDef* field = upb_MessageDef_Field(self->msgdef, i);
325     VALUE obj = get_fielddef_obj(self->descriptor_pool, field);
326     rb_yield(obj);
327   }
328   return Qnil;
329 }
330 
331 /*
332  * call-seq:
333  *     Descriptor.lookup(name) => FieldDescriptor
334  *
335  * Returns the field descriptor for the field with the given name, if present,
336  * or nil if none.
337  */
Descriptor_lookup(VALUE _self,VALUE name)338 static VALUE Descriptor_lookup(VALUE _self, VALUE name) {
339   Descriptor* self = ruby_to_Descriptor(_self);
340   const char* s = get_str(name);
341   const upb_FieldDef* field = upb_MessageDef_FindFieldByName(self->msgdef, s);
342   if (field == NULL) {
343     return Qnil;
344   }
345   return get_fielddef_obj(self->descriptor_pool, field);
346 }
347 
348 /*
349  * call-seq:
350  *     Descriptor.each_oneof(&block) => nil
351  *
352  * Invokes the given block for each oneof in this message type, passing the
353  * corresponding OneofDescriptor.
354  */
Descriptor_each_oneof(VALUE _self)355 static VALUE Descriptor_each_oneof(VALUE _self) {
356   Descriptor* self = ruby_to_Descriptor(_self);
357 
358   int n = upb_MessageDef_OneofCount(self->msgdef);
359   for (int i = 0; i < n; i++) {
360     const upb_OneofDef* oneof = upb_MessageDef_Oneof(self->msgdef, i);
361     VALUE obj = get_oneofdef_obj(self->descriptor_pool, oneof);
362     rb_yield(obj);
363   }
364   return Qnil;
365 }
366 
367 /*
368  * call-seq:
369  *     Descriptor.lookup_oneof(name) => OneofDescriptor
370  *
371  * Returns the oneof descriptor for the oneof with the given name, if present,
372  * or nil if none.
373  */
Descriptor_lookup_oneof(VALUE _self,VALUE name)374 static VALUE Descriptor_lookup_oneof(VALUE _self, VALUE name) {
375   Descriptor* self = ruby_to_Descriptor(_self);
376   const char* s = get_str(name);
377   const upb_OneofDef* oneof = upb_MessageDef_FindOneofByName(self->msgdef, s);
378   if (oneof == NULL) {
379     return Qnil;
380   }
381   return get_oneofdef_obj(self->descriptor_pool, oneof);
382 }
383 
384 /*
385  * call-seq:
386  *     Descriptor.msgclass => message_klass
387  *
388  * Returns the Ruby class created for this message type.
389  */
Descriptor_msgclass(VALUE _self)390 static VALUE Descriptor_msgclass(VALUE _self) {
391   Descriptor* self = ruby_to_Descriptor(_self);
392   if (self->klass == Qnil) {
393     self->klass = build_class_from_descriptor(_self);
394   }
395   return self->klass;
396 }
397 
Descriptor_register(VALUE module)398 static void Descriptor_register(VALUE module) {
399   VALUE klass = rb_define_class_under(module, "Descriptor", rb_cObject);
400   rb_define_alloc_func(klass, Descriptor_alloc);
401   rb_define_method(klass, "initialize", Descriptor_initialize, 3);
402   rb_define_method(klass, "each", Descriptor_each, 0);
403   rb_define_method(klass, "lookup", Descriptor_lookup, 1);
404   rb_define_method(klass, "each_oneof", Descriptor_each_oneof, 0);
405   rb_define_method(klass, "lookup_oneof", Descriptor_lookup_oneof, 1);
406   rb_define_method(klass, "msgclass", Descriptor_msgclass, 0);
407   rb_define_method(klass, "name", Descriptor_name, 0);
408   rb_define_method(klass, "file_descriptor", Descriptor_file_descriptor, 0);
409   rb_include_module(klass, rb_mEnumerable);
410   rb_gc_register_address(&cDescriptor);
411   cDescriptor = klass;
412 }
413 
414 // -----------------------------------------------------------------------------
415 // FileDescriptor.
416 // -----------------------------------------------------------------------------
417 
418 typedef struct {
419   const upb_FileDef* filedef;
420   VALUE descriptor_pool;  // Owns the upb_FileDef.
421 } FileDescriptor;
422 
423 static VALUE cFileDescriptor = Qnil;
424 
FileDescriptor_mark(void * _self)425 static void FileDescriptor_mark(void* _self) {
426   FileDescriptor* self = _self;
427   rb_gc_mark(self->descriptor_pool);
428 }
429 
430 static const rb_data_type_t FileDescriptor_type = {
431     "Google::Protobuf::FileDescriptor",
432     {FileDescriptor_mark, RUBY_DEFAULT_FREE, NULL},
433     .flags = RUBY_TYPED_FREE_IMMEDIATELY,
434 };
435 
ruby_to_FileDescriptor(VALUE val)436 static FileDescriptor* ruby_to_FileDescriptor(VALUE val) {
437   FileDescriptor* ret;
438   TypedData_Get_Struct(val, FileDescriptor, &FileDescriptor_type, ret);
439   return ret;
440 }
441 
FileDescriptor_alloc(VALUE klass)442 static VALUE FileDescriptor_alloc(VALUE klass) {
443   FileDescriptor* self = ALLOC(FileDescriptor);
444   VALUE ret = TypedData_Wrap_Struct(klass, &FileDescriptor_type, self);
445   self->descriptor_pool = Qnil;
446   self->filedef = NULL;
447   return ret;
448 }
449 
450 /*
451  * call-seq:
452  *     FileDescriptor.new => file
453  *
454  * Returns a new file descriptor. The syntax must be set before it's passed
455  * to a builder.
456  */
FileDescriptor_initialize(VALUE _self,VALUE cookie,VALUE descriptor_pool,VALUE ptr)457 static VALUE FileDescriptor_initialize(VALUE _self, VALUE cookie,
458                                        VALUE descriptor_pool, VALUE ptr) {
459   FileDescriptor* self = ruby_to_FileDescriptor(_self);
460 
461   if (cookie != c_only_cookie) {
462     rb_raise(rb_eRuntimeError,
463              "Descriptor objects may not be created from Ruby.");
464   }
465 
466   self->descriptor_pool = descriptor_pool;
467   self->filedef = (const upb_FileDef*)NUM2ULL(ptr);
468 
469   return Qnil;
470 }
471 
472 /*
473  * call-seq:
474  *     FileDescriptor.name => name
475  *
476  * Returns the name of the file.
477  */
FileDescriptor_name(VALUE _self)478 static VALUE FileDescriptor_name(VALUE _self) {
479   FileDescriptor* self = ruby_to_FileDescriptor(_self);
480   const char* name = upb_FileDef_Name(self->filedef);
481   return name == NULL ? Qnil : rb_str_new2(name);
482 }
483 
484 /*
485  * call-seq:
486  *     FileDescriptor.syntax => syntax
487  *
488  * Returns this file descriptors syntax.
489  *
490  * Valid syntax versions are:
491  *     :proto2 or :proto3.
492  */
FileDescriptor_syntax(VALUE _self)493 static VALUE FileDescriptor_syntax(VALUE _self) {
494   FileDescriptor* self = ruby_to_FileDescriptor(_self);
495 
496   switch (upb_FileDef_Syntax(self->filedef)) {
497     case kUpb_Syntax_Proto3:
498       return ID2SYM(rb_intern("proto3"));
499     case kUpb_Syntax_Proto2:
500       return ID2SYM(rb_intern("proto2"));
501     default:
502       return Qnil;
503   }
504 }
505 
FileDescriptor_register(VALUE module)506 static void FileDescriptor_register(VALUE module) {
507   VALUE klass = rb_define_class_under(module, "FileDescriptor", rb_cObject);
508   rb_define_alloc_func(klass, FileDescriptor_alloc);
509   rb_define_method(klass, "initialize", FileDescriptor_initialize, 3);
510   rb_define_method(klass, "name", FileDescriptor_name, 0);
511   rb_define_method(klass, "syntax", FileDescriptor_syntax, 0);
512   rb_gc_register_address(&cFileDescriptor);
513   cFileDescriptor = klass;
514 }
515 
516 // -----------------------------------------------------------------------------
517 // FieldDescriptor.
518 // -----------------------------------------------------------------------------
519 
520 typedef struct {
521   const upb_FieldDef* fielddef;
522   VALUE descriptor_pool;  // Owns the upb_FieldDef.
523 } FieldDescriptor;
524 
525 static VALUE cFieldDescriptor = Qnil;
526 
FieldDescriptor_mark(void * _self)527 static void FieldDescriptor_mark(void* _self) {
528   FieldDescriptor* self = _self;
529   rb_gc_mark(self->descriptor_pool);
530 }
531 
532 static const rb_data_type_t FieldDescriptor_type = {
533     "Google::Protobuf::FieldDescriptor",
534     {FieldDescriptor_mark, RUBY_DEFAULT_FREE, NULL},
535     .flags = RUBY_TYPED_FREE_IMMEDIATELY,
536 };
537 
ruby_to_FieldDescriptor(VALUE val)538 static FieldDescriptor* ruby_to_FieldDescriptor(VALUE val) {
539   FieldDescriptor* ret;
540   TypedData_Get_Struct(val, FieldDescriptor, &FieldDescriptor_type, ret);
541   return ret;
542 }
543 
544 /*
545  * call-seq:
546  *     FieldDescriptor.new => field
547  *
548  * Returns a new field descriptor. Its name, type, etc. must be set before it is
549  * added to a message type.
550  */
FieldDescriptor_alloc(VALUE klass)551 static VALUE FieldDescriptor_alloc(VALUE klass) {
552   FieldDescriptor* self = ALLOC(FieldDescriptor);
553   VALUE ret = TypedData_Wrap_Struct(klass, &FieldDescriptor_type, self);
554   self->fielddef = NULL;
555   return ret;
556 }
557 
558 /*
559  * call-seq:
560  *    EnumDescriptor.new(c_only_cookie, pool, ptr) => EnumDescriptor
561  *
562  * Creates a descriptor wrapper object.  May only be called from C.
563  */
FieldDescriptor_initialize(VALUE _self,VALUE cookie,VALUE descriptor_pool,VALUE ptr)564 static VALUE FieldDescriptor_initialize(VALUE _self, VALUE cookie,
565                                         VALUE descriptor_pool, VALUE ptr) {
566   FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
567 
568   if (cookie != c_only_cookie) {
569     rb_raise(rb_eRuntimeError,
570              "Descriptor objects may not be created from Ruby.");
571   }
572 
573   self->descriptor_pool = descriptor_pool;
574   self->fielddef = (const upb_FieldDef*)NUM2ULL(ptr);
575 
576   return Qnil;
577 }
578 
579 /*
580  * call-seq:
581  *     FieldDescriptor.name => name
582  *
583  * Returns the name of this field.
584  */
FieldDescriptor_name(VALUE _self)585 static VALUE FieldDescriptor_name(VALUE _self) {
586   FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
587   return rb_str_maybe_null(upb_FieldDef_Name(self->fielddef));
588 }
589 
590 // Non-static, exposed to other .c files.
ruby_to_fieldtype(VALUE type)591 upb_CType ruby_to_fieldtype(VALUE type) {
592   if (TYPE(type) != T_SYMBOL) {
593     rb_raise(rb_eArgError, "Expected symbol for field type.");
594   }
595 
596 #define CONVERT(upb, ruby)                \
597   if (SYM2ID(type) == rb_intern(#ruby)) { \
598     return kUpb_CType_##upb;                \
599   }
600 
601   CONVERT(Float, float);
602   CONVERT(Double, double);
603   CONVERT(Bool, bool);
604   CONVERT(String, string);
605   CONVERT(Bytes, bytes);
606   CONVERT(Message, message);
607   CONVERT(Enum, enum);
608   CONVERT(Int32, int32);
609   CONVERT(Int64, int64);
610   CONVERT(UInt32, uint32);
611   CONVERT(UInt64, uint64);
612 
613 #undef CONVERT
614 
615   rb_raise(rb_eArgError, "Unknown field type.");
616   return 0;
617 }
618 
descriptortype_to_ruby(upb_FieldType type)619 static VALUE descriptortype_to_ruby(upb_FieldType type) {
620   switch (type) {
621 #define CONVERT(upb, ruby)        \
622   case kUpb_FieldType_##upb: \
623     return ID2SYM(rb_intern(#ruby));
624     CONVERT(Float, float);
625     CONVERT(Double, double);
626     CONVERT(Bool, bool);
627     CONVERT(String, string);
628     CONVERT(Bytes, bytes);
629     CONVERT(Message, message);
630     CONVERT(Group, group);
631     CONVERT(Enum, enum);
632     CONVERT(Int32, int32);
633     CONVERT(Int64, int64);
634     CONVERT(UInt32, uint32);
635     CONVERT(UInt64, uint64);
636     CONVERT(SInt32, sint32);
637     CONVERT(SInt64, sint64);
638     CONVERT(Fixed32, fixed32);
639     CONVERT(Fixed64, fixed64);
640     CONVERT(SFixed32, sfixed32);
641     CONVERT(SFixed64, sfixed64);
642 #undef CONVERT
643   }
644   return Qnil;
645 }
646 
647 /*
648  * call-seq:
649  *     FieldDescriptor.type => type
650  *
651  * Returns this field's type, as a Ruby symbol, or nil if not yet set.
652  *
653  * Valid field types are:
654  *     :int32, :int64, :uint32, :uint64, :float, :double, :bool, :string,
655  *     :bytes, :message.
656  */
FieldDescriptor__type(VALUE _self)657 static VALUE FieldDescriptor__type(VALUE _self) {
658   FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
659   return descriptortype_to_ruby(upb_FieldDef_Type(self->fielddef));
660 }
661 
662 /*
663  * call-seq:
664  *     FieldDescriptor.default => default
665  *
666  * Returns this field's default, as a Ruby object, or nil if not yet set.
667  */
FieldDescriptor_default(VALUE _self)668 static VALUE FieldDescriptor_default(VALUE _self) {
669   FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
670   const upb_FieldDef* f = self->fielddef;
671   upb_MessageValue default_val = {0};
672   if (upb_FieldDef_IsSubMessage(f)) {
673     return Qnil;
674   } else if (!upb_FieldDef_IsRepeated(f)) {
675     default_val = upb_FieldDef_Default(f);
676   }
677   return Convert_UpbToRuby(default_val, TypeInfo_get(self->fielddef), Qnil);
678 }
679 
680 /*
681  * call-seq:
682  *     FieldDescriptor.json_name => json_name
683  *
684  * Returns this field's json_name, as a Ruby string, or nil if not yet set.
685  */
FieldDescriptor_json_name(VALUE _self)686 static VALUE FieldDescriptor_json_name(VALUE _self) {
687   FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
688   const upb_FieldDef* f = self->fielddef;
689   const char* json_name = upb_FieldDef_JsonName(f);
690   return rb_str_new2(json_name);
691 }
692 
693 /*
694  * call-seq:
695  *     FieldDescriptor.label => label
696  *
697  * Returns this field's label (i.e., plurality), as a Ruby symbol.
698  *
699  * Valid field labels are:
700  *     :optional, :repeated
701  */
FieldDescriptor_label(VALUE _self)702 static VALUE FieldDescriptor_label(VALUE _self) {
703   FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
704   switch (upb_FieldDef_Label(self->fielddef)) {
705 #define CONVERT(upb, ruby) \
706   case kUpb_Label_##upb:    \
707     return ID2SYM(rb_intern(#ruby));
708 
709     CONVERT(Optional, optional);
710     CONVERT(Required, required);
711     CONVERT(Repeated, repeated);
712 
713 #undef CONVERT
714   }
715 
716   return Qnil;
717 }
718 
719 /*
720  * call-seq:
721  *     FieldDescriptor.number => number
722  *
723  * Returns the tag number for this field.
724  */
FieldDescriptor_number(VALUE _self)725 static VALUE FieldDescriptor_number(VALUE _self) {
726   FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
727   return INT2NUM(upb_FieldDef_Number(self->fielddef));
728 }
729 
730 /*
731  * call-seq:
732  *     FieldDescriptor.submsg_name => submsg_name
733  *
734  * Returns the name of the message or enum type corresponding to this field, if
735  * it is a message or enum field (respectively), or nil otherwise. This type
736  * name will be resolved within the context of the pool to which the containing
737  * message type is added.
738  */
FieldDescriptor_submsg_name(VALUE _self)739 static VALUE FieldDescriptor_submsg_name(VALUE _self) {
740   FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
741   switch (upb_FieldDef_CType(self->fielddef)) {
742     case kUpb_CType_Enum:
743       return rb_str_new2(
744           upb_EnumDef_FullName(upb_FieldDef_EnumSubDef(self->fielddef)));
745     case kUpb_CType_Message:
746       return rb_str_new2(
747           upb_MessageDef_FullName(upb_FieldDef_MessageSubDef(self->fielddef)));
748     default:
749       return Qnil;
750   }
751 }
752 
753 /*
754  * call-seq:
755  *     FieldDescriptor.subtype => message_or_enum_descriptor
756  *
757  * Returns the message or enum descriptor corresponding to this field's type if
758  * it is a message or enum field, respectively, or nil otherwise. Cannot be
759  * called *until* the containing message type is added to a pool (and thus
760  * resolved).
761  */
FieldDescriptor_subtype(VALUE _self)762 static VALUE FieldDescriptor_subtype(VALUE _self) {
763   FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
764   switch (upb_FieldDef_CType(self->fielddef)) {
765     case kUpb_CType_Enum:
766       return get_enumdef_obj(self->descriptor_pool,
767                              upb_FieldDef_EnumSubDef(self->fielddef));
768     case kUpb_CType_Message:
769       return get_msgdef_obj(self->descriptor_pool,
770                             upb_FieldDef_MessageSubDef(self->fielddef));
771     default:
772       return Qnil;
773   }
774 }
775 
776 /*
777  * call-seq:
778  *     FieldDescriptor.get(message) => value
779  *
780  * Returns the value set for this field on the given message. Raises an
781  * exception if message is of the wrong type.
782  */
FieldDescriptor_get(VALUE _self,VALUE msg_rb)783 static VALUE FieldDescriptor_get(VALUE _self, VALUE msg_rb) {
784   FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
785   const upb_MessageDef* m;
786 
787   Message_Get(msg_rb, &m);
788 
789   if (m != upb_FieldDef_ContainingType(self->fielddef)) {
790     rb_raise(cTypeError, "get method called on wrong message type");
791   }
792 
793   return Message_getfield(msg_rb, self->fielddef);
794 }
795 
796 /*
797  * call-seq:
798  *     FieldDescriptor.has?(message) => boolean
799  *
800  * Returns whether the value is set on the given message. Raises an
801  * exception when calling for fields that do not have presence.
802  */
FieldDescriptor_has(VALUE _self,VALUE msg_rb)803 static VALUE FieldDescriptor_has(VALUE _self, VALUE msg_rb) {
804   FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
805   const upb_MessageDef* m;
806   const upb_MessageDef* msg = Message_Get(msg_rb, &m);
807 
808   if (m != upb_FieldDef_ContainingType(self->fielddef)) {
809     rb_raise(cTypeError, "has method called on wrong message type");
810   } else if (!upb_FieldDef_HasPresence(self->fielddef)) {
811     rb_raise(rb_eArgError, "does not track presence");
812   }
813 
814   return upb_Message_Has(msg, self->fielddef) ? Qtrue : Qfalse;
815 }
816 
817 /*
818  * call-seq:
819  *     FieldDescriptor.clear(message)
820  *
821  * Clears the field from the message if it's set.
822  */
FieldDescriptor_clear(VALUE _self,VALUE msg_rb)823 static VALUE FieldDescriptor_clear(VALUE _self, VALUE msg_rb) {
824   FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
825   const upb_MessageDef* m;
826   upb_MessageDef* msg = Message_GetMutable(msg_rb, &m);
827 
828   if (m != upb_FieldDef_ContainingType(self->fielddef)) {
829     rb_raise(cTypeError, "has method called on wrong message type");
830   }
831 
832   upb_Message_ClearField(msg, self->fielddef);
833   return Qnil;
834 }
835 
836 /*
837  * call-seq:
838  *     FieldDescriptor.set(message, value)
839  *
840  * Sets the value corresponding to this field to the given value on the given
841  * message. Raises an exception if message is of the wrong type. Performs the
842  * ordinary type-checks for field setting.
843  */
FieldDescriptor_set(VALUE _self,VALUE msg_rb,VALUE value)844 static VALUE FieldDescriptor_set(VALUE _self, VALUE msg_rb, VALUE value) {
845   FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
846   const upb_MessageDef* m;
847   upb_MessageDef* msg = Message_GetMutable(msg_rb, &m);
848   upb_Arena* arena = Arena_get(Message_GetArena(msg_rb));
849   upb_MessageValue msgval;
850 
851   if (m != upb_FieldDef_ContainingType(self->fielddef)) {
852     rb_raise(cTypeError, "set method called on wrong message type");
853   }
854 
855   msgval = Convert_RubyToUpb(value, upb_FieldDef_Name(self->fielddef),
856                              TypeInfo_get(self->fielddef), arena);
857   upb_Message_Set(msg, self->fielddef, msgval, arena);
858   return Qnil;
859 }
860 
FieldDescriptor_register(VALUE module)861 static void FieldDescriptor_register(VALUE module) {
862   VALUE klass = rb_define_class_under(module, "FieldDescriptor", rb_cObject);
863   rb_define_alloc_func(klass, FieldDescriptor_alloc);
864   rb_define_method(klass, "initialize", FieldDescriptor_initialize, 3);
865   rb_define_method(klass, "name", FieldDescriptor_name, 0);
866   rb_define_method(klass, "type", FieldDescriptor__type, 0);
867   rb_define_method(klass, "default", FieldDescriptor_default, 0);
868   rb_define_method(klass, "json_name", FieldDescriptor_json_name, 0);
869   rb_define_method(klass, "label", FieldDescriptor_label, 0);
870   rb_define_method(klass, "number", FieldDescriptor_number, 0);
871   rb_define_method(klass, "submsg_name", FieldDescriptor_submsg_name, 0);
872   rb_define_method(klass, "subtype", FieldDescriptor_subtype, 0);
873   rb_define_method(klass, "has?", FieldDescriptor_has, 1);
874   rb_define_method(klass, "clear", FieldDescriptor_clear, 1);
875   rb_define_method(klass, "get", FieldDescriptor_get, 1);
876   rb_define_method(klass, "set", FieldDescriptor_set, 2);
877   rb_gc_register_address(&cFieldDescriptor);
878   cFieldDescriptor = klass;
879 }
880 
881 // -----------------------------------------------------------------------------
882 // OneofDescriptor.
883 // -----------------------------------------------------------------------------
884 
885 typedef struct {
886   const upb_OneofDef* oneofdef;
887   VALUE descriptor_pool;  // Owns the upb_OneofDef.
888 } OneofDescriptor;
889 
890 static VALUE cOneofDescriptor = Qnil;
891 
OneofDescriptor_mark(void * _self)892 static void OneofDescriptor_mark(void* _self) {
893   OneofDescriptor* self = _self;
894   rb_gc_mark(self->descriptor_pool);
895 }
896 
897 static const rb_data_type_t OneofDescriptor_type = {
898     "Google::Protobuf::OneofDescriptor",
899     {OneofDescriptor_mark, RUBY_DEFAULT_FREE, NULL},
900     .flags = RUBY_TYPED_FREE_IMMEDIATELY,
901 };
902 
ruby_to_OneofDescriptor(VALUE val)903 static OneofDescriptor* ruby_to_OneofDescriptor(VALUE val) {
904   OneofDescriptor* ret;
905   TypedData_Get_Struct(val, OneofDescriptor, &OneofDescriptor_type, ret);
906   return ret;
907 }
908 
909 /*
910  * call-seq:
911  *     OneofDescriptor.new => oneof_descriptor
912  *
913  * Creates a new, empty, oneof descriptor. The oneof may only be modified prior
914  * to being added to a message descriptor which is subsequently added to a pool.
915  */
OneofDescriptor_alloc(VALUE klass)916 static VALUE OneofDescriptor_alloc(VALUE klass) {
917   OneofDescriptor* self = ALLOC(OneofDescriptor);
918   VALUE ret = TypedData_Wrap_Struct(klass, &OneofDescriptor_type, self);
919   self->oneofdef = NULL;
920   self->descriptor_pool = Qnil;
921   return ret;
922 }
923 
924 /*
925  * call-seq:
926  *    OneofDescriptor.new(c_only_cookie, pool, ptr) => OneofDescriptor
927  *
928  * Creates a descriptor wrapper object.  May only be called from C.
929  */
OneofDescriptor_initialize(VALUE _self,VALUE cookie,VALUE descriptor_pool,VALUE ptr)930 static VALUE OneofDescriptor_initialize(VALUE _self, VALUE cookie,
931                                         VALUE descriptor_pool, VALUE ptr) {
932   OneofDescriptor* self = ruby_to_OneofDescriptor(_self);
933 
934   if (cookie != c_only_cookie) {
935     rb_raise(rb_eRuntimeError,
936              "Descriptor objects may not be created from Ruby.");
937   }
938 
939   self->descriptor_pool = descriptor_pool;
940   self->oneofdef = (const upb_OneofDef*)NUM2ULL(ptr);
941 
942   return Qnil;
943 }
944 
945 /*
946  * call-seq:
947  *     OneofDescriptor.name => name
948  *
949  * Returns the name of this oneof.
950  */
OneofDescriptor_name(VALUE _self)951 static VALUE OneofDescriptor_name(VALUE _self) {
952   OneofDescriptor* self = ruby_to_OneofDescriptor(_self);
953   return rb_str_maybe_null(upb_OneofDef_Name(self->oneofdef));
954 }
955 
956 /*
957  * call-seq:
958  *     OneofDescriptor.each(&block) => nil
959  *
960  * Iterates through fields in this oneof, yielding to the block on each one.
961  */
OneofDescriptor_each(VALUE _self)962 static VALUE OneofDescriptor_each(VALUE _self) {
963   OneofDescriptor* self = ruby_to_OneofDescriptor(_self);
964 
965   int n = upb_OneofDef_FieldCount(self->oneofdef);
966   for (int i = 0; i < n; i++) {
967     const upb_FieldDef* f = upb_OneofDef_Field(self->oneofdef, i);
968     VALUE obj = get_fielddef_obj(self->descriptor_pool, f);
969     rb_yield(obj);
970   }
971   return Qnil;
972 }
973 
OneofDescriptor_register(VALUE module)974 static void OneofDescriptor_register(VALUE module) {
975   VALUE klass = rb_define_class_under(module, "OneofDescriptor", rb_cObject);
976   rb_define_alloc_func(klass, OneofDescriptor_alloc);
977   rb_define_method(klass, "initialize", OneofDescriptor_initialize, 3);
978   rb_define_method(klass, "name", OneofDescriptor_name, 0);
979   rb_define_method(klass, "each", OneofDescriptor_each, 0);
980   rb_include_module(klass, rb_mEnumerable);
981   rb_gc_register_address(&cOneofDescriptor);
982   cOneofDescriptor = klass;
983 }
984 
985 // -----------------------------------------------------------------------------
986 // EnumDescriptor.
987 // -----------------------------------------------------------------------------
988 
989 typedef struct {
990   const upb_EnumDef* enumdef;
991   VALUE module;           // begins as nil
992   VALUE descriptor_pool;  // Owns the upb_EnumDef.
993 } EnumDescriptor;
994 
995 static VALUE cEnumDescriptor = Qnil;
996 
EnumDescriptor_mark(void * _self)997 static void EnumDescriptor_mark(void* _self) {
998   EnumDescriptor* self = _self;
999   rb_gc_mark(self->module);
1000   rb_gc_mark(self->descriptor_pool);
1001 }
1002 
1003 static const rb_data_type_t EnumDescriptor_type = {
1004     "Google::Protobuf::EnumDescriptor",
1005     {EnumDescriptor_mark, RUBY_DEFAULT_FREE, NULL},
1006     .flags = RUBY_TYPED_FREE_IMMEDIATELY,
1007 };
1008 
ruby_to_EnumDescriptor(VALUE val)1009 static EnumDescriptor* ruby_to_EnumDescriptor(VALUE val) {
1010   EnumDescriptor* ret;
1011   TypedData_Get_Struct(val, EnumDescriptor, &EnumDescriptor_type, ret);
1012   return ret;
1013 }
1014 
EnumDescriptor_alloc(VALUE klass)1015 static VALUE EnumDescriptor_alloc(VALUE klass) {
1016   EnumDescriptor* self = ALLOC(EnumDescriptor);
1017   VALUE ret = TypedData_Wrap_Struct(klass, &EnumDescriptor_type, self);
1018   self->enumdef = NULL;
1019   self->module = Qnil;
1020   self->descriptor_pool = Qnil;
1021   return ret;
1022 }
1023 
1024 // Exposed to other modules in defs.h.
EnumDescriptor_GetEnumDef(VALUE enum_desc_rb)1025 const upb_EnumDef* EnumDescriptor_GetEnumDef(VALUE enum_desc_rb) {
1026   EnumDescriptor* desc = ruby_to_EnumDescriptor(enum_desc_rb);
1027   return desc->enumdef;
1028 }
1029 
1030 /*
1031  * call-seq:
1032  *    EnumDescriptor.new(c_only_cookie, ptr) => EnumDescriptor
1033  *
1034  * Creates a descriptor wrapper object.  May only be called from C.
1035  */
EnumDescriptor_initialize(VALUE _self,VALUE cookie,VALUE descriptor_pool,VALUE ptr)1036 static VALUE EnumDescriptor_initialize(VALUE _self, VALUE cookie,
1037                                        VALUE descriptor_pool, VALUE ptr) {
1038   EnumDescriptor* self = ruby_to_EnumDescriptor(_self);
1039 
1040   if (cookie != c_only_cookie) {
1041     rb_raise(rb_eRuntimeError,
1042              "Descriptor objects may not be created from Ruby.");
1043   }
1044 
1045   self->descriptor_pool = descriptor_pool;
1046   self->enumdef = (const upb_EnumDef*)NUM2ULL(ptr);
1047 
1048   return Qnil;
1049 }
1050 
1051 /*
1052  * call-seq:
1053  *    EnumDescriptor.file_descriptor
1054  *
1055  * Returns the FileDescriptor object this enum belongs to.
1056  */
EnumDescriptor_file_descriptor(VALUE _self)1057 static VALUE EnumDescriptor_file_descriptor(VALUE _self) {
1058   EnumDescriptor* self = ruby_to_EnumDescriptor(_self);
1059   return get_filedef_obj(self->descriptor_pool,
1060                          upb_EnumDef_File(self->enumdef));
1061 }
1062 
1063 /*
1064  * call-seq:
1065  *     EnumDescriptor.name => name
1066  *
1067  * Returns the name of this enum type.
1068  */
EnumDescriptor_name(VALUE _self)1069 static VALUE EnumDescriptor_name(VALUE _self) {
1070   EnumDescriptor* self = ruby_to_EnumDescriptor(_self);
1071   return rb_str_maybe_null(upb_EnumDef_FullName(self->enumdef));
1072 }
1073 
1074 /*
1075  * call-seq:
1076  *     EnumDescriptor.lookup_name(name) => value
1077  *
1078  * Returns the numeric value corresponding to the given key name (as a Ruby
1079  * symbol), or nil if none.
1080  */
EnumDescriptor_lookup_name(VALUE _self,VALUE name)1081 static VALUE EnumDescriptor_lookup_name(VALUE _self, VALUE name) {
1082   EnumDescriptor* self = ruby_to_EnumDescriptor(_self);
1083   const char* name_str = rb_id2name(SYM2ID(name));
1084   const upb_EnumValueDef *ev =
1085       upb_EnumDef_FindValueByName(self->enumdef, name_str);
1086   if (ev) {
1087     return INT2NUM(upb_EnumValueDef_Number(ev));
1088   } else {
1089     return Qnil;
1090   }
1091 }
1092 
1093 /*
1094  * call-seq:
1095  *     EnumDescriptor.lookup_value(name) => value
1096  *
1097  * Returns the key name (as a Ruby symbol) corresponding to the integer value,
1098  * or nil if none.
1099  */
EnumDescriptor_lookup_value(VALUE _self,VALUE number)1100 static VALUE EnumDescriptor_lookup_value(VALUE _self, VALUE number) {
1101   EnumDescriptor* self = ruby_to_EnumDescriptor(_self);
1102   int32_t val = NUM2INT(number);
1103   const upb_EnumValueDef* ev = upb_EnumDef_FindValueByNumber(self->enumdef, val);
1104   if (ev) {
1105     return ID2SYM(rb_intern(upb_EnumValueDef_Name(ev)));
1106   } else {
1107     return Qnil;
1108   }
1109 }
1110 
1111 /*
1112  * call-seq:
1113  *     EnumDescriptor.each(&block)
1114  *
1115  * Iterates over key => value mappings in this enum's definition, yielding to
1116  * the block with (key, value) arguments for each one.
1117  */
EnumDescriptor_each(VALUE _self)1118 static VALUE EnumDescriptor_each(VALUE _self) {
1119   EnumDescriptor* self = ruby_to_EnumDescriptor(_self);
1120 
1121   int n = upb_EnumDef_ValueCount(self->enumdef);
1122   for (int i = 0; i < n; i++) {
1123     const upb_EnumValueDef* ev = upb_EnumDef_Value(self->enumdef, i);
1124     VALUE key = ID2SYM(rb_intern(upb_EnumValueDef_Name(ev)));
1125     VALUE number = INT2NUM(upb_EnumValueDef_Number(ev));
1126     rb_yield_values(2, key, number);
1127   }
1128 
1129   return Qnil;
1130 }
1131 
1132 /*
1133  * call-seq:
1134  *     EnumDescriptor.enummodule => module
1135  *
1136  * Returns the Ruby module corresponding to this enum type.
1137  */
EnumDescriptor_enummodule(VALUE _self)1138 static VALUE EnumDescriptor_enummodule(VALUE _self) {
1139   EnumDescriptor* self = ruby_to_EnumDescriptor(_self);
1140   if (self->module == Qnil) {
1141     self->module = build_module_from_enumdesc(_self);
1142   }
1143   return self->module;
1144 }
1145 
EnumDescriptor_register(VALUE module)1146 static void EnumDescriptor_register(VALUE module) {
1147   VALUE klass = rb_define_class_under(module, "EnumDescriptor", rb_cObject);
1148   rb_define_alloc_func(klass, EnumDescriptor_alloc);
1149   rb_define_method(klass, "initialize", EnumDescriptor_initialize, 3);
1150   rb_define_method(klass, "name", EnumDescriptor_name, 0);
1151   rb_define_method(klass, "lookup_name", EnumDescriptor_lookup_name, 1);
1152   rb_define_method(klass, "lookup_value", EnumDescriptor_lookup_value, 1);
1153   rb_define_method(klass, "each", EnumDescriptor_each, 0);
1154   rb_define_method(klass, "enummodule", EnumDescriptor_enummodule, 0);
1155   rb_define_method(klass, "file_descriptor", EnumDescriptor_file_descriptor, 0);
1156   rb_include_module(klass, rb_mEnumerable);
1157   rb_gc_register_address(&cEnumDescriptor);
1158   cEnumDescriptor = klass;
1159 }
1160 
get_def_obj(VALUE _descriptor_pool,const void * ptr,VALUE klass)1161 static VALUE get_def_obj(VALUE _descriptor_pool, const void* ptr, VALUE klass) {
1162   DescriptorPool* descriptor_pool = ruby_to_DescriptorPool(_descriptor_pool);
1163   VALUE key = ULL2NUM((intptr_t)ptr);
1164   VALUE def;
1165 
1166   def = rb_hash_aref(descriptor_pool->def_to_descriptor, key);
1167 
1168   if (ptr == NULL) {
1169     return Qnil;
1170   }
1171 
1172   if (def == Qnil) {
1173     // Lazily create wrapper object.
1174     VALUE args[3] = {c_only_cookie, _descriptor_pool, key};
1175     def = rb_class_new_instance(3, args, klass);
1176     rb_hash_aset(descriptor_pool->def_to_descriptor, key, def);
1177   }
1178 
1179   return def;
1180 }
1181 
get_msgdef_obj(VALUE descriptor_pool,const upb_MessageDef * def)1182 static VALUE get_msgdef_obj(VALUE descriptor_pool, const upb_MessageDef* def) {
1183   return get_def_obj(descriptor_pool, def, cDescriptor);
1184 }
1185 
get_enumdef_obj(VALUE descriptor_pool,const upb_EnumDef * def)1186 static VALUE get_enumdef_obj(VALUE descriptor_pool, const upb_EnumDef* def) {
1187   return get_def_obj(descriptor_pool, def, cEnumDescriptor);
1188 }
1189 
get_fielddef_obj(VALUE descriptor_pool,const upb_FieldDef * def)1190 static VALUE get_fielddef_obj(VALUE descriptor_pool, const upb_FieldDef* def) {
1191   return get_def_obj(descriptor_pool, def, cFieldDescriptor);
1192 }
1193 
get_filedef_obj(VALUE descriptor_pool,const upb_FileDef * def)1194 static VALUE get_filedef_obj(VALUE descriptor_pool, const upb_FileDef* def) {
1195   return get_def_obj(descriptor_pool, def, cFileDescriptor);
1196 }
1197 
get_oneofdef_obj(VALUE descriptor_pool,const upb_OneofDef * def)1198 static VALUE get_oneofdef_obj(VALUE descriptor_pool, const upb_OneofDef* def) {
1199   return get_def_obj(descriptor_pool, def, cOneofDescriptor);
1200 }
1201 
1202 // -----------------------------------------------------------------------------
1203 // Shared functions
1204 // -----------------------------------------------------------------------------
1205 
1206 // Functions exposed to other modules in defs.h.
1207 
Descriptor_DefToClass(const upb_MessageDef * m)1208 VALUE Descriptor_DefToClass(const upb_MessageDef* m) {
1209   const upb_DefPool* symtab = upb_FileDef_Pool(upb_MessageDef_File(m));
1210   VALUE pool = ObjectCache_Get(symtab);
1211   PBRUBY_ASSERT(pool != Qnil);
1212   VALUE desc_rb = get_msgdef_obj(pool, m);
1213   const Descriptor* desc = ruby_to_Descriptor(desc_rb);
1214   return desc->klass;
1215 }
1216 
Descriptor_GetMsgDef(VALUE desc_rb)1217 const upb_MessageDef* Descriptor_GetMsgDef(VALUE desc_rb) {
1218   const Descriptor* desc = ruby_to_Descriptor(desc_rb);
1219   return desc->msgdef;
1220 }
1221 
TypeInfo_InitArg(int argc,VALUE * argv,int skip_arg)1222 VALUE TypeInfo_InitArg(int argc, VALUE* argv, int skip_arg) {
1223   if (argc > skip_arg) {
1224     if (argc > 1 + skip_arg) {
1225       rb_raise(rb_eArgError, "Expected a maximum of %d arguments.",
1226                skip_arg + 1);
1227     }
1228     return argv[skip_arg];
1229   } else {
1230     return Qnil;
1231   }
1232 }
1233 
TypeInfo_FromClass(int argc,VALUE * argv,int skip_arg,VALUE * type_class,VALUE * init_arg)1234 TypeInfo TypeInfo_FromClass(int argc, VALUE* argv, int skip_arg,
1235                             VALUE* type_class, VALUE* init_arg) {
1236   TypeInfo ret = {ruby_to_fieldtype(argv[skip_arg])};
1237 
1238   if (ret.type == kUpb_CType_Message || ret.type == kUpb_CType_Enum) {
1239     *init_arg = TypeInfo_InitArg(argc, argv, skip_arg + 2);
1240 
1241     if (argc < 2 + skip_arg) {
1242       rb_raise(rb_eArgError, "Expected at least %d arguments for message/enum.",
1243                2 + skip_arg);
1244     }
1245 
1246     VALUE klass = argv[1 + skip_arg];
1247     VALUE desc = MessageOrEnum_GetDescriptor(klass);
1248     *type_class = klass;
1249 
1250     if (desc == Qnil) {
1251       rb_raise(rb_eArgError,
1252                "Type class has no descriptor. Please pass a "
1253                "class or enum as returned by the DescriptorPool.");
1254     }
1255 
1256     if (ret.type == kUpb_CType_Message) {
1257       ret.def.msgdef = ruby_to_Descriptor(desc)->msgdef;
1258       Message_CheckClass(klass);
1259     } else {
1260       PBRUBY_ASSERT(ret.type == kUpb_CType_Enum);
1261       ret.def.enumdef = ruby_to_EnumDescriptor(desc)->enumdef;
1262     }
1263   } else {
1264     *init_arg = TypeInfo_InitArg(argc, argv, skip_arg + 1);
1265   }
1266 
1267   return ret;
1268 }
1269 
Defs_register(VALUE module)1270 void Defs_register(VALUE module) {
1271   DescriptorPool_register(module);
1272   Descriptor_register(module);
1273   FileDescriptor_register(module);
1274   FieldDescriptor_register(module);
1275   OneofDescriptor_register(module);
1276   EnumDescriptor_register(module);
1277 
1278   rb_gc_register_address(&c_only_cookie);
1279   c_only_cookie = rb_class_new_instance(0, NULL, rb_cObject);
1280 }
1281