google-protobuf 3.21.2 → 4.29.1

Sign up to get free protection for your applications and to get access to all the features.
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);