google-protobuf 3.21.2 → 4.29.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. checksums.yaml +4 -4
  2. data/ext/google/protobuf_c/Rakefile +3 -0
  3. data/ext/google/protobuf_c/convert.c +67 -86
  4. data/ext/google/protobuf_c/convert.h +3 -28
  5. data/ext/google/protobuf_c/defs.c +538 -77
  6. data/ext/google/protobuf_c/defs.h +3 -28
  7. data/ext/google/protobuf_c/extconf.rb +4 -4
  8. data/ext/google/protobuf_c/glue.c +72 -0
  9. data/ext/google/protobuf_c/map.c +114 -85
  10. data/ext/google/protobuf_c/map.h +12 -30
  11. data/ext/google/protobuf_c/message.c +264 -238
  12. data/ext/google/protobuf_c/message.h +11 -33
  13. data/ext/google/protobuf_c/protobuf.c +63 -187
  14. data/ext/google/protobuf_c/protobuf.h +27 -39
  15. data/ext/google/protobuf_c/repeated_field.c +72 -38
  16. data/ext/google/protobuf_c/repeated_field.h +11 -29
  17. data/ext/google/protobuf_c/ruby-upb.c +13783 -8236
  18. data/ext/google/protobuf_c/ruby-upb.h +14077 -4495
  19. data/ext/google/protobuf_c/shared_convert.c +69 -0
  20. data/ext/google/protobuf_c/shared_convert.h +26 -0
  21. data/ext/google/protobuf_c/shared_message.c +37 -0
  22. data/ext/google/protobuf_c/shared_message.h +21 -0
  23. data/ext/google/protobuf_c/third_party/utf8_range/LICENSE +1 -0
  24. data/ext/google/protobuf_c/third_party/utf8_range/utf8_range.c +467 -0
  25. data/ext/google/protobuf_c/third_party/utf8_range/utf8_range.h +20 -7
  26. data/ext/google/protobuf_c/wrap_memcpy.c +3 -26
  27. data/lib/google/protobuf/any_pb.rb +6 -8
  28. data/lib/google/protobuf/api_pb.rb +6 -26
  29. data/lib/google/protobuf/descriptor_pb.rb +23 -226
  30. data/lib/google/protobuf/duration_pb.rb +6 -8
  31. data/lib/google/protobuf/empty_pb.rb +6 -6
  32. data/lib/google/protobuf/ffi/descriptor.rb +165 -0
  33. data/lib/google/protobuf/ffi/descriptor_pool.rb +77 -0
  34. data/lib/google/protobuf/ffi/enum_descriptor.rb +173 -0
  35. data/lib/google/protobuf/ffi/ffi.rb +215 -0
  36. data/lib/google/protobuf/ffi/field_descriptor.rb +330 -0
  37. data/lib/google/protobuf/ffi/file_descriptor.rb +49 -0
  38. data/lib/google/protobuf/ffi/internal/arena.rb +60 -0
  39. data/lib/google/protobuf/ffi/internal/convert.rb +296 -0
  40. data/lib/google/protobuf/ffi/internal/pointer_helper.rb +35 -0
  41. data/lib/google/protobuf/ffi/internal/type_safety.rb +25 -0
  42. data/lib/google/protobuf/ffi/map.rb +433 -0
  43. data/lib/google/protobuf/ffi/message.rb +785 -0
  44. data/lib/google/protobuf/ffi/method_descriptor.rb +114 -0
  45. data/lib/google/protobuf/ffi/object_cache.rb +30 -0
  46. data/lib/google/protobuf/ffi/oneof_descriptor.rb +97 -0
  47. data/lib/google/protobuf/ffi/repeated_field.rb +411 -0
  48. data/lib/google/protobuf/ffi/service_descriptor.rb +107 -0
  49. data/lib/google/protobuf/field_mask_pb.rb +6 -7
  50. data/lib/google/protobuf/internal/object_cache.rb +99 -0
  51. data/lib/google/protobuf/message_exts.rb +8 -26
  52. data/lib/google/protobuf/plugin_pb.rb +25 -0
  53. data/lib/google/protobuf/repeated_field.rb +7 -31
  54. data/lib/google/protobuf/source_context_pb.rb +6 -7
  55. data/lib/google/protobuf/struct_pb.rb +6 -23
  56. data/lib/google/protobuf/timestamp_pb.rb +6 -8
  57. data/lib/google/protobuf/type_pb.rb +6 -71
  58. data/lib/google/protobuf/well_known_types.rb +5 -34
  59. data/lib/google/protobuf/wrappers_pb.rb +6 -31
  60. data/lib/google/protobuf.rb +27 -45
  61. data/lib/google/protobuf_ffi.rb +51 -0
  62. data/lib/google/protobuf_native.rb +19 -0
  63. data/lib/google/tasks/ffi.rake +100 -0
  64. metadata +92 -16
  65. data/ext/google/protobuf_c/third_party/utf8_range/naive.c +0 -92
  66. data/ext/google/protobuf_c/third_party/utf8_range/range2-neon.c +0 -157
  67. data/ext/google/protobuf_c/third_party/utf8_range/range2-sse.c +0 -170
  68. data/lib/google/protobuf/descriptor_dsl.rb +0 -465
  69. data/tests/basic.rb +0 -739
  70. data/tests/generated_code_test.rb +0 -23
  71. data/tests/stress.rb +0 -38
@@ -1,36 +1,12 @@
1
1
  // Protocol Buffers - Google's data interchange format
2
2
  // Copyright 2014 Google Inc. All rights reserved.
3
- // https://developers.google.com/protocol-buffers/
4
3
  //
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.
4
+ // Use of this source code is governed by a BSD-style
5
+ // license that can be found in the LICENSE file or at
6
+ // https://developers.google.com/open-source/licenses/bsd
30
7
 
31
8
  #include <ctype.h>
32
9
  #include <errno.h>
33
- #include <ruby/version.h>
34
10
 
35
11
  #include "convert.h"
36
12
  #include "message.h"
@@ -46,6 +22,9 @@ static VALUE get_enumdef_obj(VALUE descriptor_pool, const upb_EnumDef* def);
46
22
  static VALUE get_fielddef_obj(VALUE descriptor_pool, const upb_FieldDef* def);
47
23
  static VALUE get_filedef_obj(VALUE descriptor_pool, const upb_FileDef* def);
48
24
  static VALUE get_oneofdef_obj(VALUE descriptor_pool, const upb_OneofDef* def);
25
+ static VALUE get_servicedef_obj(VALUE descriptor_pool,
26
+ const upb_ServiceDef* def);
27
+ static VALUE get_methoddef_obj(VALUE descriptor_pool, const upb_MethodDef* def);
49
28
 
50
29
  // A distinct object that is not accessible from Ruby. We use this as a
51
30
  // constructor argument to enforce that certain objects cannot be created from
@@ -67,12 +46,14 @@ static VALUE rb_str_maybe_null(const char* s) {
67
46
  }
68
47
  return rb_str_new2(s);
69
48
  }
70
-
49
+ static ID options_instancevar_interned;
71
50
  // -----------------------------------------------------------------------------
72
51
  // DescriptorPool.
73
52
  // -----------------------------------------------------------------------------
74
53
 
75
54
  typedef struct {
55
+ // IMPORTANT: WB_PROTECTED objects must only use the RB_OBJ_WRITE()
56
+ // macro to update VALUE references, as to trigger write barriers.
76
57
  VALUE def_to_descriptor; // Hash table of def* -> Ruby descriptor.
77
58
  upb_DefPool* symtab;
78
59
  } DescriptorPool;
@@ -97,7 +78,7 @@ static void DescriptorPool_free(void* _self) {
97
78
  static const rb_data_type_t DescriptorPool_type = {
98
79
  "Google::Protobuf::DescriptorPool",
99
80
  {DescriptorPool_mark, DescriptorPool_free, NULL},
100
- .flags = RUBY_TYPED_FREE_IMMEDIATELY,
81
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
101
82
  };
102
83
 
103
84
  static DescriptorPool* ruby_to_DescriptorPool(VALUE val) {
@@ -125,11 +106,9 @@ static VALUE DescriptorPool_alloc(VALUE klass) {
125
106
  self->def_to_descriptor = Qnil;
126
107
  ret = TypedData_Wrap_Struct(klass, &DescriptorPool_type, self);
127
108
 
128
- self->def_to_descriptor = rb_hash_new();
109
+ RB_OBJ_WRITE(ret, &self->def_to_descriptor, rb_hash_new());
129
110
  self->symtab = upb_DefPool_New();
130
- ObjectCache_Add(self->symtab, ret);
131
-
132
- return ret;
111
+ return ObjectCache_TryAdd(self->symtab, ret);
133
112
  }
134
113
 
135
114
  /*
@@ -167,25 +146,37 @@ VALUE DescriptorPool_add_serialized_file(VALUE _self,
167
146
  * call-seq:
168
147
  * DescriptorPool.lookup(name) => descriptor
169
148
  *
170
- * Finds a Descriptor or EnumDescriptor by name and returns it, or nil if none
171
- * exists with the given name.
149
+ * Finds a Descriptor, EnumDescriptor or FieldDescriptor by name and returns it,
150
+ * or nil if none exists with the given name.
172
151
  */
173
152
  static VALUE DescriptorPool_lookup(VALUE _self, VALUE name) {
174
153
  DescriptorPool* self = ruby_to_DescriptorPool(_self);
175
154
  const char* name_str = get_str(name);
176
155
  const upb_MessageDef* msgdef;
177
156
  const upb_EnumDef* enumdef;
157
+ const upb_FieldDef* fielddef;
158
+ const upb_ServiceDef* servicedef;
178
159
 
179
160
  msgdef = upb_DefPool_FindMessageByName(self->symtab, name_str);
180
161
  if (msgdef) {
181
162
  return get_msgdef_obj(_self, msgdef);
182
163
  }
183
164
 
165
+ fielddef = upb_DefPool_FindExtensionByName(self->symtab, name_str);
166
+ if (fielddef) {
167
+ return get_fielddef_obj(_self, fielddef);
168
+ }
169
+
184
170
  enumdef = upb_DefPool_FindEnumByName(self->symtab, name_str);
185
171
  if (enumdef) {
186
172
  return get_enumdef_obj(_self, enumdef);
187
173
  }
188
174
 
175
+ servicedef = upb_DefPool_FindServiceByName(self->symtab, name_str);
176
+ if (servicedef) {
177
+ return get_servicedef_obj(_self, servicedef);
178
+ }
179
+
189
180
  return Qnil;
190
181
  }
191
182
 
@@ -215,6 +206,7 @@ static void DescriptorPool_register(VALUE module) {
215
206
 
216
207
  rb_gc_register_address(&generated_pool);
217
208
  generated_pool = rb_class_new_instance(0, NULL, klass);
209
+ options_instancevar_interned = rb_intern("options");
218
210
  }
219
211
 
220
212
  // -----------------------------------------------------------------------------
@@ -223,6 +215,8 @@ static void DescriptorPool_register(VALUE module) {
223
215
 
224
216
  typedef struct {
225
217
  const upb_MessageDef* msgdef;
218
+ // IMPORTANT: WB_PROTECTED objects must only use the RB_OBJ_WRITE()
219
+ // macro to update VALUE references, as to trigger write barriers.
226
220
  VALUE klass;
227
221
  VALUE descriptor_pool;
228
222
  } Descriptor;
@@ -238,7 +232,7 @@ static void Descriptor_mark(void* _self) {
238
232
  static const rb_data_type_t Descriptor_type = {
239
233
  "Google::Protobuf::Descriptor",
240
234
  {Descriptor_mark, RUBY_DEFAULT_FREE, NULL},
241
- .flags = RUBY_TYPED_FREE_IMMEDIATELY,
235
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
242
236
  };
243
237
 
244
238
  static Descriptor* ruby_to_Descriptor(VALUE val) {
@@ -247,6 +241,48 @@ static Descriptor* ruby_to_Descriptor(VALUE val) {
247
241
  return ret;
248
242
  }
249
243
 
244
+ // Decode and return a frozen instance of a Descriptor Option for the given pool
245
+ static VALUE decode_options(VALUE self, const char* option_type, int size,
246
+ const char* bytes, VALUE descriptor_pool) {
247
+ VALUE options_rb = rb_ivar_get(self, options_instancevar_interned);
248
+ if (options_rb != Qnil) {
249
+ return options_rb;
250
+ }
251
+
252
+ static const char* prefix = "google.protobuf.";
253
+ char fullname
254
+ [/*strlen(prefix)*/ 16 +
255
+ /*strln(longest option type supported e.g. "MessageOptions")*/ 14 +
256
+ /*null terminator*/ 1];
257
+
258
+ snprintf(fullname, sizeof(fullname), "%s%s", prefix, option_type);
259
+ const upb_MessageDef* msgdef = upb_DefPool_FindMessageByName(
260
+ ruby_to_DescriptorPool(descriptor_pool)->symtab, fullname);
261
+ if (!msgdef) {
262
+ rb_raise(rb_eRuntimeError, "Cannot find %s in DescriptorPool", option_type);
263
+ }
264
+
265
+ VALUE desc_rb = get_msgdef_obj(descriptor_pool, msgdef);
266
+ const Descriptor* desc = ruby_to_Descriptor(desc_rb);
267
+
268
+ options_rb = Message_decode_bytes(size, bytes, 0, desc->klass, false);
269
+
270
+ // Strip features from the options proto to keep it internal.
271
+ const upb_MessageDef* decoded_desc = NULL;
272
+ upb_Message* options = Message_GetMutable(options_rb, &decoded_desc);
273
+ PBRUBY_ASSERT(options != NULL);
274
+ PBRUBY_ASSERT(decoded_desc == msgdef);
275
+ const upb_FieldDef* field =
276
+ upb_MessageDef_FindFieldByName(decoded_desc, "features");
277
+ PBRUBY_ASSERT(field != NULL);
278
+ upb_Message_ClearFieldByDef(options, field);
279
+
280
+ Message_freeze(options_rb);
281
+
282
+ rb_ivar_set(self, options_instancevar_interned, options_rb);
283
+ return options_rb;
284
+ }
285
+
250
286
  /*
251
287
  * call-seq:
252
288
  * Descriptor.new => descriptor
@@ -280,7 +316,7 @@ static VALUE Descriptor_initialize(VALUE _self, VALUE cookie,
280
316
  "Descriptor objects may not be created from Ruby.");
281
317
  }
282
318
 
283
- self->descriptor_pool = descriptor_pool;
319
+ RB_OBJ_WRITE(_self, &self->descriptor_pool, descriptor_pool);
284
320
  self->msgdef = (const upb_MessageDef*)NUM2ULL(ptr);
285
321
 
286
322
  return Qnil;
@@ -390,11 +426,31 @@ static VALUE Descriptor_lookup_oneof(VALUE _self, VALUE name) {
390
426
  static VALUE Descriptor_msgclass(VALUE _self) {
391
427
  Descriptor* self = ruby_to_Descriptor(_self);
392
428
  if (self->klass == Qnil) {
393
- self->klass = build_class_from_descriptor(_self);
429
+ RB_OBJ_WRITE(_self, &self->klass, build_class_from_descriptor(_self));
394
430
  }
395
431
  return self->klass;
396
432
  }
397
433
 
434
+ /*
435
+ * call-seq:
436
+ * Descriptor.options => options
437
+ *
438
+ * Returns the `MessageOptions` for this `Descriptor`.
439
+ */
440
+ static VALUE Descriptor_options(VALUE _self) {
441
+ Descriptor* self = ruby_to_Descriptor(_self);
442
+ const google_protobuf_MessageOptions* opts =
443
+ upb_MessageDef_Options(self->msgdef);
444
+ upb_Arena* arena = upb_Arena_New();
445
+ size_t size;
446
+ char* serialized =
447
+ google_protobuf_MessageOptions_serialize(opts, arena, &size);
448
+ VALUE message_options = decode_options(_self, "MessageOptions", size,
449
+ serialized, self->descriptor_pool);
450
+ upb_Arena_Free(arena);
451
+ return message_options;
452
+ }
453
+
398
454
  static void Descriptor_register(VALUE module) {
399
455
  VALUE klass = rb_define_class_under(module, "Descriptor", rb_cObject);
400
456
  rb_define_alloc_func(klass, Descriptor_alloc);
@@ -406,6 +462,7 @@ static void Descriptor_register(VALUE module) {
406
462
  rb_define_method(klass, "msgclass", Descriptor_msgclass, 0);
407
463
  rb_define_method(klass, "name", Descriptor_name, 0);
408
464
  rb_define_method(klass, "file_descriptor", Descriptor_file_descriptor, 0);
465
+ rb_define_method(klass, "options", Descriptor_options, 0);
409
466
  rb_include_module(klass, rb_mEnumerable);
410
467
  rb_gc_register_address(&cDescriptor);
411
468
  cDescriptor = klass;
@@ -417,6 +474,8 @@ static void Descriptor_register(VALUE module) {
417
474
 
418
475
  typedef struct {
419
476
  const upb_FileDef* filedef;
477
+ // IMPORTANT: WB_PROTECTED objects must only use the RB_OBJ_WRITE()
478
+ // macro to update VALUE references, as to trigger write barriers.
420
479
  VALUE descriptor_pool; // Owns the upb_FileDef.
421
480
  } FileDescriptor;
422
481
 
@@ -430,7 +489,7 @@ static void FileDescriptor_mark(void* _self) {
430
489
  static const rb_data_type_t FileDescriptor_type = {
431
490
  "Google::Protobuf::FileDescriptor",
432
491
  {FileDescriptor_mark, RUBY_DEFAULT_FREE, NULL},
433
- .flags = RUBY_TYPED_FREE_IMMEDIATELY,
492
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
434
493
  };
435
494
 
436
495
  static FileDescriptor* ruby_to_FileDescriptor(VALUE val) {
@@ -451,7 +510,7 @@ static VALUE FileDescriptor_alloc(VALUE klass) {
451
510
  * call-seq:
452
511
  * FileDescriptor.new => file
453
512
  *
454
- * Returns a new file descriptor. The syntax must be set before it's passed
513
+ * Returns a new file descriptor. May
455
514
  * to a builder.
456
515
  */
457
516
  static VALUE FileDescriptor_initialize(VALUE _self, VALUE cookie,
@@ -463,7 +522,7 @@ static VALUE FileDescriptor_initialize(VALUE _self, VALUE cookie,
463
522
  "Descriptor objects may not be created from Ruby.");
464
523
  }
465
524
 
466
- self->descriptor_pool = descriptor_pool;
525
+ RB_OBJ_WRITE(_self, &self->descriptor_pool, descriptor_pool);
467
526
  self->filedef = (const upb_FileDef*)NUM2ULL(ptr);
468
527
 
469
528
  return Qnil;
@@ -483,24 +542,20 @@ static VALUE FileDescriptor_name(VALUE _self) {
483
542
 
484
543
  /*
485
544
  * call-seq:
486
- * FileDescriptor.syntax => syntax
545
+ * FileDescriptor.options => options
487
546
  *
488
- * Returns this file descriptors syntax.
489
- *
490
- * Valid syntax versions are:
491
- * :proto2 or :proto3.
547
+ * Returns the `FileOptions` for this `FileDescriptor`.
492
548
  */
493
- static VALUE FileDescriptor_syntax(VALUE _self) {
549
+ static VALUE FileDescriptor_options(VALUE _self) {
494
550
  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
- }
551
+ const google_protobuf_FileOptions* opts = upb_FileDef_Options(self->filedef);
552
+ upb_Arena* arena = upb_Arena_New();
553
+ size_t size;
554
+ char* serialized = google_protobuf_FileOptions_serialize(opts, arena, &size);
555
+ VALUE file_options = decode_options(_self, "FileOptions", size, serialized,
556
+ self->descriptor_pool);
557
+ upb_Arena_Free(arena);
558
+ return file_options;
504
559
  }
505
560
 
506
561
  static void FileDescriptor_register(VALUE module) {
@@ -508,7 +563,7 @@ static void FileDescriptor_register(VALUE module) {
508
563
  rb_define_alloc_func(klass, FileDescriptor_alloc);
509
564
  rb_define_method(klass, "initialize", FileDescriptor_initialize, 3);
510
565
  rb_define_method(klass, "name", FileDescriptor_name, 0);
511
- rb_define_method(klass, "syntax", FileDescriptor_syntax, 0);
566
+ rb_define_method(klass, "options", FileDescriptor_options, 0);
512
567
  rb_gc_register_address(&cFileDescriptor);
513
568
  cFileDescriptor = klass;
514
569
  }
@@ -519,6 +574,8 @@ static void FileDescriptor_register(VALUE module) {
519
574
 
520
575
  typedef struct {
521
576
  const upb_FieldDef* fielddef;
577
+ // IMPORTANT: WB_PROTECTED objects must only use the RB_OBJ_WRITE()
578
+ // macro to update VALUE references, as to trigger write barriers.
522
579
  VALUE descriptor_pool; // Owns the upb_FieldDef.
523
580
  } FieldDescriptor;
524
581
 
@@ -532,7 +589,7 @@ static void FieldDescriptor_mark(void* _self) {
532
589
  static const rb_data_type_t FieldDescriptor_type = {
533
590
  "Google::Protobuf::FieldDescriptor",
534
591
  {FieldDescriptor_mark, RUBY_DEFAULT_FREE, NULL},
535
- .flags = RUBY_TYPED_FREE_IMMEDIATELY,
592
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
536
593
  };
537
594
 
538
595
  static FieldDescriptor* ruby_to_FieldDescriptor(VALUE val) {
@@ -557,7 +614,7 @@ static VALUE FieldDescriptor_alloc(VALUE klass) {
557
614
 
558
615
  /*
559
616
  * call-seq:
560
- * EnumDescriptor.new(c_only_cookie, pool, ptr) => EnumDescriptor
617
+ * FieldDescriptor.new(c_only_cookie, pool, ptr) => FieldDescriptor
561
618
  *
562
619
  * Creates a descriptor wrapper object. May only be called from C.
563
620
  */
@@ -570,7 +627,7 @@ static VALUE FieldDescriptor_initialize(VALUE _self, VALUE cookie,
570
627
  "Descriptor objects may not be created from Ruby.");
571
628
  }
572
629
 
573
- self->descriptor_pool = descriptor_pool;
630
+ RB_OBJ_WRITE(_self, &self->descriptor_pool, descriptor_pool);
574
631
  self->fielddef = (const upb_FieldDef*)NUM2ULL(ptr);
575
632
 
576
633
  return Qnil;
@@ -595,7 +652,7 @@ upb_CType ruby_to_fieldtype(VALUE type) {
595
652
 
596
653
  #define CONVERT(upb, ruby) \
597
654
  if (SYM2ID(type) == rb_intern(#ruby)) { \
598
- return kUpb_CType_##upb; \
655
+ return kUpb_CType_##upb; \
599
656
  }
600
657
 
601
658
  CONVERT(Float, float);
@@ -618,7 +675,7 @@ upb_CType ruby_to_fieldtype(VALUE type) {
618
675
 
619
676
  static VALUE descriptortype_to_ruby(upb_FieldType type) {
620
677
  switch (type) {
621
- #define CONVERT(upb, ruby) \
678
+ #define CONVERT(upb, ruby) \
622
679
  case kUpb_FieldType_##upb: \
623
680
  return ID2SYM(rb_intern(#ruby));
624
681
  CONVERT(Float, float);
@@ -668,7 +725,7 @@ static VALUE FieldDescriptor__type(VALUE _self) {
668
725
  static VALUE FieldDescriptor_default(VALUE _self) {
669
726
  FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
670
727
  const upb_FieldDef* f = self->fielddef;
671
- upb_MessageValue default_val = {0};
728
+ upb_MessageValue default_val = upb_MessageValue_Zero();
672
729
  if (upb_FieldDef_IsSubMessage(f)) {
673
730
  return Qnil;
674
731
  } else if (!upb_FieldDef_IsRepeated(f)) {
@@ -677,6 +734,28 @@ static VALUE FieldDescriptor_default(VALUE _self) {
677
734
  return Convert_UpbToRuby(default_val, TypeInfo_get(self->fielddef), Qnil);
678
735
  }
679
736
 
737
+ /*
738
+ * call-seq:
739
+ * FieldDescriptor.has_presence? => bool
740
+ *
741
+ * Returns whether this field tracks presence.
742
+ */
743
+ static VALUE FieldDescriptor_has_presence(VALUE _self) {
744
+ FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
745
+ return upb_FieldDef_HasPresence(self->fielddef) ? Qtrue : Qfalse;
746
+ }
747
+
748
+ /*
749
+ * call-seq:
750
+ * FieldDescriptor.is_packed? => bool
751
+ *
752
+ * Returns whether this is a repeated field that uses packed encoding.
753
+ */
754
+ static VALUE FieldDescriptor_is_packed(VALUE _self) {
755
+ FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
756
+ return upb_FieldDef_IsPacked(self->fielddef) ? Qtrue : Qfalse;
757
+ }
758
+
680
759
  /*
681
760
  * call-seq:
682
761
  * FieldDescriptor.json_name => json_name
@@ -703,7 +782,7 @@ static VALUE FieldDescriptor_label(VALUE _self) {
703
782
  FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
704
783
  switch (upb_FieldDef_Label(self->fielddef)) {
705
784
  #define CONVERT(upb, ruby) \
706
- case kUpb_Label_##upb: \
785
+ case kUpb_Label_##upb: \
707
786
  return ID2SYM(rb_intern(#ruby));
708
787
 
709
788
  CONVERT(Optional, optional);
@@ -803,7 +882,7 @@ static VALUE FieldDescriptor_get(VALUE _self, VALUE msg_rb) {
803
882
  static VALUE FieldDescriptor_has(VALUE _self, VALUE msg_rb) {
804
883
  FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
805
884
  const upb_MessageDef* m;
806
- const upb_MessageDef* msg = Message_Get(msg_rb, &m);
885
+ const upb_Message* msg = Message_Get(msg_rb, &m);
807
886
 
808
887
  if (m != upb_FieldDef_ContainingType(self->fielddef)) {
809
888
  rb_raise(cTypeError, "has method called on wrong message type");
@@ -811,7 +890,7 @@ static VALUE FieldDescriptor_has(VALUE _self, VALUE msg_rb) {
811
890
  rb_raise(rb_eArgError, "does not track presence");
812
891
  }
813
892
 
814
- return upb_Message_Has(msg, self->fielddef) ? Qtrue : Qfalse;
893
+ return upb_Message_HasFieldByDef(msg, self->fielddef) ? Qtrue : Qfalse;
815
894
  }
816
895
 
817
896
  /*
@@ -823,13 +902,13 @@ static VALUE FieldDescriptor_has(VALUE _self, VALUE msg_rb) {
823
902
  static VALUE FieldDescriptor_clear(VALUE _self, VALUE msg_rb) {
824
903
  FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
825
904
  const upb_MessageDef* m;
826
- upb_MessageDef* msg = Message_GetMutable(msg_rb, &m);
905
+ upb_Message* msg = Message_GetMutable(msg_rb, &m);
827
906
 
828
907
  if (m != upb_FieldDef_ContainingType(self->fielddef)) {
829
908
  rb_raise(cTypeError, "has method called on wrong message type");
830
909
  }
831
910
 
832
- upb_Message_ClearField(msg, self->fielddef);
911
+ upb_Message_ClearFieldByDef(msg, self->fielddef);
833
912
  return Qnil;
834
913
  }
835
914
 
@@ -844,7 +923,7 @@ static VALUE FieldDescriptor_clear(VALUE _self, VALUE msg_rb) {
844
923
  static VALUE FieldDescriptor_set(VALUE _self, VALUE msg_rb, VALUE value) {
845
924
  FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
846
925
  const upb_MessageDef* m;
847
- upb_MessageDef* msg = Message_GetMutable(msg_rb, &m);
926
+ upb_Message* msg = Message_GetMutable(msg_rb, &m);
848
927
  upb_Arena* arena = Arena_get(Message_GetArena(msg_rb));
849
928
  upb_MessageValue msgval;
850
929
 
@@ -854,10 +933,29 @@ static VALUE FieldDescriptor_set(VALUE _self, VALUE msg_rb, VALUE value) {
854
933
 
855
934
  msgval = Convert_RubyToUpb(value, upb_FieldDef_Name(self->fielddef),
856
935
  TypeInfo_get(self->fielddef), arena);
857
- upb_Message_Set(msg, self->fielddef, msgval, arena);
936
+ upb_Message_SetFieldByDef(msg, self->fielddef, msgval, arena);
858
937
  return Qnil;
859
938
  }
860
939
 
940
+ /*
941
+ * call-seq:
942
+ * FieldDescriptor.options => options
943
+ *
944
+ * Returns the `FieldOptions` for this `FieldDescriptor`.
945
+ */
946
+ static VALUE FieldDescriptor_options(VALUE _self) {
947
+ FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
948
+ const google_protobuf_FieldOptions* opts =
949
+ upb_FieldDef_Options(self->fielddef);
950
+ upb_Arena* arena = upb_Arena_New();
951
+ size_t size;
952
+ char* serialized = google_protobuf_FieldOptions_serialize(opts, arena, &size);
953
+ VALUE field_options = decode_options(_self, "FieldOptions", size, serialized,
954
+ self->descriptor_pool);
955
+ upb_Arena_Free(arena);
956
+ return field_options;
957
+ }
958
+
861
959
  static void FieldDescriptor_register(VALUE module) {
862
960
  VALUE klass = rb_define_class_under(module, "FieldDescriptor", rb_cObject);
863
961
  rb_define_alloc_func(klass, FieldDescriptor_alloc);
@@ -865,6 +963,8 @@ static void FieldDescriptor_register(VALUE module) {
865
963
  rb_define_method(klass, "name", FieldDescriptor_name, 0);
866
964
  rb_define_method(klass, "type", FieldDescriptor__type, 0);
867
965
  rb_define_method(klass, "default", FieldDescriptor_default, 0);
966
+ rb_define_method(klass, "has_presence?", FieldDescriptor_has_presence, 0);
967
+ rb_define_method(klass, "is_packed?", FieldDescriptor_is_packed, 0);
868
968
  rb_define_method(klass, "json_name", FieldDescriptor_json_name, 0);
869
969
  rb_define_method(klass, "label", FieldDescriptor_label, 0);
870
970
  rb_define_method(klass, "number", FieldDescriptor_number, 0);
@@ -874,6 +974,7 @@ static void FieldDescriptor_register(VALUE module) {
874
974
  rb_define_method(klass, "clear", FieldDescriptor_clear, 1);
875
975
  rb_define_method(klass, "get", FieldDescriptor_get, 1);
876
976
  rb_define_method(klass, "set", FieldDescriptor_set, 2);
977
+ rb_define_method(klass, "options", FieldDescriptor_options, 0);
877
978
  rb_gc_register_address(&cFieldDescriptor);
878
979
  cFieldDescriptor = klass;
879
980
  }
@@ -884,6 +985,8 @@ static void FieldDescriptor_register(VALUE module) {
884
985
 
885
986
  typedef struct {
886
987
  const upb_OneofDef* oneofdef;
988
+ // IMPORTANT: WB_PROTECTED objects must only use the RB_OBJ_WRITE()
989
+ // macro to update VALUE references, as to trigger write barriers.
887
990
  VALUE descriptor_pool; // Owns the upb_OneofDef.
888
991
  } OneofDescriptor;
889
992
 
@@ -897,7 +1000,7 @@ static void OneofDescriptor_mark(void* _self) {
897
1000
  static const rb_data_type_t OneofDescriptor_type = {
898
1001
  "Google::Protobuf::OneofDescriptor",
899
1002
  {OneofDescriptor_mark, RUBY_DEFAULT_FREE, NULL},
900
- .flags = RUBY_TYPED_FREE_IMMEDIATELY,
1003
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
901
1004
  };
902
1005
 
903
1006
  static OneofDescriptor* ruby_to_OneofDescriptor(VALUE val) {
@@ -936,7 +1039,7 @@ static VALUE OneofDescriptor_initialize(VALUE _self, VALUE cookie,
936
1039
  "Descriptor objects may not be created from Ruby.");
937
1040
  }
938
1041
 
939
- self->descriptor_pool = descriptor_pool;
1042
+ RB_OBJ_WRITE(_self, &self->descriptor_pool, descriptor_pool);
940
1043
  self->oneofdef = (const upb_OneofDef*)NUM2ULL(ptr);
941
1044
 
942
1045
  return Qnil;
@@ -971,12 +1074,32 @@ static VALUE OneofDescriptor_each(VALUE _self) {
971
1074
  return Qnil;
972
1075
  }
973
1076
 
1077
+ /*
1078
+ * call-seq:
1079
+ * OneofDescriptor.options => options
1080
+ *
1081
+ * Returns the `OneofOptions` for this `OneofDescriptor`.
1082
+ */
1083
+ static VALUE OneOfDescriptor_options(VALUE _self) {
1084
+ OneofDescriptor* self = ruby_to_OneofDescriptor(_self);
1085
+ const google_protobuf_OneofOptions* opts =
1086
+ upb_OneofDef_Options(self->oneofdef);
1087
+ upb_Arena* arena = upb_Arena_New();
1088
+ size_t size;
1089
+ char* serialized = google_protobuf_OneofOptions_serialize(opts, arena, &size);
1090
+ VALUE oneof_options = decode_options(_self, "OneofOptions", size, serialized,
1091
+ self->descriptor_pool);
1092
+ upb_Arena_Free(arena);
1093
+ return oneof_options;
1094
+ }
1095
+
974
1096
  static void OneofDescriptor_register(VALUE module) {
975
1097
  VALUE klass = rb_define_class_under(module, "OneofDescriptor", rb_cObject);
976
1098
  rb_define_alloc_func(klass, OneofDescriptor_alloc);
977
1099
  rb_define_method(klass, "initialize", OneofDescriptor_initialize, 3);
978
1100
  rb_define_method(klass, "name", OneofDescriptor_name, 0);
979
1101
  rb_define_method(klass, "each", OneofDescriptor_each, 0);
1102
+ rb_define_method(klass, "options", OneOfDescriptor_options, 0);
980
1103
  rb_include_module(klass, rb_mEnumerable);
981
1104
  rb_gc_register_address(&cOneofDescriptor);
982
1105
  cOneofDescriptor = klass;
@@ -988,6 +1111,8 @@ static void OneofDescriptor_register(VALUE module) {
988
1111
 
989
1112
  typedef struct {
990
1113
  const upb_EnumDef* enumdef;
1114
+ // IMPORTANT: WB_PROTECTED objects must only use the RB_OBJ_WRITE()
1115
+ // macro to update VALUE references, as to trigger write barriers.
991
1116
  VALUE module; // begins as nil
992
1117
  VALUE descriptor_pool; // Owns the upb_EnumDef.
993
1118
  } EnumDescriptor;
@@ -1003,7 +1128,7 @@ static void EnumDescriptor_mark(void* _self) {
1003
1128
  static const rb_data_type_t EnumDescriptor_type = {
1004
1129
  "Google::Protobuf::EnumDescriptor",
1005
1130
  {EnumDescriptor_mark, RUBY_DEFAULT_FREE, NULL},
1006
- .flags = RUBY_TYPED_FREE_IMMEDIATELY,
1131
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
1007
1132
  };
1008
1133
 
1009
1134
  static EnumDescriptor* ruby_to_EnumDescriptor(VALUE val) {
@@ -1042,7 +1167,7 @@ static VALUE EnumDescriptor_initialize(VALUE _self, VALUE cookie,
1042
1167
  "Descriptor objects may not be created from Ruby.");
1043
1168
  }
1044
1169
 
1045
- self->descriptor_pool = descriptor_pool;
1170
+ RB_OBJ_WRITE(_self, &self->descriptor_pool, descriptor_pool);
1046
1171
  self->enumdef = (const upb_EnumDef*)NUM2ULL(ptr);
1047
1172
 
1048
1173
  return Qnil;
@@ -1060,6 +1185,17 @@ static VALUE EnumDescriptor_file_descriptor(VALUE _self) {
1060
1185
  upb_EnumDef_File(self->enumdef));
1061
1186
  }
1062
1187
 
1188
+ /*
1189
+ * call-seq:
1190
+ * EnumDescriptor.is_closed? => bool
1191
+ *
1192
+ * Returns whether this enum is open or closed.
1193
+ */
1194
+ static VALUE EnumDescriptor_is_closed(VALUE _self) {
1195
+ EnumDescriptor* self = ruby_to_EnumDescriptor(_self);
1196
+ return upb_EnumDef_IsClosed(self->enumdef) ? Qtrue : Qfalse;
1197
+ }
1198
+
1063
1199
  /*
1064
1200
  * call-seq:
1065
1201
  * EnumDescriptor.name => name
@@ -1081,7 +1217,7 @@ static VALUE EnumDescriptor_name(VALUE _self) {
1081
1217
  static VALUE EnumDescriptor_lookup_name(VALUE _self, VALUE name) {
1082
1218
  EnumDescriptor* self = ruby_to_EnumDescriptor(_self);
1083
1219
  const char* name_str = rb_id2name(SYM2ID(name));
1084
- const upb_EnumValueDef *ev =
1220
+ const upb_EnumValueDef* ev =
1085
1221
  upb_EnumDef_FindValueByName(self->enumdef, name_str);
1086
1222
  if (ev) {
1087
1223
  return INT2NUM(upb_EnumValueDef_Number(ev));
@@ -1100,7 +1236,8 @@ static VALUE EnumDescriptor_lookup_name(VALUE _self, VALUE name) {
1100
1236
  static VALUE EnumDescriptor_lookup_value(VALUE _self, VALUE number) {
1101
1237
  EnumDescriptor* self = ruby_to_EnumDescriptor(_self);
1102
1238
  int32_t val = NUM2INT(number);
1103
- const upb_EnumValueDef* ev = upb_EnumDef_FindValueByNumber(self->enumdef, val);
1239
+ const upb_EnumValueDef* ev =
1240
+ upb_EnumDef_FindValueByNumber(self->enumdef, val);
1104
1241
  if (ev) {
1105
1242
  return ID2SYM(rb_intern(upb_EnumValueDef_Name(ev)));
1106
1243
  } else {
@@ -1138,11 +1275,29 @@ static VALUE EnumDescriptor_each(VALUE _self) {
1138
1275
  static VALUE EnumDescriptor_enummodule(VALUE _self) {
1139
1276
  EnumDescriptor* self = ruby_to_EnumDescriptor(_self);
1140
1277
  if (self->module == Qnil) {
1141
- self->module = build_module_from_enumdesc(_self);
1278
+ RB_OBJ_WRITE(_self, &self->module, build_module_from_enumdesc(_self));
1142
1279
  }
1143
1280
  return self->module;
1144
1281
  }
1145
1282
 
1283
+ /*
1284
+ * call-seq:
1285
+ * EnumDescriptor.options => options
1286
+ *
1287
+ * Returns the `EnumOptions` for this `EnumDescriptor`.
1288
+ */
1289
+ static VALUE EnumDescriptor_options(VALUE _self) {
1290
+ EnumDescriptor* self = ruby_to_EnumDescriptor(_self);
1291
+ const google_protobuf_EnumOptions* opts = upb_EnumDef_Options(self->enumdef);
1292
+ upb_Arena* arena = upb_Arena_New();
1293
+ size_t size;
1294
+ char* serialized = google_protobuf_EnumOptions_serialize(opts, arena, &size);
1295
+ VALUE enum_options = decode_options(_self, "EnumOptions", size, serialized,
1296
+ self->descriptor_pool);
1297
+ upb_Arena_Free(arena);
1298
+ return enum_options;
1299
+ }
1300
+
1146
1301
  static void EnumDescriptor_register(VALUE module) {
1147
1302
  VALUE klass = rb_define_class_under(module, "EnumDescriptor", rb_cObject);
1148
1303
  rb_define_alloc_func(klass, EnumDescriptor_alloc);
@@ -1153,11 +1308,305 @@ static void EnumDescriptor_register(VALUE module) {
1153
1308
  rb_define_method(klass, "each", EnumDescriptor_each, 0);
1154
1309
  rb_define_method(klass, "enummodule", EnumDescriptor_enummodule, 0);
1155
1310
  rb_define_method(klass, "file_descriptor", EnumDescriptor_file_descriptor, 0);
1311
+ rb_define_method(klass, "is_closed?", EnumDescriptor_is_closed, 0);
1312
+ rb_define_method(klass, "options", EnumDescriptor_options, 0);
1156
1313
  rb_include_module(klass, rb_mEnumerable);
1157
1314
  rb_gc_register_address(&cEnumDescriptor);
1158
1315
  cEnumDescriptor = klass;
1159
1316
  }
1160
1317
 
1318
+ // -----------------------------------------------------------------------------
1319
+ // ServiceDescriptor
1320
+ // -----------------------------------------------------------------------------
1321
+
1322
+ typedef struct {
1323
+ const upb_ServiceDef* servicedef;
1324
+ // IMPORTANT: WB_PROTECTED objects must only use the RB_OBJ_WRITE()
1325
+ // macro to update VALUE references, as to trigger write barriers.
1326
+ VALUE module; // begins as nil
1327
+ VALUE descriptor_pool; // Owns the upb_ServiceDef.
1328
+ } ServiceDescriptor;
1329
+
1330
+ static VALUE cServiceDescriptor = Qnil;
1331
+
1332
+ static void ServiceDescriptor_mark(void* _self) {
1333
+ ServiceDescriptor* self = _self;
1334
+ rb_gc_mark(self->module);
1335
+ rb_gc_mark(self->descriptor_pool);
1336
+ }
1337
+
1338
+ static const rb_data_type_t ServiceDescriptor_type = {
1339
+ "Google::Protobuf::ServicDescriptor",
1340
+ {ServiceDescriptor_mark, RUBY_DEFAULT_FREE, NULL},
1341
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
1342
+ };
1343
+
1344
+ static ServiceDescriptor* ruby_to_ServiceDescriptor(VALUE val) {
1345
+ ServiceDescriptor* ret;
1346
+ TypedData_Get_Struct(val, ServiceDescriptor, &ServiceDescriptor_type, ret);
1347
+ return ret;
1348
+ }
1349
+
1350
+ static VALUE ServiceDescriptor_alloc(VALUE klass) {
1351
+ ServiceDescriptor* self = ALLOC(ServiceDescriptor);
1352
+ VALUE ret = TypedData_Wrap_Struct(klass, &ServiceDescriptor_type, self);
1353
+ self->servicedef = NULL;
1354
+ self->module = Qnil;
1355
+ self->descriptor_pool = Qnil;
1356
+ return ret;
1357
+ }
1358
+
1359
+ /*
1360
+ * call-seq:
1361
+ * ServiceDescriptor.new(c_only_cookie, ptr) => ServiceDescriptor
1362
+ *
1363
+ * Creates a descriptor wrapper object. May only be called from C.
1364
+ */
1365
+ static VALUE ServiceDescriptor_initialize(VALUE _self, VALUE cookie,
1366
+ VALUE descriptor_pool, VALUE ptr) {
1367
+ ServiceDescriptor* self = ruby_to_ServiceDescriptor(_self);
1368
+
1369
+ if (cookie != c_only_cookie) {
1370
+ rb_raise(rb_eRuntimeError,
1371
+ "Descriptor objects may not be created from Ruby.");
1372
+ }
1373
+
1374
+ RB_OBJ_WRITE(_self, &self->descriptor_pool, descriptor_pool);
1375
+ self->servicedef = (const upb_ServiceDef*)NUM2ULL(ptr);
1376
+
1377
+ return Qnil;
1378
+ }
1379
+
1380
+ /*
1381
+ * call-seq:
1382
+ * ServiceDescriptor.name => name
1383
+ *
1384
+ * Returns the name of this service.
1385
+ */
1386
+ static VALUE ServiceDescriptor_name(VALUE _self) {
1387
+ ServiceDescriptor* self = ruby_to_ServiceDescriptor(_self);
1388
+ return rb_str_maybe_null(upb_ServiceDef_FullName(self->servicedef));
1389
+ }
1390
+
1391
+ /*
1392
+ * call-seq:
1393
+ * ServiceDescriptor.file_descriptor
1394
+ *
1395
+ * Returns the FileDescriptor object this service belongs to.
1396
+ */
1397
+ static VALUE ServiceDescriptor_file_descriptor(VALUE _self) {
1398
+ ServiceDescriptor* self = ruby_to_ServiceDescriptor(_self);
1399
+ return get_filedef_obj(self->descriptor_pool,
1400
+ upb_ServiceDef_File(self->servicedef));
1401
+ }
1402
+
1403
+ /*
1404
+ * call-seq:
1405
+ * ServiceDescriptor.each(&block)
1406
+ *
1407
+ * Iterates over methods in this service, yielding to the block on each one.
1408
+ */
1409
+ static VALUE ServiceDescriptor_each(VALUE _self) {
1410
+ ServiceDescriptor* self = ruby_to_ServiceDescriptor(_self);
1411
+
1412
+ int n = upb_ServiceDef_MethodCount(self->servicedef);
1413
+ for (int i = 0; i < n; i++) {
1414
+ const upb_MethodDef* method = upb_ServiceDef_Method(self->servicedef, i);
1415
+ VALUE obj = get_methoddef_obj(self->descriptor_pool, method);
1416
+ rb_yield(obj);
1417
+ }
1418
+ return Qnil;
1419
+ }
1420
+
1421
+ /*
1422
+ * call-seq:
1423
+ * ServiceDescriptor.options => options
1424
+ *
1425
+ * Returns the `ServiceOptions` for this `ServiceDescriptor`.
1426
+ */
1427
+ static VALUE ServiceDescriptor_options(VALUE _self) {
1428
+ ServiceDescriptor* self = ruby_to_ServiceDescriptor(_self);
1429
+ const google_protobuf_ServiceOptions* opts =
1430
+ upb_ServiceDef_Options(self->servicedef);
1431
+ upb_Arena* arena = upb_Arena_New();
1432
+ size_t size;
1433
+ char* serialized =
1434
+ google_protobuf_ServiceOptions_serialize(opts, arena, &size);
1435
+ VALUE service_options = decode_options(_self, "ServiceOptions", size,
1436
+ serialized, self->descriptor_pool);
1437
+ upb_Arena_Free(arena);
1438
+ return service_options;
1439
+ }
1440
+
1441
+ static void ServiceDescriptor_register(VALUE module) {
1442
+ VALUE klass = rb_define_class_under(module, "ServiceDescriptor", rb_cObject);
1443
+ rb_define_alloc_func(klass, ServiceDescriptor_alloc);
1444
+ rb_define_method(klass, "initialize", ServiceDescriptor_initialize, 3);
1445
+ rb_define_method(klass, "name", ServiceDescriptor_name, 0);
1446
+ rb_define_method(klass, "each", ServiceDescriptor_each, 0);
1447
+ rb_define_method(klass, "file_descriptor", ServiceDescriptor_file_descriptor,
1448
+ 0);
1449
+ rb_define_method(klass, "options", ServiceDescriptor_options, 0);
1450
+ rb_include_module(klass, rb_mEnumerable);
1451
+ rb_gc_register_address(&cServiceDescriptor);
1452
+ cServiceDescriptor = klass;
1453
+ }
1454
+
1455
+ // -----------------------------------------------------------------------------
1456
+ // MethodDescriptor
1457
+ // -----------------------------------------------------------------------------
1458
+
1459
+ typedef struct {
1460
+ const upb_MethodDef* methoddef;
1461
+ // IMPORTANT: WB_PROTECTED objects must only use the RB_OBJ_WRITE()
1462
+ // macro to update VALUE references, as to trigger write barriers.
1463
+ VALUE module; // begins as nil
1464
+ VALUE descriptor_pool; // Owns the upb_MethodDef.
1465
+ } MethodDescriptor;
1466
+
1467
+ static VALUE cMethodDescriptor = Qnil;
1468
+
1469
+ static void MethodDescriptor_mark(void* _self) {
1470
+ MethodDescriptor* self = _self;
1471
+ rb_gc_mark(self->module);
1472
+ rb_gc_mark(self->descriptor_pool);
1473
+ }
1474
+
1475
+ static const rb_data_type_t MethodDescriptor_type = {
1476
+ "Google::Protobuf::MethodDescriptor",
1477
+ {MethodDescriptor_mark, RUBY_DEFAULT_FREE, NULL},
1478
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
1479
+ };
1480
+
1481
+ static MethodDescriptor* ruby_to_MethodDescriptor(VALUE val) {
1482
+ MethodDescriptor* ret;
1483
+ TypedData_Get_Struct(val, MethodDescriptor, &MethodDescriptor_type, ret);
1484
+ return ret;
1485
+ }
1486
+
1487
+ static VALUE MethodDescriptor_alloc(VALUE klass) {
1488
+ MethodDescriptor* self = ALLOC(MethodDescriptor);
1489
+ VALUE ret = TypedData_Wrap_Struct(klass, &MethodDescriptor_type, self);
1490
+ self->methoddef = NULL;
1491
+ self->module = Qnil;
1492
+ self->descriptor_pool = Qnil;
1493
+ return ret;
1494
+ }
1495
+
1496
+ /*
1497
+ * call-seq:
1498
+ * MethodDescriptor.new(c_only_cookie, ptr) => MethodDescriptor
1499
+ *
1500
+ * Creates a descriptor wrapper object. May only be called from C.
1501
+ */
1502
+ static VALUE MethodDescriptor_initialize(VALUE _self, VALUE cookie,
1503
+ VALUE descriptor_pool, VALUE ptr) {
1504
+ MethodDescriptor* self = ruby_to_MethodDescriptor(_self);
1505
+
1506
+ if (cookie != c_only_cookie) {
1507
+ rb_raise(rb_eRuntimeError,
1508
+ "Descriptor objects may not be created from Ruby.");
1509
+ }
1510
+
1511
+ RB_OBJ_WRITE(_self, &self->descriptor_pool, descriptor_pool);
1512
+ self->methoddef = (const upb_MethodDef*)NUM2ULL(ptr);
1513
+
1514
+ return Qnil;
1515
+ }
1516
+
1517
+ /*
1518
+ * call-seq:
1519
+ * MethodDescriptor.name => name
1520
+ *
1521
+ * Returns the name of this method
1522
+ */
1523
+ static VALUE MethodDescriptor_name(VALUE _self) {
1524
+ MethodDescriptor* self = ruby_to_MethodDescriptor(_self);
1525
+ return rb_str_maybe_null(upb_MethodDef_Name(self->methoddef));
1526
+ }
1527
+
1528
+ /*
1529
+ * call-seq:
1530
+ * MethodDescriptor.options => options
1531
+ *
1532
+ * Returns the `MethodOptions` for this `MethodDescriptor`.
1533
+ */
1534
+ static VALUE MethodDescriptor_options(VALUE _self) {
1535
+ MethodDescriptor* self = ruby_to_MethodDescriptor(_self);
1536
+ const google_protobuf_MethodOptions* opts =
1537
+ upb_MethodDef_Options(self->methoddef);
1538
+ upb_Arena* arena = upb_Arena_New();
1539
+ size_t size;
1540
+ char* serialized =
1541
+ google_protobuf_MethodOptions_serialize(opts, arena, &size);
1542
+ VALUE method_options = decode_options(_self, "MethodOptions", size,
1543
+ serialized, self->descriptor_pool);
1544
+ upb_Arena_Free(arena);
1545
+ return method_options;
1546
+ }
1547
+
1548
+ /*
1549
+ * call-seq:
1550
+ * MethodDescriptor.input_type => Descriptor
1551
+ *
1552
+ * Returns the `Descriptor` for the request message type of this method
1553
+ */
1554
+ static VALUE MethodDescriptor_input_type(VALUE _self) {
1555
+ MethodDescriptor* self = ruby_to_MethodDescriptor(_self);
1556
+ const upb_MessageDef* type = upb_MethodDef_InputType(self->methoddef);
1557
+ return get_msgdef_obj(self->descriptor_pool, type);
1558
+ }
1559
+
1560
+ /*
1561
+ * call-seq:
1562
+ * MethodDescriptor.output_type => Descriptor
1563
+ *
1564
+ * Returns the `Descriptor` for the response message type of this method
1565
+ */
1566
+ static VALUE MethodDescriptor_output_type(VALUE _self) {
1567
+ MethodDescriptor* self = ruby_to_MethodDescriptor(_self);
1568
+ const upb_MessageDef* type = upb_MethodDef_OutputType(self->methoddef);
1569
+ return get_msgdef_obj(self->descriptor_pool, type);
1570
+ }
1571
+
1572
+ /*
1573
+ * call-seq:
1574
+ * MethodDescriptor.client_streaming => bool
1575
+ *
1576
+ * Returns whether or not this is a streaming request method
1577
+ */
1578
+ static VALUE MethodDescriptor_client_streaming(VALUE _self) {
1579
+ MethodDescriptor* self = ruby_to_MethodDescriptor(_self);
1580
+ return upb_MethodDef_ClientStreaming(self->methoddef) ? Qtrue : Qfalse;
1581
+ }
1582
+
1583
+ /*
1584
+ * call-seq:
1585
+ * MethodDescriptor.server_streaming => bool
1586
+ *
1587
+ * Returns whether or not this is a streaming response method
1588
+ */
1589
+ static VALUE MethodDescriptor_server_streaming(VALUE _self) {
1590
+ MethodDescriptor* self = ruby_to_MethodDescriptor(_self);
1591
+ return upb_MethodDef_ServerStreaming(self->methoddef) ? Qtrue : Qfalse;
1592
+ }
1593
+
1594
+ static void MethodDescriptor_register(VALUE module) {
1595
+ VALUE klass = rb_define_class_under(module, "MethodDescriptor", rb_cObject);
1596
+ rb_define_alloc_func(klass, MethodDescriptor_alloc);
1597
+ rb_define_method(klass, "initialize", MethodDescriptor_initialize, 3);
1598
+ rb_define_method(klass, "name", MethodDescriptor_name, 0);
1599
+ rb_define_method(klass, "options", MethodDescriptor_options, 0);
1600
+ rb_define_method(klass, "input_type", MethodDescriptor_input_type, 0);
1601
+ rb_define_method(klass, "output_type", MethodDescriptor_output_type, 0);
1602
+ rb_define_method(klass, "client_streaming", MethodDescriptor_client_streaming,
1603
+ 0);
1604
+ rb_define_method(klass, "server_streaming", MethodDescriptor_server_streaming,
1605
+ 0);
1606
+ rb_gc_register_address(&cMethodDescriptor);
1607
+ cMethodDescriptor = klass;
1608
+ }
1609
+
1161
1610
  static VALUE get_def_obj(VALUE _descriptor_pool, const void* ptr, VALUE klass) {
1162
1611
  DescriptorPool* descriptor_pool = ruby_to_DescriptorPool(_descriptor_pool);
1163
1612
  VALUE key = ULL2NUM((intptr_t)ptr);
@@ -1199,6 +1648,16 @@ static VALUE get_oneofdef_obj(VALUE descriptor_pool, const upb_OneofDef* def) {
1199
1648
  return get_def_obj(descriptor_pool, def, cOneofDescriptor);
1200
1649
  }
1201
1650
 
1651
+ static VALUE get_servicedef_obj(VALUE descriptor_pool,
1652
+ const upb_ServiceDef* def) {
1653
+ return get_def_obj(descriptor_pool, def, cServiceDescriptor);
1654
+ }
1655
+
1656
+ static VALUE get_methoddef_obj(VALUE descriptor_pool,
1657
+ const upb_MethodDef* def) {
1658
+ return get_def_obj(descriptor_pool, def, cMethodDescriptor);
1659
+ }
1660
+
1202
1661
  // -----------------------------------------------------------------------------
1203
1662
  // Shared functions
1204
1663
  // -----------------------------------------------------------------------------
@@ -1274,6 +1733,8 @@ void Defs_register(VALUE module) {
1274
1733
  FieldDescriptor_register(module);
1275
1734
  OneofDescriptor_register(module);
1276
1735
  EnumDescriptor_register(module);
1736
+ ServiceDescriptor_register(module);
1737
+ MethodDescriptor_register(module);
1277
1738
 
1278
1739
  rb_gc_register_address(&c_only_cookie);
1279
1740
  c_only_cookie = rb_class_new_instance(0, NULL, rb_cObject);