google-protobuf 3.20.0 → 4.34.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 (73) hide show
  1. checksums.yaml +4 -4
  2. data/ext/google/protobuf_c/Rakefile +3 -0
  3. data/ext/google/protobuf_c/convert.c +60 -86
  4. data/ext/google/protobuf_c/convert.h +3 -28
  5. data/ext/google/protobuf_c/defs.c +961 -157
  6. data/ext/google/protobuf_c/defs.h +3 -28
  7. data/ext/google/protobuf_c/extconf.rb +21 -11
  8. data/ext/google/protobuf_c/glue.c +135 -0
  9. data/ext/google/protobuf_c/map.c +187 -121
  10. data/ext/google/protobuf_c/map.h +12 -30
  11. data/ext/google/protobuf_c/message.c +354 -294
  12. data/ext/google/protobuf_c/message.h +11 -33
  13. data/ext/google/protobuf_c/protobuf.c +65 -188
  14. data/ext/google/protobuf_c/protobuf.h +21 -41
  15. data/ext/google/protobuf_c/repeated_field.c +145 -74
  16. data/ext/google/protobuf_c/repeated_field.h +11 -29
  17. data/ext/google/protobuf_c/ruby-upb.c +15734 -8866
  18. data/ext/google/protobuf_c/ruby-upb.h +16769 -4511
  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 +207 -0
  25. data/ext/google/protobuf_c/third_party/utf8_range/utf8_range.h +20 -7
  26. data/ext/google/protobuf_c/third_party/utf8_range/utf8_range_neon.inc +117 -0
  27. data/ext/google/protobuf_c/third_party/utf8_range/utf8_range_sse.inc +272 -0
  28. data/lib/google/protobuf/any_pb.rb +6 -8
  29. data/lib/google/protobuf/api_pb.rb +6 -26
  30. data/lib/google/protobuf/descriptor_pb.rb +27 -226
  31. data/lib/google/protobuf/duration_pb.rb +6 -8
  32. data/lib/google/protobuf/empty_pb.rb +6 -6
  33. data/lib/google/protobuf/ffi/descriptor.rb +175 -0
  34. data/lib/google/protobuf/ffi/descriptor_pool.rb +83 -0
  35. data/lib/google/protobuf/ffi/enum_descriptor.rb +183 -0
  36. data/lib/google/protobuf/ffi/ffi.rb +213 -0
  37. data/lib/google/protobuf/ffi/field_descriptor.rb +346 -0
  38. data/lib/google/protobuf/ffi/file_descriptor.rb +85 -0
  39. data/lib/google/protobuf/ffi/internal/arena.rb +60 -0
  40. data/lib/google/protobuf/ffi/internal/convert.rb +292 -0
  41. data/lib/google/protobuf/ffi/internal/pointer_helper.rb +36 -0
  42. data/lib/google/protobuf/ffi/internal/type_safety.rb +25 -0
  43. data/lib/google/protobuf/ffi/map.rb +433 -0
  44. data/lib/google/protobuf/ffi/message.rb +783 -0
  45. data/lib/google/protobuf/ffi/method_descriptor.rb +124 -0
  46. data/lib/google/protobuf/ffi/object_cache.rb +30 -0
  47. data/lib/google/protobuf/ffi/oneof_descriptor.rb +107 -0
  48. data/lib/google/protobuf/ffi/repeated_field.rb +411 -0
  49. data/lib/google/protobuf/ffi/service_descriptor.rb +117 -0
  50. data/lib/google/protobuf/field_mask_pb.rb +6 -7
  51. data/lib/google/protobuf/internal/object_cache.rb +99 -0
  52. data/lib/google/protobuf/message_exts.rb +12 -26
  53. data/lib/google/protobuf/plugin_pb.rb +25 -0
  54. data/lib/google/protobuf/repeated_field.rb +22 -33
  55. data/lib/google/protobuf/source_context_pb.rb +6 -7
  56. data/lib/google/protobuf/struct_pb.rb +6 -23
  57. data/lib/google/protobuf/timestamp_pb.rb +6 -8
  58. data/lib/google/protobuf/type_pb.rb +6 -71
  59. data/lib/google/protobuf/well_known_types.rb +5 -34
  60. data/lib/google/protobuf/wrappers_pb.rb +6 -31
  61. data/lib/google/protobuf.rb +27 -45
  62. data/lib/google/protobuf_ffi.rb +52 -0
  63. data/lib/google/protobuf_native.rb +19 -0
  64. data/lib/google/tasks/ffi.rake +100 -0
  65. metadata +103 -32
  66. data/ext/google/protobuf_c/third_party/utf8_range/naive.c +0 -92
  67. data/ext/google/protobuf_c/third_party/utf8_range/range2-neon.c +0 -157
  68. data/ext/google/protobuf_c/third_party/utf8_range/range2-sse.c +0 -170
  69. data/ext/google/protobuf_c/wrap_memcpy.c +0 -52
  70. data/lib/google/protobuf/descriptor_dsl.rb +0 -465
  71. data/tests/basic.rb +0 -670
  72. data/tests/generated_code_test.rb +0 -23
  73. 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) {
@@ -112,9 +93,15 @@ const upb_DefPool* DescriptorPool_GetSymtab(VALUE desc_pool_rb) {
112
93
  return pool->symtab;
113
94
  }
114
95
 
96
+ /**
97
+ * ruby-doc: DescriptorPool
98
+ *
99
+ * A DescriptorPool is the registry of all known Protobuf descriptor objects.
100
+ *
101
+ */
102
+
115
103
  /*
116
- * call-seq:
117
- * DescriptorPool.new => pool
104
+ * ruby-doc: DescriptorPool.new
118
105
  *
119
106
  * Creates a new, empty, descriptor pool.
120
107
  */
@@ -125,18 +112,24 @@ static VALUE DescriptorPool_alloc(VALUE klass) {
125
112
  self->def_to_descriptor = Qnil;
126
113
  ret = TypedData_Wrap_Struct(klass, &DescriptorPool_type, self);
127
114
 
128
- self->def_to_descriptor = rb_hash_new();
115
+ RB_OBJ_WRITE(ret, &self->def_to_descriptor, rb_hash_new());
129
116
  self->symtab = upb_DefPool_New();
130
- ObjectCache_Add(self->symtab, ret);
131
117
 
132
- return ret;
118
+ // Ruby treats all enums as open.
119
+ upb_DefPool_DisableClosedEnumChecking(self->symtab);
120
+
121
+ return ObjectCache_TryAdd(self->symtab, ret);
133
122
  }
134
123
 
135
124
  /*
136
- * call-seq:
137
- * DescriptorPool.add_serialized_file(serialized_file_proto)
125
+ * ruby-doc: DescriptorPool#add_serialized_file
126
+ *
127
+ * Adds the given serialized
128
+ * {https://protobuf.com/docs/descriptors#file-descriptors FileDescriptorProto}
129
+ * to the pool.
138
130
  *
139
- * Adds the given serialized FileDescriptorProto to the pool.
131
+ * @param serialized_file_proto [String]
132
+ * @return [FileDescriptor]
140
133
  */
141
134
  VALUE DescriptorPool_add_serialized_file(VALUE _self,
142
135
  VALUE serialized_file_proto) {
@@ -164,39 +157,61 @@ VALUE DescriptorPool_add_serialized_file(VALUE _self,
164
157
  }
165
158
 
166
159
  /*
167
- * call-seq:
168
- * DescriptorPool.lookup(name) => descriptor
160
+ * ruby-doc: DescriptorPool#lookup
161
+ *
162
+ * Finds a {Descriptor}, {EnumDescriptor},
163
+ * {FieldDescriptor} or {ServiceDescriptor} by
164
+ * name and returns it, or nil if none exists with the given name.
169
165
  *
170
- * Finds a Descriptor or EnumDescriptor by name and returns it, or nil if none
171
- * exists with the given name.
166
+ * @param name [String]
167
+ * @return [Descriptor,EnumDescriptor,FieldDescriptor,ServiceDescriptor]
172
168
  */
173
169
  static VALUE DescriptorPool_lookup(VALUE _self, VALUE name) {
174
170
  DescriptorPool* self = ruby_to_DescriptorPool(_self);
175
171
  const char* name_str = get_str(name);
176
172
  const upb_MessageDef* msgdef;
177
173
  const upb_EnumDef* enumdef;
174
+ const upb_FieldDef* fielddef;
175
+ const upb_ServiceDef* servicedef;
176
+ const upb_FileDef* filedef;
178
177
 
179
178
  msgdef = upb_DefPool_FindMessageByName(self->symtab, name_str);
180
179
  if (msgdef) {
181
180
  return get_msgdef_obj(_self, msgdef);
182
181
  }
183
182
 
183
+ fielddef = upb_DefPool_FindExtensionByName(self->symtab, name_str);
184
+ if (fielddef) {
185
+ return get_fielddef_obj(_self, fielddef);
186
+ }
187
+
184
188
  enumdef = upb_DefPool_FindEnumByName(self->symtab, name_str);
185
189
  if (enumdef) {
186
190
  return get_enumdef_obj(_self, enumdef);
187
191
  }
188
192
 
193
+ servicedef = upb_DefPool_FindServiceByName(self->symtab, name_str);
194
+ if (servicedef) {
195
+ return get_servicedef_obj(_self, servicedef);
196
+ }
197
+
198
+ filedef = upb_DefPool_FindFileByName(self->symtab, name_str);
199
+ if (filedef) {
200
+ return get_filedef_obj(_self, filedef);
201
+ }
202
+
189
203
  return Qnil;
190
204
  }
191
205
 
192
206
  /*
193
- * call-seq:
194
- * DescriptorPool.generated_pool => descriptor_pool
207
+ * ruby-doc: DescriptorPool.generated_pool
208
+ *
209
+ * Class method that returns the global {DescriptorPool}. This is a singleton
210
+ * into which generated-code message and enum types are registered. The user may
211
+ * also register types in this pool for convenience so that they do not have to
212
+ * hold a reference to a private pool instance.
195
213
  *
196
- * Class method that returns the global DescriptorPool. This is a singleton into
197
- * which generated-code message and enum types are registered. The user may also
198
- * register types in this pool for convenience so that they do not have to hold
199
- * a reference to a private pool instance.
214
+ * @return [DescriptorPool]
200
215
  */
201
216
  static VALUE DescriptorPool_generated_pool(VALUE _self) {
202
217
  return generated_pool;
@@ -215,6 +230,7 @@ static void DescriptorPool_register(VALUE module) {
215
230
 
216
231
  rb_gc_register_address(&generated_pool);
217
232
  generated_pool = rb_class_new_instance(0, NULL, klass);
233
+ options_instancevar_interned = rb_intern("options");
218
234
  }
219
235
 
220
236
  // -----------------------------------------------------------------------------
@@ -223,6 +239,8 @@ static void DescriptorPool_register(VALUE module) {
223
239
 
224
240
  typedef struct {
225
241
  const upb_MessageDef* msgdef;
242
+ // IMPORTANT: WB_PROTECTED objects must only use the RB_OBJ_WRITE()
243
+ // macro to update VALUE references, as to trigger write barriers.
226
244
  VALUE klass;
227
245
  VALUE descriptor_pool;
228
246
  } Descriptor;
@@ -238,7 +256,7 @@ static void Descriptor_mark(void* _self) {
238
256
  static const rb_data_type_t Descriptor_type = {
239
257
  "Google::Protobuf::Descriptor",
240
258
  {Descriptor_mark, RUBY_DEFAULT_FREE, NULL},
241
- .flags = RUBY_TYPED_FREE_IMMEDIATELY,
259
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
242
260
  };
243
261
 
244
262
  static Descriptor* ruby_to_Descriptor(VALUE val) {
@@ -247,9 +265,56 @@ static Descriptor* ruby_to_Descriptor(VALUE val) {
247
265
  return ret;
248
266
  }
249
267
 
268
+ // Decode and return a frozen instance of a Descriptor Option for the given pool
269
+ static VALUE decode_options(VALUE self, const char* option_type, int size,
270
+ const char* bytes, VALUE descriptor_pool) {
271
+ VALUE options_rb = rb_ivar_get(self, options_instancevar_interned);
272
+ if (options_rb != Qnil) {
273
+ return options_rb;
274
+ }
275
+
276
+ static const char* prefix = "google.protobuf.";
277
+ char fullname
278
+ [/*strlen(prefix)*/ 16 +
279
+ /*strln(longest option type supported e.g. "MessageOptions")*/ 14 +
280
+ /*null terminator*/ 1];
281
+
282
+ snprintf(fullname, sizeof(fullname), "%s%s", prefix, option_type);
283
+ const upb_MessageDef* msgdef = upb_DefPool_FindMessageByName(
284
+ ruby_to_DescriptorPool(descriptor_pool)->symtab, fullname);
285
+ if (!msgdef) {
286
+ rb_raise(rb_eRuntimeError, "Cannot find %s in DescriptorPool", option_type);
287
+ }
288
+
289
+ VALUE desc_rb = get_msgdef_obj(descriptor_pool, msgdef);
290
+ const Descriptor* desc = ruby_to_Descriptor(desc_rb);
291
+
292
+ options_rb = Message_decode_bytes(size, bytes, 0, desc->klass, false);
293
+
294
+ // Strip features from the options proto to keep it internal.
295
+ const upb_MessageDef* decoded_desc = NULL;
296
+ upb_Message* options = Message_GetMutable(options_rb, &decoded_desc);
297
+ PBRUBY_ASSERT(options != NULL);
298
+ PBRUBY_ASSERT(decoded_desc == msgdef);
299
+ const upb_FieldDef* field =
300
+ upb_MessageDef_FindFieldByName(decoded_desc, "features");
301
+ PBRUBY_ASSERT(field != NULL);
302
+ upb_Message_ClearFieldByDef(options, field);
303
+
304
+ Message_freeze(options_rb);
305
+
306
+ rb_ivar_set(self, options_instancevar_interned, options_rb);
307
+ return options_rb;
308
+ }
309
+
250
310
  /*
251
- * call-seq:
252
- * Descriptor.new => descriptor
311
+ * ruby-doc: Descriptor
312
+ *
313
+ * A Descriptor provides information about a given Protobuf definition.
314
+ */
315
+
316
+ /*
317
+ * ruby-doc: Descriptor.initialize
253
318
  *
254
319
  * Creates a new, empty, message type descriptor. At a minimum, its name must be
255
320
  * set before it is added to a pool. It cannot be used to create messages until
@@ -280,17 +345,18 @@ static VALUE Descriptor_initialize(VALUE _self, VALUE cookie,
280
345
  "Descriptor objects may not be created from Ruby.");
281
346
  }
282
347
 
283
- self->descriptor_pool = descriptor_pool;
348
+ RB_OBJ_WRITE(_self, &self->descriptor_pool, descriptor_pool);
284
349
  self->msgdef = (const upb_MessageDef*)NUM2ULL(ptr);
285
350
 
286
351
  return Qnil;
287
352
  }
288
353
 
289
354
  /*
290
- * call-seq:
291
- * Descriptor.file_descriptor
355
+ * ruby-doc: Descriptor#file_descriptor
356
+ *
357
+ * Returns the {FileDescriptor} object this message belongs to.
292
358
  *
293
- * Returns the FileDescriptor object this message belongs to.
359
+ * @return [FileDescriptor]
294
360
  */
295
361
  static VALUE Descriptor_file_descriptor(VALUE _self) {
296
362
  Descriptor* self = ruby_to_Descriptor(_self);
@@ -299,11 +365,12 @@ static VALUE Descriptor_file_descriptor(VALUE _self) {
299
365
  }
300
366
 
301
367
  /*
302
- * call-seq:
303
- * Descriptor.name => name
368
+ * ruby-doc: Descriptor#name
304
369
  *
305
370
  * Returns the name of this message type as a fully-qualified string (e.g.,
306
371
  * My.Package.MessageType).
372
+ *
373
+ * @return [String]
307
374
  */
308
375
  static VALUE Descriptor_name(VALUE _self) {
309
376
  Descriptor* self = ruby_to_Descriptor(_self);
@@ -311,10 +378,12 @@ static VALUE Descriptor_name(VALUE _self) {
311
378
  }
312
379
 
313
380
  /*
314
- * call-seq:
315
- * Descriptor.each(&block)
381
+ * ruby-doc: Descriptor#each
316
382
  *
317
383
  * Iterates over fields in this message type, yielding to the block on each one.
384
+ *
385
+ * @yield [FieldDescriptor]
386
+ * @return [nil]
318
387
  */
319
388
  static VALUE Descriptor_each(VALUE _self) {
320
389
  Descriptor* self = ruby_to_Descriptor(_self);
@@ -329,11 +398,13 @@ static VALUE Descriptor_each(VALUE _self) {
329
398
  }
330
399
 
331
400
  /*
332
- * call-seq:
333
- * Descriptor.lookup(name) => FieldDescriptor
401
+ * ruby-doc: Descriptor#lookup
334
402
  *
335
403
  * Returns the field descriptor for the field with the given name, if present,
336
404
  * or nil if none.
405
+ *
406
+ * @param name [String]
407
+ * @return [FieldDescriptor]
337
408
  */
338
409
  static VALUE Descriptor_lookup(VALUE _self, VALUE name) {
339
410
  Descriptor* self = ruby_to_Descriptor(_self);
@@ -346,11 +417,13 @@ static VALUE Descriptor_lookup(VALUE _self, VALUE name) {
346
417
  }
347
418
 
348
419
  /*
349
- * call-seq:
350
- * Descriptor.each_oneof(&block) => nil
420
+ * ruby-doc: Descriptor#each_oneof
351
421
  *
352
422
  * Invokes the given block for each oneof in this message type, passing the
353
- * corresponding OneofDescriptor.
423
+ * corresponding {OneofDescriptor}.
424
+ *
425
+ * @yield [OneofDescriptor]
426
+ * @return [nil]
354
427
  */
355
428
  static VALUE Descriptor_each_oneof(VALUE _self) {
356
429
  Descriptor* self = ruby_to_Descriptor(_self);
@@ -365,11 +438,13 @@ static VALUE Descriptor_each_oneof(VALUE _self) {
365
438
  }
366
439
 
367
440
  /*
368
- * call-seq:
369
- * Descriptor.lookup_oneof(name) => OneofDescriptor
441
+ * ruby-doc: Descriptor#lookup_oneof
370
442
  *
371
443
  * Returns the oneof descriptor for the oneof with the given name, if present,
372
444
  * or nil if none.
445
+ *
446
+ * @param name [String]
447
+ * @return [OneofDescriptor]
373
448
  */
374
449
  static VALUE Descriptor_lookup_oneof(VALUE _self, VALUE name) {
375
450
  Descriptor* self = ruby_to_Descriptor(_self);
@@ -382,19 +457,67 @@ static VALUE Descriptor_lookup_oneof(VALUE _self, VALUE name) {
382
457
  }
383
458
 
384
459
  /*
385
- * call-seq:
386
- * Descriptor.msgclass => message_klass
460
+ * ruby-doc: Descriptor#msgclass
387
461
  *
388
462
  * Returns the Ruby class created for this message type.
463
+ *
464
+ * @return [Class<Google::Protobuf::AbstractMessage>]
389
465
  */
390
466
  static VALUE Descriptor_msgclass(VALUE _self) {
391
467
  Descriptor* self = ruby_to_Descriptor(_self);
392
468
  if (self->klass == Qnil) {
393
- self->klass = build_class_from_descriptor(_self);
469
+ RB_OBJ_WRITE(_self, &self->klass, build_class_from_descriptor(_self));
394
470
  }
395
471
  return self->klass;
396
472
  }
397
473
 
474
+ /*
475
+ * ruby-doc: Descriptor#options
476
+ *
477
+ * Returns the
478
+ * {https://github.com/protocolbuffers/protobuf/blob/v30.2/src/google/protobuf/descriptor.proto#L571
479
+ * MessageOptions} for this {Descriptor}.
480
+ *
481
+ * @return [MessageOptions]
482
+ */
483
+ static VALUE Descriptor_options(VALUE _self) {
484
+ Descriptor* self = ruby_to_Descriptor(_self);
485
+ const google_protobuf_MessageOptions* opts =
486
+ upb_MessageDef_Options(self->msgdef);
487
+ upb_Arena* arena = upb_Arena_New();
488
+ size_t size;
489
+ char* serialized =
490
+ google_protobuf_MessageOptions_serialize(opts, arena, &size);
491
+ VALUE message_options = decode_options(_self, "MessageOptions", size,
492
+ serialized, self->descriptor_pool);
493
+ upb_Arena_Free(arena);
494
+ return message_options;
495
+ }
496
+
497
+ /*
498
+ * ruby-doc: Descriptor#to_proto
499
+ *
500
+ * Returns the
501
+ * {https://github.com/protocolbuffers/protobuf/blob/v30.2/src/google/protobuf/descriptor.proto#L147
502
+ * DescriptorProto} of this {Descriptor}.
503
+ *
504
+ * @return [DescriptorProto]
505
+ */
506
+ static VALUE Descriptor_to_proto(VALUE _self) {
507
+ Descriptor* self = ruby_to_Descriptor(_self);
508
+ upb_Arena* arena = upb_Arena_New();
509
+ google_protobuf_DescriptorProto* proto =
510
+ upb_MessageDef_ToProto(self->msgdef, arena);
511
+ size_t size;
512
+ const char* serialized =
513
+ google_protobuf_DescriptorProto_serialize(proto, arena, &size);
514
+ VALUE proto_class = rb_path2class("Google::Protobuf::DescriptorProto");
515
+ VALUE proto_rb =
516
+ Message_decode_bytes(size, serialized, 0, proto_class, false);
517
+ upb_Arena_Free(arena);
518
+ return proto_rb;
519
+ }
520
+
398
521
  static void Descriptor_register(VALUE module) {
399
522
  VALUE klass = rb_define_class_under(module, "Descriptor", rb_cObject);
400
523
  rb_define_alloc_func(klass, Descriptor_alloc);
@@ -406,6 +529,8 @@ static void Descriptor_register(VALUE module) {
406
529
  rb_define_method(klass, "msgclass", Descriptor_msgclass, 0);
407
530
  rb_define_method(klass, "name", Descriptor_name, 0);
408
531
  rb_define_method(klass, "file_descriptor", Descriptor_file_descriptor, 0);
532
+ rb_define_method(klass, "options", Descriptor_options, 0);
533
+ rb_define_method(klass, "to_proto", Descriptor_to_proto, 0);
409
534
  rb_include_module(klass, rb_mEnumerable);
410
535
  rb_gc_register_address(&cDescriptor);
411
536
  cDescriptor = klass;
@@ -417,6 +542,8 @@ static void Descriptor_register(VALUE module) {
417
542
 
418
543
  typedef struct {
419
544
  const upb_FileDef* filedef;
545
+ // IMPORTANT: WB_PROTECTED objects must only use the RB_OBJ_WRITE()
546
+ // macro to update VALUE references, as to trigger write barriers.
420
547
  VALUE descriptor_pool; // Owns the upb_FileDef.
421
548
  } FileDescriptor;
422
549
 
@@ -430,7 +557,7 @@ static void FileDescriptor_mark(void* _self) {
430
557
  static const rb_data_type_t FileDescriptor_type = {
431
558
  "Google::Protobuf::FileDescriptor",
432
559
  {FileDescriptor_mark, RUBY_DEFAULT_FREE, NULL},
433
- .flags = RUBY_TYPED_FREE_IMMEDIATELY,
560
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
434
561
  };
435
562
 
436
563
  static FileDescriptor* ruby_to_FileDescriptor(VALUE val) {
@@ -447,11 +574,17 @@ static VALUE FileDescriptor_alloc(VALUE klass) {
447
574
  return ret;
448
575
  }
449
576
 
577
+ /**
578
+ * ruby-doc: FileDescriptor
579
+ *
580
+ * A FileDescriptor provides information about all Protobuf definitions in a
581
+ * particular file.
582
+ */
583
+
450
584
  /*
451
- * call-seq:
452
- * FileDescriptor.new => file
585
+ * ruby-doc: FileDescriptor#initialize
453
586
  *
454
- * Returns a new file descriptor. The syntax must be set before it's passed
587
+ * Returns a new file descriptor. May
455
588
  * to a builder.
456
589
  */
457
590
  static VALUE FileDescriptor_initialize(VALUE _self, VALUE cookie,
@@ -463,17 +596,18 @@ static VALUE FileDescriptor_initialize(VALUE _self, VALUE cookie,
463
596
  "Descriptor objects may not be created from Ruby.");
464
597
  }
465
598
 
466
- self->descriptor_pool = descriptor_pool;
599
+ RB_OBJ_WRITE(_self, &self->descriptor_pool, descriptor_pool);
467
600
  self->filedef = (const upb_FileDef*)NUM2ULL(ptr);
468
601
 
469
602
  return Qnil;
470
603
  }
471
604
 
472
605
  /*
473
- * call-seq:
474
- * FileDescriptor.name => name
606
+ * ruby-doc: FileDescriptor#name
475
607
  *
476
608
  * Returns the name of the file.
609
+ *
610
+ * @return [String]
477
611
  */
478
612
  static VALUE FileDescriptor_name(VALUE _self) {
479
613
  FileDescriptor* self = ruby_to_FileDescriptor(_self);
@@ -482,25 +616,51 @@ static VALUE FileDescriptor_name(VALUE _self) {
482
616
  }
483
617
 
484
618
  /*
485
- * call-seq:
486
- * FileDescriptor.syntax => syntax
619
+ * ruby-doc: FileDescriptor#options
487
620
  *
488
- * Returns this file descriptors syntax.
621
+ * Returns the
622
+ * {https://github.com/protocolbuffers/protobuf/blob/v30.2/src/google/protobuf/descriptor.proto#L442
623
+ * FileOptions} for this {FileDescriptor}.
489
624
  *
490
- * Valid syntax versions are:
491
- * :proto2 or :proto3.
625
+ * @return [FileOptions]
492
626
  */
493
- static VALUE FileDescriptor_syntax(VALUE _self) {
627
+ static VALUE FileDescriptor_options(VALUE _self) {
494
628
  FileDescriptor* self = ruby_to_FileDescriptor(_self);
629
+ const google_protobuf_FileOptions* opts = upb_FileDef_Options(self->filedef);
630
+ upb_Arena* arena = upb_Arena_New();
631
+ size_t size;
632
+ char* serialized = google_protobuf_FileOptions_serialize(opts, arena, &size);
633
+ VALUE file_options = decode_options(_self, "FileOptions", size, serialized,
634
+ self->descriptor_pool);
635
+ upb_Arena_Free(arena);
636
+ return file_options;
637
+ }
495
638
 
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
- }
639
+ /*
640
+ * ruby-doc: FileDescriptor#to_proto
641
+ *
642
+ * Returns the
643
+ * {https://github.com/protocolbuffers/protobuf/blob/v30.2/src/google/protobuf/descriptor.proto#L104
644
+ * FileDescriptorProto} of this {FileDescriptor}.
645
+ *
646
+ * @return [FileDescriptorProto]
647
+ */
648
+ static VALUE FileDescriptor_to_proto(VALUE _self) {
649
+ FileDescriptor* self = ruby_to_FileDescriptor(_self);
650
+ upb_Arena* arena = upb_Arena_New();
651
+ google_protobuf_FileDescriptorProto* file_proto =
652
+ upb_FileDef_ToProto(self->filedef, arena);
653
+
654
+ size_t size;
655
+ const char* serialized =
656
+ google_protobuf_FileDescriptorProto_serialize(file_proto, arena, &size);
657
+
658
+ VALUE file_proto_class =
659
+ rb_path2class("Google::Protobuf::FileDescriptorProto");
660
+ VALUE proto_rb =
661
+ Message_decode_bytes(size, serialized, 0, file_proto_class, false);
662
+ upb_Arena_Free(arena);
663
+ return proto_rb;
504
664
  }
505
665
 
506
666
  static void FileDescriptor_register(VALUE module) {
@@ -508,7 +668,8 @@ static void FileDescriptor_register(VALUE module) {
508
668
  rb_define_alloc_func(klass, FileDescriptor_alloc);
509
669
  rb_define_method(klass, "initialize", FileDescriptor_initialize, 3);
510
670
  rb_define_method(klass, "name", FileDescriptor_name, 0);
511
- rb_define_method(klass, "syntax", FileDescriptor_syntax, 0);
671
+ rb_define_method(klass, "options", FileDescriptor_options, 0);
672
+ rb_define_method(klass, "to_proto", FileDescriptor_to_proto, 0);
512
673
  rb_gc_register_address(&cFileDescriptor);
513
674
  cFileDescriptor = klass;
514
675
  }
@@ -519,6 +680,8 @@ static void FileDescriptor_register(VALUE module) {
519
680
 
520
681
  typedef struct {
521
682
  const upb_FieldDef* fielddef;
683
+ // IMPORTANT: WB_PROTECTED objects must only use the RB_OBJ_WRITE()
684
+ // macro to update VALUE references, as to trigger write barriers.
522
685
  VALUE descriptor_pool; // Owns the upb_FieldDef.
523
686
  } FieldDescriptor;
524
687
 
@@ -532,7 +695,7 @@ static void FieldDescriptor_mark(void* _self) {
532
695
  static const rb_data_type_t FieldDescriptor_type = {
533
696
  "Google::Protobuf::FieldDescriptor",
534
697
  {FieldDescriptor_mark, RUBY_DEFAULT_FREE, NULL},
535
- .flags = RUBY_TYPED_FREE_IMMEDIATELY,
698
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
536
699
  };
537
700
 
538
701
  static FieldDescriptor* ruby_to_FieldDescriptor(VALUE val) {
@@ -541,9 +704,15 @@ static FieldDescriptor* ruby_to_FieldDescriptor(VALUE val) {
541
704
  return ret;
542
705
  }
543
706
 
707
+ /**
708
+ * ruby-doc: FieldDescriptor
709
+ *
710
+ * A FieldDescriptor provides information about the Protobuf definition of a
711
+ * field inside a {Descriptor}.
712
+ */
713
+
544
714
  /*
545
- * call-seq:
546
- * FieldDescriptor.new => field
715
+ * ruby-doc: FieldDescriptor#initialize
547
716
  *
548
717
  * Returns a new field descriptor. Its name, type, etc. must be set before it is
549
718
  * added to a message type.
@@ -557,7 +726,7 @@ static VALUE FieldDescriptor_alloc(VALUE klass) {
557
726
 
558
727
  /*
559
728
  * call-seq:
560
- * EnumDescriptor.new(c_only_cookie, pool, ptr) => EnumDescriptor
729
+ * FieldDescriptor.new(c_only_cookie, pool, ptr) => FieldDescriptor
561
730
  *
562
731
  * Creates a descriptor wrapper object. May only be called from C.
563
732
  */
@@ -570,17 +739,18 @@ static VALUE FieldDescriptor_initialize(VALUE _self, VALUE cookie,
570
739
  "Descriptor objects may not be created from Ruby.");
571
740
  }
572
741
 
573
- self->descriptor_pool = descriptor_pool;
742
+ RB_OBJ_WRITE(_self, &self->descriptor_pool, descriptor_pool);
574
743
  self->fielddef = (const upb_FieldDef*)NUM2ULL(ptr);
575
744
 
576
745
  return Qnil;
577
746
  }
578
747
 
579
748
  /*
580
- * call-seq:
581
- * FieldDescriptor.name => name
749
+ * ruby-doc: FieldDescriptor#name
582
750
  *
583
751
  * Returns the name of this field.
752
+ *
753
+ * @return [String]
584
754
  */
585
755
  static VALUE FieldDescriptor_name(VALUE _self) {
586
756
  FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
@@ -595,7 +765,7 @@ upb_CType ruby_to_fieldtype(VALUE type) {
595
765
 
596
766
  #define CONVERT(upb, ruby) \
597
767
  if (SYM2ID(type) == rb_intern(#ruby)) { \
598
- return kUpb_CType_##upb; \
768
+ return kUpb_CType_##upb; \
599
769
  }
600
770
 
601
771
  CONVERT(Float, float);
@@ -618,7 +788,7 @@ upb_CType ruby_to_fieldtype(VALUE type) {
618
788
 
619
789
  static VALUE descriptortype_to_ruby(upb_FieldType type) {
620
790
  switch (type) {
621
- #define CONVERT(upb, ruby) \
791
+ #define CONVERT(upb, ruby) \
622
792
  case kUpb_FieldType_##upb: \
623
793
  return ID2SYM(rb_intern(#ruby));
624
794
  CONVERT(Float, float);
@@ -645,14 +815,15 @@ static VALUE descriptortype_to_ruby(upb_FieldType type) {
645
815
  }
646
816
 
647
817
  /*
648
- * call-seq:
649
- * FieldDescriptor.type => type
818
+ * ruby-doc: FieldDescriptor#type
650
819
  *
651
820
  * Returns this field's type, as a Ruby symbol, or nil if not yet set.
652
821
  *
653
822
  * Valid field types are:
654
823
  * :int32, :int64, :uint32, :uint64, :float, :double, :bool, :string,
655
824
  * :bytes, :message.
825
+ *
826
+ * @return [Symbol]
656
827
  */
657
828
  static VALUE FieldDescriptor__type(VALUE _self) {
658
829
  FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
@@ -660,15 +831,16 @@ static VALUE FieldDescriptor__type(VALUE _self) {
660
831
  }
661
832
 
662
833
  /*
663
- * call-seq:
664
- * FieldDescriptor.default => default
834
+ * ruby-doc: FieldDescriptor#default
665
835
  *
666
836
  * Returns this field's default, as a Ruby object, or nil if not yet set.
837
+ *
838
+ * @return [Object,nil]
667
839
  */
668
840
  static VALUE FieldDescriptor_default(VALUE _self) {
669
841
  FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
670
842
  const upb_FieldDef* f = self->fielddef;
671
- upb_MessageValue default_val = {0};
843
+ upb_MessageValue default_val = upb_MessageValue_Zero();
672
844
  if (upb_FieldDef_IsSubMessage(f)) {
673
845
  return Qnil;
674
846
  } else if (!upb_FieldDef_IsRepeated(f)) {
@@ -678,10 +850,57 @@ static VALUE FieldDescriptor_default(VALUE _self) {
678
850
  }
679
851
 
680
852
  /*
681
- * call-seq:
682
- * FieldDescriptor.json_name => json_name
853
+ * ruby-doc: FieldDescriptor.has_presence?
854
+ *
855
+ * Returns whether this field tracks presence.
856
+ *
857
+ * @return [Boolean]
858
+ */
859
+ static VALUE FieldDescriptor_has_presence(VALUE _self) {
860
+ FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
861
+ return upb_FieldDef_HasPresence(self->fielddef) ? Qtrue : Qfalse;
862
+ }
863
+
864
+ /*
865
+ * ruby-doc: FieldDescriptor#required?
866
+ *
867
+ * Returns whether this is a required field.
868
+ *
869
+ * @return [Boolean]
870
+ */
871
+ static VALUE FieldDescriptor_is_required(VALUE _self) {
872
+ FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
873
+ return upb_FieldDef_IsRequired(self->fielddef) ? Qtrue : Qfalse;
874
+ }
875
+
876
+ /*
877
+ * ruby-doc: FieldDescriptor#repeated?
878
+ *
879
+ * Returns whether this is a repeated field.
880
+ * @return [Boolean]
881
+ */
882
+ static VALUE FieldDescriptor_is_repeated(VALUE _self) {
883
+ FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
884
+ return upb_FieldDef_IsRepeated(self->fielddef) ? Qtrue : Qfalse;
885
+ }
886
+
887
+ /*
888
+ * ruby-doc: FieldDescriptor#is_packed?
889
+ *
890
+ * Returns whether this is a repeated field that uses packed encoding.
891
+ * @return [Boolean]
892
+ */
893
+ static VALUE FieldDescriptor_is_packed(VALUE _self) {
894
+ FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
895
+ return upb_FieldDef_IsPacked(self->fielddef) ? Qtrue : Qfalse;
896
+ }
897
+
898
+ /*
899
+ * ruby-doc: FieldDescriptor#json_name
683
900
  *
684
901
  * Returns this field's json_name, as a Ruby string, or nil if not yet set.
902
+ *
903
+ * @return [String,nil]
685
904
  */
686
905
  static VALUE FieldDescriptor_json_name(VALUE _self) {
687
906
  FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
@@ -691,19 +910,20 @@ static VALUE FieldDescriptor_json_name(VALUE _self) {
691
910
  }
692
911
 
693
912
  /*
694
- * call-seq:
695
- * FieldDescriptor.label => label
913
+ * ruby-doc: FieldDescriptor#label
696
914
  *
697
915
  * Returns this field's label (i.e., plurality), as a Ruby symbol.
698
- *
699
916
  * Valid field labels are:
700
- * :optional, :repeated
917
+ * :optional, :repeated
918
+ *
919
+ * @return [Symbol]
920
+ * @deprecated Use {#repeated?} or {#required?} instead.
701
921
  */
702
922
  static VALUE FieldDescriptor_label(VALUE _self) {
703
923
  FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
704
924
  switch (upb_FieldDef_Label(self->fielddef)) {
705
925
  #define CONVERT(upb, ruby) \
706
- case kUpb_Label_##upb: \
926
+ case kUpb_Label_##upb: \
707
927
  return ID2SYM(rb_intern(#ruby));
708
928
 
709
929
  CONVERT(Optional, optional);
@@ -717,10 +937,11 @@ static VALUE FieldDescriptor_label(VALUE _self) {
717
937
  }
718
938
 
719
939
  /*
720
- * call-seq:
721
- * FieldDescriptor.number => number
940
+ * ruby-doc: FieldDescriptor#number
722
941
  *
723
942
  * Returns the tag number for this field.
943
+ *
944
+ * @return [Integer]
724
945
  */
725
946
  static VALUE FieldDescriptor_number(VALUE _self) {
726
947
  FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
@@ -728,13 +949,14 @@ static VALUE FieldDescriptor_number(VALUE _self) {
728
949
  }
729
950
 
730
951
  /*
731
- * call-seq:
732
- * FieldDescriptor.submsg_name => submsg_name
952
+ * ruby-doc: FieldDescriptor#submsg_name
733
953
  *
734
954
  * Returns the name of the message or enum type corresponding to this field, if
735
955
  * it is a message or enum field (respectively), or nil otherwise. This type
736
956
  * name will be resolved within the context of the pool to which the containing
737
957
  * message type is added.
958
+ *
959
+ * @return [String,nil]
738
960
  */
739
961
  static VALUE FieldDescriptor_submsg_name(VALUE _self) {
740
962
  FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
@@ -751,13 +973,14 @@ static VALUE FieldDescriptor_submsg_name(VALUE _self) {
751
973
  }
752
974
 
753
975
  /*
754
- * call-seq:
755
- * FieldDescriptor.subtype => message_or_enum_descriptor
976
+ * ruby-doc: FieldDescriptor#subtype
756
977
  *
757
978
  * Returns the message or enum descriptor corresponding to this field's type if
758
979
  * it is a message or enum field, respectively, or nil otherwise. Cannot be
759
980
  * called *until* the containing message type is added to a pool (and thus
760
981
  * resolved).
982
+ *
983
+ * @return [Descriptor,EnumDescriptor,nil]
761
984
  */
762
985
  static VALUE FieldDescriptor_subtype(VALUE _self) {
763
986
  FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
@@ -774,11 +997,13 @@ static VALUE FieldDescriptor_subtype(VALUE _self) {
774
997
  }
775
998
 
776
999
  /*
777
- * call-seq:
778
- * FieldDescriptor.get(message) => value
1000
+ * ruby-doc: FieldDescriptor#get
779
1001
  *
780
1002
  * Returns the value set for this field on the given message. Raises an
781
1003
  * exception if message is of the wrong type.
1004
+ *
1005
+ * @param message [AbstractMessage]
1006
+ * @return [Object]
782
1007
  */
783
1008
  static VALUE FieldDescriptor_get(VALUE _self, VALUE msg_rb) {
784
1009
  FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
@@ -794,16 +1019,18 @@ static VALUE FieldDescriptor_get(VALUE _self, VALUE msg_rb) {
794
1019
  }
795
1020
 
796
1021
  /*
797
- * call-seq:
798
- * FieldDescriptor.has?(message) => boolean
1022
+ * ruby-doc: FieldDescriptor.has?
799
1023
  *
800
1024
  * Returns whether the value is set on the given message. Raises an
801
1025
  * exception when calling for fields that do not have presence.
1026
+ *
1027
+ * @param message [AbstractMessage]
1028
+ * @return [Boolean]
802
1029
  */
803
1030
  static VALUE FieldDescriptor_has(VALUE _self, VALUE msg_rb) {
804
1031
  FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
805
1032
  const upb_MessageDef* m;
806
- const upb_MessageDef* msg = Message_Get(msg_rb, &m);
1033
+ const upb_Message* msg = Message_Get(msg_rb, &m);
807
1034
 
808
1035
  if (m != upb_FieldDef_ContainingType(self->fielddef)) {
809
1036
  rb_raise(cTypeError, "has method called on wrong message type");
@@ -811,40 +1038,44 @@ static VALUE FieldDescriptor_has(VALUE _self, VALUE msg_rb) {
811
1038
  rb_raise(rb_eArgError, "does not track presence");
812
1039
  }
813
1040
 
814
- return upb_Message_Has(msg, self->fielddef) ? Qtrue : Qfalse;
1041
+ return upb_Message_HasFieldByDef(msg, self->fielddef) ? Qtrue : Qfalse;
815
1042
  }
816
1043
 
817
1044
  /*
818
- * call-seq:
819
- * FieldDescriptor.clear(message)
1045
+ * ruby-doc: FieldDescriptor#clear
820
1046
  *
821
1047
  * Clears the field from the message if it's set.
1048
+ *
1049
+ * @param message [AbstractMessage]
1050
+ * @return [nil]
822
1051
  */
823
1052
  static VALUE FieldDescriptor_clear(VALUE _self, VALUE msg_rb) {
824
1053
  FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
825
1054
  const upb_MessageDef* m;
826
- upb_MessageDef* msg = Message_GetMutable(msg_rb, &m);
1055
+ upb_Message* msg = Message_GetMutable(msg_rb, &m);
827
1056
 
828
1057
  if (m != upb_FieldDef_ContainingType(self->fielddef)) {
829
1058
  rb_raise(cTypeError, "has method called on wrong message type");
830
1059
  }
831
1060
 
832
- upb_Message_ClearField(msg, self->fielddef);
1061
+ upb_Message_ClearFieldByDef(msg, self->fielddef);
833
1062
  return Qnil;
834
1063
  }
835
1064
 
836
1065
  /*
837
- * call-seq:
838
- * FieldDescriptor.set(message, value)
1066
+ * ruby-doc: FieldDescriptor#set
839
1067
  *
840
1068
  * Sets the value corresponding to this field to the given value on the given
841
1069
  * message. Raises an exception if message is of the wrong type. Performs the
842
1070
  * ordinary type-checks for field setting.
1071
+ *
1072
+ * @param message [AbstractMessage]
1073
+ * @param value [Object]
843
1074
  */
844
1075
  static VALUE FieldDescriptor_set(VALUE _self, VALUE msg_rb, VALUE value) {
845
1076
  FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
846
1077
  const upb_MessageDef* m;
847
- upb_MessageDef* msg = Message_GetMutable(msg_rb, &m);
1078
+ upb_Message* msg = Message_GetMutable(msg_rb, &m);
848
1079
  upb_Arena* arena = Arena_get(Message_GetArena(msg_rb));
849
1080
  upb_MessageValue msgval;
850
1081
 
@@ -854,10 +1085,56 @@ static VALUE FieldDescriptor_set(VALUE _self, VALUE msg_rb, VALUE value) {
854
1085
 
855
1086
  msgval = Convert_RubyToUpb(value, upb_FieldDef_Name(self->fielddef),
856
1087
  TypeInfo_get(self->fielddef), arena);
857
- upb_Message_Set(msg, self->fielddef, msgval, arena);
1088
+ upb_Message_SetFieldByDef(msg, self->fielddef, msgval, arena);
858
1089
  return Qnil;
859
1090
  }
860
1091
 
1092
+ /*
1093
+ * ruby-doc: FieldDescriptor#options
1094
+ *
1095
+ * Returns the
1096
+ * {https://github.com/protocolbuffers/protobuf/blob/v30.2/src/google/protobuf/descriptor.proto#L656
1097
+ * FieldOptions} for this {FieldDescriptor}.
1098
+ *
1099
+ * @return [FieldOptions]
1100
+ */
1101
+ static VALUE FieldDescriptor_options(VALUE _self) {
1102
+ FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
1103
+ const google_protobuf_FieldOptions* opts =
1104
+ upb_FieldDef_Options(self->fielddef);
1105
+ upb_Arena* arena = upb_Arena_New();
1106
+ size_t size;
1107
+ char* serialized = google_protobuf_FieldOptions_serialize(opts, arena, &size);
1108
+ VALUE field_options = decode_options(_self, "FieldOptions", size, serialized,
1109
+ self->descriptor_pool);
1110
+ upb_Arena_Free(arena);
1111
+ return field_options;
1112
+ }
1113
+
1114
+ /*
1115
+ * ruby-doc: FieldDescriptor#to_proto
1116
+ *
1117
+ * Returns the
1118
+ * {https://github.com/protocolbuffers/protobuf/blob/v30.2/src/google/protobuf/descriptor.proto#L236
1119
+ * FieldDescriptorProto} of this {FieldDescriptor}.
1120
+ *
1121
+ * @return [FieldDescriptorProto]
1122
+ */
1123
+ static VALUE FieldDescriptor_to_proto(VALUE _self) {
1124
+ FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
1125
+ upb_Arena* arena = upb_Arena_New();
1126
+ google_protobuf_FieldDescriptorProto* proto =
1127
+ upb_FieldDef_ToProto(self->fielddef, arena);
1128
+ size_t size;
1129
+ const char* serialized =
1130
+ google_protobuf_FieldDescriptorProto_serialize(proto, arena, &size);
1131
+ VALUE proto_class = rb_path2class("Google::Protobuf::FieldDescriptorProto");
1132
+ VALUE proto_rb =
1133
+ Message_decode_bytes(size, serialized, 0, proto_class, false);
1134
+ upb_Arena_Free(arena);
1135
+ return proto_rb;
1136
+ }
1137
+
861
1138
  static void FieldDescriptor_register(VALUE module) {
862
1139
  VALUE klass = rb_define_class_under(module, "FieldDescriptor", rb_cObject);
863
1140
  rb_define_alloc_func(klass, FieldDescriptor_alloc);
@@ -865,6 +1142,10 @@ static void FieldDescriptor_register(VALUE module) {
865
1142
  rb_define_method(klass, "name", FieldDescriptor_name, 0);
866
1143
  rb_define_method(klass, "type", FieldDescriptor__type, 0);
867
1144
  rb_define_method(klass, "default", FieldDescriptor_default, 0);
1145
+ rb_define_method(klass, "has_presence?", FieldDescriptor_has_presence, 0);
1146
+ rb_define_method(klass, "required?", FieldDescriptor_is_required, 0);
1147
+ rb_define_method(klass, "repeated?", FieldDescriptor_is_repeated, 0);
1148
+ rb_define_method(klass, "is_packed?", FieldDescriptor_is_packed, 0);
868
1149
  rb_define_method(klass, "json_name", FieldDescriptor_json_name, 0);
869
1150
  rb_define_method(klass, "label", FieldDescriptor_label, 0);
870
1151
  rb_define_method(klass, "number", FieldDescriptor_number, 0);
@@ -874,6 +1155,8 @@ static void FieldDescriptor_register(VALUE module) {
874
1155
  rb_define_method(klass, "clear", FieldDescriptor_clear, 1);
875
1156
  rb_define_method(klass, "get", FieldDescriptor_get, 1);
876
1157
  rb_define_method(klass, "set", FieldDescriptor_set, 2);
1158
+ rb_define_method(klass, "options", FieldDescriptor_options, 0);
1159
+ rb_define_method(klass, "to_proto", FieldDescriptor_to_proto, 0);
877
1160
  rb_gc_register_address(&cFieldDescriptor);
878
1161
  cFieldDescriptor = klass;
879
1162
  }
@@ -884,6 +1167,8 @@ static void FieldDescriptor_register(VALUE module) {
884
1167
 
885
1168
  typedef struct {
886
1169
  const upb_OneofDef* oneofdef;
1170
+ // IMPORTANT: WB_PROTECTED objects must only use the RB_OBJ_WRITE()
1171
+ // macro to update VALUE references, as to trigger write barriers.
887
1172
  VALUE descriptor_pool; // Owns the upb_OneofDef.
888
1173
  } OneofDescriptor;
889
1174
 
@@ -897,7 +1182,7 @@ static void OneofDescriptor_mark(void* _self) {
897
1182
  static const rb_data_type_t OneofDescriptor_type = {
898
1183
  "Google::Protobuf::OneofDescriptor",
899
1184
  {OneofDescriptor_mark, RUBY_DEFAULT_FREE, NULL},
900
- .flags = RUBY_TYPED_FREE_IMMEDIATELY,
1185
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
901
1186
  };
902
1187
 
903
1188
  static OneofDescriptor* ruby_to_OneofDescriptor(VALUE val) {
@@ -906,9 +1191,15 @@ static OneofDescriptor* ruby_to_OneofDescriptor(VALUE val) {
906
1191
  return ret;
907
1192
  }
908
1193
 
1194
+ /**
1195
+ * ruby-doc: OneofDescriptor
1196
+ *
1197
+ * A OneofDescriptor provides information about the Protobuf definition of a
1198
+ * oneof inside a {Descriptor}.
1199
+ */
1200
+
909
1201
  /*
910
- * call-seq:
911
- * OneofDescriptor.new => oneof_descriptor
1202
+ * ruby-doc: OneofDescriptor#initialize
912
1203
  *
913
1204
  * Creates a new, empty, oneof descriptor. The oneof may only be modified prior
914
1205
  * to being added to a message descriptor which is subsequently added to a pool.
@@ -936,17 +1227,18 @@ static VALUE OneofDescriptor_initialize(VALUE _self, VALUE cookie,
936
1227
  "Descriptor objects may not be created from Ruby.");
937
1228
  }
938
1229
 
939
- self->descriptor_pool = descriptor_pool;
1230
+ RB_OBJ_WRITE(_self, &self->descriptor_pool, descriptor_pool);
940
1231
  self->oneofdef = (const upb_OneofDef*)NUM2ULL(ptr);
941
1232
 
942
1233
  return Qnil;
943
1234
  }
944
1235
 
945
1236
  /*
946
- * call-seq:
947
- * OneofDescriptor.name => name
1237
+ * ruby-doc: OneofDescriptor#name
948
1238
  *
949
1239
  * Returns the name of this oneof.
1240
+ *
1241
+ * @return [String]
950
1242
  */
951
1243
  static VALUE OneofDescriptor_name(VALUE _self) {
952
1244
  OneofDescriptor* self = ruby_to_OneofDescriptor(_self);
@@ -954,10 +1246,12 @@ static VALUE OneofDescriptor_name(VALUE _self) {
954
1246
  }
955
1247
 
956
1248
  /*
957
- * call-seq:
958
- * OneofDescriptor.each(&block) => nil
1249
+ * ruby-doc: OneofDescriptor#each
959
1250
  *
960
1251
  * Iterates through fields in this oneof, yielding to the block on each one.
1252
+ *
1253
+ * @yield [FieldDescriptor]
1254
+ * @return [nil]
961
1255
  */
962
1256
  static VALUE OneofDescriptor_each(VALUE _self) {
963
1257
  OneofDescriptor* self = ruby_to_OneofDescriptor(_self);
@@ -971,12 +1265,60 @@ static VALUE OneofDescriptor_each(VALUE _self) {
971
1265
  return Qnil;
972
1266
  }
973
1267
 
1268
+ /*
1269
+ * ruby-doc: OneofDescriptor#options
1270
+ *
1271
+ * Returns the
1272
+ * {https://github.com/protocolbuffers/protobuf/blob/v30.2/src/google/protobuf/descriptor.proto#L824
1273
+ * OneofOptions} for this {OneofDescriptor}.
1274
+ *
1275
+ * @return [OneofOptions]
1276
+ */
1277
+ static VALUE OneOfDescriptor_options(VALUE _self) {
1278
+ OneofDescriptor* self = ruby_to_OneofDescriptor(_self);
1279
+ const google_protobuf_OneofOptions* opts =
1280
+ upb_OneofDef_Options(self->oneofdef);
1281
+ upb_Arena* arena = upb_Arena_New();
1282
+ size_t size;
1283
+ char* serialized = google_protobuf_OneofOptions_serialize(opts, arena, &size);
1284
+ VALUE oneof_options = decode_options(_self, "OneofOptions", size, serialized,
1285
+ self->descriptor_pool);
1286
+ upb_Arena_Free(arena);
1287
+ return oneof_options;
1288
+ }
1289
+
1290
+ /*
1291
+ * ruby-doc: OneofDescriptor#to_proto
1292
+ *
1293
+ * Returns the
1294
+ * {https://github.com/protocolbuffers/protobuf/blob/v30.2/src/google/protobuf/descriptor.proto#L343
1295
+ * OneofDescriptorProto} of this {OneofDescriptor}.
1296
+ *
1297
+ * @return [OneofDescriptorProto]
1298
+ */
1299
+ static VALUE OneOfDescriptor_to_proto(VALUE _self) {
1300
+ OneofDescriptor* self = ruby_to_OneofDescriptor(_self);
1301
+ upb_Arena* arena = upb_Arena_New();
1302
+ google_protobuf_OneofDescriptorProto* proto =
1303
+ upb_OneofDef_ToProto(self->oneofdef, arena);
1304
+ size_t size;
1305
+ const char* serialized =
1306
+ google_protobuf_OneofDescriptorProto_serialize(proto, arena, &size);
1307
+ VALUE proto_class = rb_path2class("Google::Protobuf::OneofDescriptorProto");
1308
+ VALUE proto_rb =
1309
+ Message_decode_bytes(size, serialized, 0, proto_class, false);
1310
+ upb_Arena_Free(arena);
1311
+ return proto_rb;
1312
+ }
1313
+
974
1314
  static void OneofDescriptor_register(VALUE module) {
975
1315
  VALUE klass = rb_define_class_under(module, "OneofDescriptor", rb_cObject);
976
1316
  rb_define_alloc_func(klass, OneofDescriptor_alloc);
977
1317
  rb_define_method(klass, "initialize", OneofDescriptor_initialize, 3);
978
1318
  rb_define_method(klass, "name", OneofDescriptor_name, 0);
979
1319
  rb_define_method(klass, "each", OneofDescriptor_each, 0);
1320
+ rb_define_method(klass, "options", OneOfDescriptor_options, 0);
1321
+ rb_define_method(klass, "to_proto", OneOfDescriptor_to_proto, 0);
980
1322
  rb_include_module(klass, rb_mEnumerable);
981
1323
  rb_gc_register_address(&cOneofDescriptor);
982
1324
  cOneofDescriptor = klass;
@@ -988,6 +1330,8 @@ static void OneofDescriptor_register(VALUE module) {
988
1330
 
989
1331
  typedef struct {
990
1332
  const upb_EnumDef* enumdef;
1333
+ // IMPORTANT: WB_PROTECTED objects must only use the RB_OBJ_WRITE()
1334
+ // macro to update VALUE references, as to trigger write barriers.
991
1335
  VALUE module; // begins as nil
992
1336
  VALUE descriptor_pool; // Owns the upb_EnumDef.
993
1337
  } EnumDescriptor;
@@ -1003,7 +1347,7 @@ static void EnumDescriptor_mark(void* _self) {
1003
1347
  static const rb_data_type_t EnumDescriptor_type = {
1004
1348
  "Google::Protobuf::EnumDescriptor",
1005
1349
  {EnumDescriptor_mark, RUBY_DEFAULT_FREE, NULL},
1006
- .flags = RUBY_TYPED_FREE_IMMEDIATELY,
1350
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
1007
1351
  };
1008
1352
 
1009
1353
  static EnumDescriptor* ruby_to_EnumDescriptor(VALUE val) {
@@ -1027,6 +1371,13 @@ const upb_EnumDef* EnumDescriptor_GetEnumDef(VALUE enum_desc_rb) {
1027
1371
  return desc->enumdef;
1028
1372
  }
1029
1373
 
1374
+ /**
1375
+ * ruby-doc: EnumDescriptor
1376
+ *
1377
+ * An EnumDescriptor provides information about the Protobuf definition of an
1378
+ * enum inside a {Descriptor}.
1379
+ */
1380
+
1030
1381
  /*
1031
1382
  * call-seq:
1032
1383
  * EnumDescriptor.new(c_only_cookie, ptr) => EnumDescriptor
@@ -1042,17 +1393,18 @@ static VALUE EnumDescriptor_initialize(VALUE _self, VALUE cookie,
1042
1393
  "Descriptor objects may not be created from Ruby.");
1043
1394
  }
1044
1395
 
1045
- self->descriptor_pool = descriptor_pool;
1396
+ RB_OBJ_WRITE(_self, &self->descriptor_pool, descriptor_pool);
1046
1397
  self->enumdef = (const upb_EnumDef*)NUM2ULL(ptr);
1047
1398
 
1048
1399
  return Qnil;
1049
1400
  }
1050
1401
 
1051
1402
  /*
1052
- * call-seq:
1053
- * EnumDescriptor.file_descriptor
1403
+ * ruby-doc: EnumDescriptor#file_descriptor
1404
+ *
1405
+ * Returns the {FileDescriptor} object this enum belongs to.
1054
1406
  *
1055
- * Returns the FileDescriptor object this enum belongs to.
1407
+ * @return [FileDescriptor]
1056
1408
  */
1057
1409
  static VALUE EnumDescriptor_file_descriptor(VALUE _self) {
1058
1410
  EnumDescriptor* self = ruby_to_EnumDescriptor(_self);
@@ -1061,10 +1413,23 @@ static VALUE EnumDescriptor_file_descriptor(VALUE _self) {
1061
1413
  }
1062
1414
 
1063
1415
  /*
1064
- * call-seq:
1065
- * EnumDescriptor.name => name
1416
+ * ruby-doc: EnumDescriptor#is_closed?
1417
+ *
1418
+ * Returns whether this enum is open or closed.
1419
+ *
1420
+ * @return [Boolean]
1421
+ */
1422
+ static VALUE EnumDescriptor_is_closed(VALUE _self) {
1423
+ EnumDescriptor* self = ruby_to_EnumDescriptor(_self);
1424
+ return upb_EnumDef_IsClosed(self->enumdef) ? Qtrue : Qfalse;
1425
+ }
1426
+
1427
+ /*
1428
+ * ruby-doc: EnumDescriptor#name
1066
1429
  *
1067
1430
  * Returns the name of this enum type.
1431
+ *
1432
+ * @return [String]
1068
1433
  */
1069
1434
  static VALUE EnumDescriptor_name(VALUE _self) {
1070
1435
  EnumDescriptor* self = ruby_to_EnumDescriptor(_self);
@@ -1072,16 +1437,18 @@ static VALUE EnumDescriptor_name(VALUE _self) {
1072
1437
  }
1073
1438
 
1074
1439
  /*
1075
- * call-seq:
1076
- * EnumDescriptor.lookup_name(name) => value
1440
+ * ruby-doc: EnumDescriptor#lookup_name
1077
1441
  *
1078
1442
  * Returns the numeric value corresponding to the given key name (as a Ruby
1079
1443
  * symbol), or nil if none.
1444
+ *
1445
+ * @param name [Symbol]
1446
+ * @return [Integer,nil]
1080
1447
  */
1081
1448
  static VALUE EnumDescriptor_lookup_name(VALUE _self, VALUE name) {
1082
1449
  EnumDescriptor* self = ruby_to_EnumDescriptor(_self);
1083
1450
  const char* name_str = rb_id2name(SYM2ID(name));
1084
- const upb_EnumValueDef *ev =
1451
+ const upb_EnumValueDef* ev =
1085
1452
  upb_EnumDef_FindValueByName(self->enumdef, name_str);
1086
1453
  if (ev) {
1087
1454
  return INT2NUM(upb_EnumValueDef_Number(ev));
@@ -1091,16 +1458,19 @@ static VALUE EnumDescriptor_lookup_name(VALUE _self, VALUE name) {
1091
1458
  }
1092
1459
 
1093
1460
  /*
1094
- * call-seq:
1095
- * EnumDescriptor.lookup_value(name) => value
1461
+ * ruby-doc: EnumDescriptor#lookup_value
1096
1462
  *
1097
1463
  * Returns the key name (as a Ruby symbol) corresponding to the integer value,
1098
1464
  * or nil if none.
1465
+ *
1466
+ * @param name [Integer]
1467
+ * @return [Symbol,nil]
1099
1468
  */
1100
1469
  static VALUE EnumDescriptor_lookup_value(VALUE _self, VALUE number) {
1101
1470
  EnumDescriptor* self = ruby_to_EnumDescriptor(_self);
1102
1471
  int32_t val = NUM2INT(number);
1103
- const upb_EnumValueDef* ev = upb_EnumDef_FindValueByNumber(self->enumdef, val);
1472
+ const upb_EnumValueDef* ev =
1473
+ upb_EnumDef_FindValueByNumber(self->enumdef, val);
1104
1474
  if (ev) {
1105
1475
  return ID2SYM(rb_intern(upb_EnumValueDef_Name(ev)));
1106
1476
  } else {
@@ -1109,11 +1479,13 @@ static VALUE EnumDescriptor_lookup_value(VALUE _self, VALUE number) {
1109
1479
  }
1110
1480
 
1111
1481
  /*
1112
- * call-seq:
1113
- * EnumDescriptor.each(&block)
1482
+ * ruby-doc: EnumDescriptor#each
1114
1483
  *
1115
1484
  * Iterates over key => value mappings in this enum's definition, yielding to
1116
1485
  * the block with (key, value) arguments for each one.
1486
+ *
1487
+ * @yield [Symbol, Integer]
1488
+ * @return [nil]
1117
1489
  */
1118
1490
  static VALUE EnumDescriptor_each(VALUE _self) {
1119
1491
  EnumDescriptor* self = ruby_to_EnumDescriptor(_self);
@@ -1130,19 +1502,66 @@ static VALUE EnumDescriptor_each(VALUE _self) {
1130
1502
  }
1131
1503
 
1132
1504
  /*
1133
- * call-seq:
1134
- * EnumDescriptor.enummodule => module
1505
+ * ruby-doc: EnumDescriptor#enummodule
1135
1506
  *
1136
1507
  * Returns the Ruby module corresponding to this enum type.
1508
+ *
1509
+ * @return [Module]
1137
1510
  */
1138
1511
  static VALUE EnumDescriptor_enummodule(VALUE _self) {
1139
1512
  EnumDescriptor* self = ruby_to_EnumDescriptor(_self);
1140
1513
  if (self->module == Qnil) {
1141
- self->module = build_module_from_enumdesc(_self);
1514
+ RB_OBJ_WRITE(_self, &self->module, build_module_from_enumdesc(_self));
1142
1515
  }
1143
1516
  return self->module;
1144
1517
  }
1145
1518
 
1519
+ /*
1520
+ * ruby-doc: EnumDescriptor#options
1521
+ *
1522
+ * Returns the
1523
+ * {https://github.com/protocolbuffers/protobuf/blob/v30.2/src/google/protobuf/descriptor.proto#L838
1524
+ * EnumOptions} for this {EnumDescriptor}.
1525
+ *
1526
+ * @return [EnumOptions]
1527
+ */
1528
+ static VALUE EnumDescriptor_options(VALUE _self) {
1529
+ EnumDescriptor* self = ruby_to_EnumDescriptor(_self);
1530
+ const google_protobuf_EnumOptions* opts = upb_EnumDef_Options(self->enumdef);
1531
+ upb_Arena* arena = upb_Arena_New();
1532
+ size_t size;
1533
+ char* serialized = google_protobuf_EnumOptions_serialize(opts, arena, &size);
1534
+ VALUE enum_options = decode_options(_self, "EnumOptions", size, serialized,
1535
+ self->descriptor_pool);
1536
+ upb_Arena_Free(arena);
1537
+ return enum_options;
1538
+ }
1539
+
1540
+ /*
1541
+ * ruby-doc: EnumDescriptor#to_proto
1542
+ *
1543
+ * Returns the
1544
+ * {https://github.com/protocolbuffers/protobuf/blob/v30.2/src/google/protobuf/descriptor.proto#L349
1545
+ * EnumDescriptorProto} of this {EnumDescriptor}.
1546
+ * @return [EnumDescriptorProto]
1547
+ */
1548
+ static VALUE EnumDescriptor_to_proto(VALUE _self) {
1549
+ EnumDescriptor* self = ruby_to_EnumDescriptor(_self);
1550
+ upb_Arena* arena = upb_Arena_New();
1551
+ google_protobuf_EnumDescriptorProto* proto =
1552
+ upb_EnumDef_ToProto(self->enumdef, arena);
1553
+
1554
+ size_t size;
1555
+ const char* serialized =
1556
+ google_protobuf_EnumDescriptorProto_serialize(proto, arena, &size);
1557
+
1558
+ VALUE proto_class = rb_path2class("Google::Protobuf::EnumDescriptorProto");
1559
+ VALUE proto_rb =
1560
+ Message_decode_bytes(size, serialized, 0, proto_class, false);
1561
+ upb_Arena_Free(arena);
1562
+ return proto_rb;
1563
+ }
1564
+
1146
1565
  static void EnumDescriptor_register(VALUE module) {
1147
1566
  VALUE klass = rb_define_class_under(module, "EnumDescriptor", rb_cObject);
1148
1567
  rb_define_alloc_func(klass, EnumDescriptor_alloc);
@@ -1153,11 +1572,384 @@ static void EnumDescriptor_register(VALUE module) {
1153
1572
  rb_define_method(klass, "each", EnumDescriptor_each, 0);
1154
1573
  rb_define_method(klass, "enummodule", EnumDescriptor_enummodule, 0);
1155
1574
  rb_define_method(klass, "file_descriptor", EnumDescriptor_file_descriptor, 0);
1575
+ rb_define_method(klass, "is_closed?", EnumDescriptor_is_closed, 0);
1576
+ rb_define_method(klass, "options", EnumDescriptor_options, 0);
1577
+ rb_define_method(klass, "to_proto", EnumDescriptor_to_proto, 0);
1156
1578
  rb_include_module(klass, rb_mEnumerable);
1157
1579
  rb_gc_register_address(&cEnumDescriptor);
1158
1580
  cEnumDescriptor = klass;
1159
1581
  }
1160
1582
 
1583
+ // -----------------------------------------------------------------------------
1584
+ // ServiceDescriptor
1585
+ // -----------------------------------------------------------------------------
1586
+
1587
+ typedef struct {
1588
+ const upb_ServiceDef* servicedef;
1589
+ // IMPORTANT: WB_PROTECTED objects must only use the RB_OBJ_WRITE()
1590
+ // macro to update VALUE references, as to trigger write barriers.
1591
+ VALUE module; // begins as nil
1592
+ VALUE descriptor_pool; // Owns the upb_ServiceDef.
1593
+ } ServiceDescriptor;
1594
+
1595
+ static VALUE cServiceDescriptor = Qnil;
1596
+
1597
+ static void ServiceDescriptor_mark(void* _self) {
1598
+ ServiceDescriptor* self = _self;
1599
+ rb_gc_mark(self->module);
1600
+ rb_gc_mark(self->descriptor_pool);
1601
+ }
1602
+
1603
+ static const rb_data_type_t ServiceDescriptor_type = {
1604
+ "Google::Protobuf::ServicDescriptor",
1605
+ {ServiceDescriptor_mark, RUBY_DEFAULT_FREE, NULL},
1606
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
1607
+ };
1608
+
1609
+ static ServiceDescriptor* ruby_to_ServiceDescriptor(VALUE val) {
1610
+ ServiceDescriptor* ret;
1611
+ TypedData_Get_Struct(val, ServiceDescriptor, &ServiceDescriptor_type, ret);
1612
+ return ret;
1613
+ }
1614
+
1615
+ static VALUE ServiceDescriptor_alloc(VALUE klass) {
1616
+ ServiceDescriptor* self = ALLOC(ServiceDescriptor);
1617
+ VALUE ret = TypedData_Wrap_Struct(klass, &ServiceDescriptor_type, self);
1618
+ self->servicedef = NULL;
1619
+ self->module = Qnil;
1620
+ self->descriptor_pool = Qnil;
1621
+ return ret;
1622
+ }
1623
+
1624
+ /**
1625
+ * ruby-doc: ServiceDescriptor
1626
+ *
1627
+ * A ServiceDescriptor provides information about the Protobuf definition of an
1628
+ * RPC service.
1629
+ */
1630
+
1631
+ /*
1632
+ * call-seq:
1633
+ * ServiceDescriptor.new(c_only_cookie, ptr) => ServiceDescriptor
1634
+ *
1635
+ * Creates a descriptor wrapper object. May only be called from C.
1636
+ */
1637
+ static VALUE ServiceDescriptor_initialize(VALUE _self, VALUE cookie,
1638
+ VALUE descriptor_pool, VALUE ptr) {
1639
+ ServiceDescriptor* self = ruby_to_ServiceDescriptor(_self);
1640
+
1641
+ if (cookie != c_only_cookie) {
1642
+ rb_raise(rb_eRuntimeError,
1643
+ "Descriptor objects may not be created from Ruby.");
1644
+ }
1645
+
1646
+ RB_OBJ_WRITE(_self, &self->descriptor_pool, descriptor_pool);
1647
+ self->servicedef = (const upb_ServiceDef*)NUM2ULL(ptr);
1648
+
1649
+ return Qnil;
1650
+ }
1651
+
1652
+ /*
1653
+ * ruby-doc: ServiceDescriptor#name
1654
+ *
1655
+ * Returns the name of this service.
1656
+ *
1657
+ * @return [String]
1658
+ */
1659
+ static VALUE ServiceDescriptor_name(VALUE _self) {
1660
+ ServiceDescriptor* self = ruby_to_ServiceDescriptor(_self);
1661
+ return rb_str_maybe_null(upb_ServiceDef_FullName(self->servicedef));
1662
+ }
1663
+
1664
+ /*
1665
+ * ruby-doc: ServiceDescriptor#file_descriptor
1666
+ *
1667
+ * Returns the {FileDescriptor} object this service belongs to.
1668
+ * @return [FileDescriptor]
1669
+ */
1670
+ static VALUE ServiceDescriptor_file_descriptor(VALUE _self) {
1671
+ ServiceDescriptor* self = ruby_to_ServiceDescriptor(_self);
1672
+ return get_filedef_obj(self->descriptor_pool,
1673
+ upb_ServiceDef_File(self->servicedef));
1674
+ }
1675
+
1676
+ /*
1677
+ * ruby-doc: ServiceDescriptor#each
1678
+ *
1679
+ * Iterates over methods in this service, yielding to the block on each one.
1680
+ *
1681
+ * @yield [MethodDescriptor]
1682
+ * @return [nil]
1683
+ */
1684
+ static VALUE ServiceDescriptor_each(VALUE _self) {
1685
+ ServiceDescriptor* self = ruby_to_ServiceDescriptor(_self);
1686
+
1687
+ int n = upb_ServiceDef_MethodCount(self->servicedef);
1688
+ for (int i = 0; i < n; i++) {
1689
+ const upb_MethodDef* method = upb_ServiceDef_Method(self->servicedef, i);
1690
+ VALUE obj = get_methoddef_obj(self->descriptor_pool, method);
1691
+ rb_yield(obj);
1692
+ }
1693
+ return Qnil;
1694
+ }
1695
+
1696
+ /*
1697
+ * ruby-doc: ServiceDescriptor#options
1698
+ *
1699
+ * Returns the
1700
+ * {https://github.com/protocolbuffers/protobuf/blob/v30.2/src/google/protobuf/descriptor.proto#L901
1701
+ * ServiceOptions} for this {ServiceDescriptor}.
1702
+ *
1703
+ * @return [ServiceOptions]
1704
+ */
1705
+ static VALUE ServiceDescriptor_options(VALUE _self) {
1706
+ ServiceDescriptor* self = ruby_to_ServiceDescriptor(_self);
1707
+ const google_protobuf_ServiceOptions* opts =
1708
+ upb_ServiceDef_Options(self->servicedef);
1709
+ upb_Arena* arena = upb_Arena_New();
1710
+ size_t size;
1711
+ char* serialized =
1712
+ google_protobuf_ServiceOptions_serialize(opts, arena, &size);
1713
+ VALUE service_options = decode_options(_self, "ServiceOptions", size,
1714
+ serialized, self->descriptor_pool);
1715
+ upb_Arena_Free(arena);
1716
+ return service_options;
1717
+ }
1718
+
1719
+ /*
1720
+ * ruby-doc: ServiceDescriptor#to_proto
1721
+ *
1722
+ * Returns the
1723
+ * {https://github.com/protocolbuffers/protobuf/blob/v30.2/src/google/protobuf/descriptor.proto#L386
1724
+ * ServiceDescriptorProto} of this {ServiceDescriptor}.
1725
+ *
1726
+ * @return [ServiceDescriptorProto]
1727
+ */
1728
+ static VALUE ServiceDescriptor_to_proto(VALUE _self) {
1729
+ ServiceDescriptor* self = ruby_to_ServiceDescriptor(_self);
1730
+ upb_Arena* arena = upb_Arena_New();
1731
+ google_protobuf_ServiceDescriptorProto* proto =
1732
+ upb_ServiceDef_ToProto(self->servicedef, arena);
1733
+ size_t size;
1734
+ const char* serialized =
1735
+ google_protobuf_ServiceDescriptorProto_serialize(proto, arena, &size);
1736
+ VALUE proto_class = rb_path2class("Google::Protobuf::ServiceDescriptorProto");
1737
+ VALUE proto_rb =
1738
+ Message_decode_bytes(size, serialized, 0, proto_class, false);
1739
+ upb_Arena_Free(arena);
1740
+ return proto_rb;
1741
+ }
1742
+
1743
+ static void ServiceDescriptor_register(VALUE module) {
1744
+ VALUE klass = rb_define_class_under(module, "ServiceDescriptor", rb_cObject);
1745
+ rb_define_alloc_func(klass, ServiceDescriptor_alloc);
1746
+ rb_define_method(klass, "initialize", ServiceDescriptor_initialize, 3);
1747
+ rb_define_method(klass, "name", ServiceDescriptor_name, 0);
1748
+ rb_define_method(klass, "each", ServiceDescriptor_each, 0);
1749
+ rb_define_method(klass, "file_descriptor", ServiceDescriptor_file_descriptor,
1750
+ 0);
1751
+ rb_define_method(klass, "options", ServiceDescriptor_options, 0);
1752
+ rb_define_method(klass, "to_proto", ServiceDescriptor_to_proto, 0);
1753
+ rb_include_module(klass, rb_mEnumerable);
1754
+ rb_gc_register_address(&cServiceDescriptor);
1755
+ cServiceDescriptor = klass;
1756
+ }
1757
+
1758
+ // -----------------------------------------------------------------------------
1759
+ // MethodDescriptor
1760
+ // -----------------------------------------------------------------------------
1761
+
1762
+ typedef struct {
1763
+ const upb_MethodDef* methoddef;
1764
+ // IMPORTANT: WB_PROTECTED objects must only use the RB_OBJ_WRITE()
1765
+ // macro to update VALUE references, as to trigger write barriers.
1766
+ VALUE module; // begins as nil
1767
+ VALUE descriptor_pool; // Owns the upb_MethodDef.
1768
+ } MethodDescriptor;
1769
+
1770
+ static VALUE cMethodDescriptor = Qnil;
1771
+
1772
+ static void MethodDescriptor_mark(void* _self) {
1773
+ MethodDescriptor* self = _self;
1774
+ rb_gc_mark(self->module);
1775
+ rb_gc_mark(self->descriptor_pool);
1776
+ }
1777
+
1778
+ static const rb_data_type_t MethodDescriptor_type = {
1779
+ "Google::Protobuf::MethodDescriptor",
1780
+ {MethodDescriptor_mark, RUBY_DEFAULT_FREE, NULL},
1781
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
1782
+ };
1783
+
1784
+ static MethodDescriptor* ruby_to_MethodDescriptor(VALUE val) {
1785
+ MethodDescriptor* ret;
1786
+ TypedData_Get_Struct(val, MethodDescriptor, &MethodDescriptor_type, ret);
1787
+ return ret;
1788
+ }
1789
+
1790
+ static VALUE MethodDescriptor_alloc(VALUE klass) {
1791
+ MethodDescriptor* self = ALLOC(MethodDescriptor);
1792
+ VALUE ret = TypedData_Wrap_Struct(klass, &MethodDescriptor_type, self);
1793
+ self->methoddef = NULL;
1794
+ self->module = Qnil;
1795
+ self->descriptor_pool = Qnil;
1796
+ return ret;
1797
+ }
1798
+
1799
+ /**
1800
+ * ruby-doc: MethodDescriptor
1801
+ *
1802
+ * A MethodDescriptor provides information about the Protobuf definition of a
1803
+ * method inside an RPC service.
1804
+ */
1805
+
1806
+ /*
1807
+ * call-seq:
1808
+ * MethodDescriptor.new(c_only_cookie, ptr) => MethodDescriptor
1809
+ *
1810
+ * Creates a descriptor wrapper object. May only be called from C.
1811
+ */
1812
+ static VALUE MethodDescriptor_initialize(VALUE _self, VALUE cookie,
1813
+ VALUE descriptor_pool, VALUE ptr) {
1814
+ MethodDescriptor* self = ruby_to_MethodDescriptor(_self);
1815
+
1816
+ if (cookie != c_only_cookie) {
1817
+ rb_raise(rb_eRuntimeError,
1818
+ "Descriptor objects may not be created from Ruby.");
1819
+ }
1820
+
1821
+ RB_OBJ_WRITE(_self, &self->descriptor_pool, descriptor_pool);
1822
+ self->methoddef = (const upb_MethodDef*)NUM2ULL(ptr);
1823
+
1824
+ return Qnil;
1825
+ }
1826
+
1827
+ /*
1828
+ * ruby-doc: MethodDescriptor#name
1829
+ *
1830
+ * Returns the name of this method
1831
+ *
1832
+ * @return [String]
1833
+ */
1834
+ static VALUE MethodDescriptor_name(VALUE _self) {
1835
+ MethodDescriptor* self = ruby_to_MethodDescriptor(_self);
1836
+ return rb_str_maybe_null(upb_MethodDef_Name(self->methoddef));
1837
+ }
1838
+
1839
+ /*
1840
+ * ruby-doc: MethodDescriptor#options
1841
+ *
1842
+ * Returns the
1843
+ * {https://github.com/protocolbuffers/protobuf/blob/v30.2/src/google/protobuf/descriptor.proto#L927
1844
+ * MethodOptions} for this {MethodDescriptor}.
1845
+ *
1846
+ * @return [MethodOptions]
1847
+ */
1848
+ static VALUE MethodDescriptor_options(VALUE _self) {
1849
+ MethodDescriptor* self = ruby_to_MethodDescriptor(_self);
1850
+ const google_protobuf_MethodOptions* opts =
1851
+ upb_MethodDef_Options(self->methoddef);
1852
+ upb_Arena* arena = upb_Arena_New();
1853
+ size_t size;
1854
+ char* serialized =
1855
+ google_protobuf_MethodOptions_serialize(opts, arena, &size);
1856
+ VALUE method_options = decode_options(_self, "MethodOptions", size,
1857
+ serialized, self->descriptor_pool);
1858
+ upb_Arena_Free(arena);
1859
+ return method_options;
1860
+ }
1861
+
1862
+ /*
1863
+ * ruby-doc: MethodDescriptor#input_type
1864
+ *
1865
+ * Returns the {Descriptor} for the request message type of this method
1866
+ *
1867
+ * @return [Descriptor]
1868
+ */
1869
+ static VALUE MethodDescriptor_input_type(VALUE _self) {
1870
+ MethodDescriptor* self = ruby_to_MethodDescriptor(_self);
1871
+ const upb_MessageDef* type = upb_MethodDef_InputType(self->methoddef);
1872
+ return get_msgdef_obj(self->descriptor_pool, type);
1873
+ }
1874
+
1875
+ /*
1876
+ * ruby-doc: MethodDescriptor#output_type
1877
+ *
1878
+ * Returns the {Descriptor} for the response message type of this method
1879
+ *
1880
+ * @return [Descriptor]
1881
+ */
1882
+ static VALUE MethodDescriptor_output_type(VALUE _self) {
1883
+ MethodDescriptor* self = ruby_to_MethodDescriptor(_self);
1884
+ const upb_MessageDef* type = upb_MethodDef_OutputType(self->methoddef);
1885
+ return get_msgdef_obj(self->descriptor_pool, type);
1886
+ }
1887
+
1888
+ /*
1889
+ * ruby-doc: MethodDescriptor#client_streaming
1890
+ *
1891
+ * Returns whether or not this is a streaming request method
1892
+ *
1893
+ * @return [Boolean]
1894
+ */
1895
+ static VALUE MethodDescriptor_client_streaming(VALUE _self) {
1896
+ MethodDescriptor* self = ruby_to_MethodDescriptor(_self);
1897
+ return upb_MethodDef_ClientStreaming(self->methoddef) ? Qtrue : Qfalse;
1898
+ }
1899
+
1900
+ /*
1901
+ * ruby-doc: MethodDescriptor#to_proto
1902
+ *
1903
+ * Returns the
1904
+ * {https://github.com/protocolbuffers/protobuf/blob/v30.2/src/google/protobuf/descriptor.proto#L394
1905
+ * MethodDescriptorProto} of this {MethodDescriptor}.
1906
+ *
1907
+ * @return [MethodDescriptorProto]
1908
+ */
1909
+ static VALUE MethodDescriptor_to_proto(VALUE _self) {
1910
+ MethodDescriptor* self = ruby_to_MethodDescriptor(_self);
1911
+ upb_Arena* arena = upb_Arena_New();
1912
+ google_protobuf_MethodDescriptorProto* proto =
1913
+ upb_MethodDef_ToProto(self->methoddef, arena);
1914
+ size_t size;
1915
+ const char* serialized =
1916
+ google_protobuf_MethodDescriptorProto_serialize(proto, arena, &size);
1917
+ VALUE proto_class = rb_path2class("Google::Protobuf::MethodDescriptorProto");
1918
+ VALUE proto_rb =
1919
+ Message_decode_bytes(size, serialized, 0, proto_class, false);
1920
+ upb_Arena_Free(arena);
1921
+ return proto_rb;
1922
+ }
1923
+
1924
+ /*
1925
+ * ruby-doc: MethodDescriptor#server_streaming
1926
+ *
1927
+ * Returns whether or not this is a streaming response method
1928
+ *
1929
+ * @return [Boolean]
1930
+ */
1931
+ static VALUE MethodDescriptor_server_streaming(VALUE _self) {
1932
+ MethodDescriptor* self = ruby_to_MethodDescriptor(_self);
1933
+ return upb_MethodDef_ServerStreaming(self->methoddef) ? Qtrue : Qfalse;
1934
+ }
1935
+
1936
+ static void MethodDescriptor_register(VALUE module) {
1937
+ VALUE klass = rb_define_class_under(module, "MethodDescriptor", rb_cObject);
1938
+ rb_define_alloc_func(klass, MethodDescriptor_alloc);
1939
+ rb_define_method(klass, "initialize", MethodDescriptor_initialize, 3);
1940
+ rb_define_method(klass, "name", MethodDescriptor_name, 0);
1941
+ rb_define_method(klass, "options", MethodDescriptor_options, 0);
1942
+ rb_define_method(klass, "input_type", MethodDescriptor_input_type, 0);
1943
+ rb_define_method(klass, "output_type", MethodDescriptor_output_type, 0);
1944
+ rb_define_method(klass, "client_streaming", MethodDescriptor_client_streaming,
1945
+ 0);
1946
+ rb_define_method(klass, "server_streaming", MethodDescriptor_server_streaming,
1947
+ 0);
1948
+ rb_define_method(klass, "to_proto", MethodDescriptor_to_proto, 0);
1949
+ rb_gc_register_address(&cMethodDescriptor);
1950
+ cMethodDescriptor = klass;
1951
+ }
1952
+
1161
1953
  static VALUE get_def_obj(VALUE _descriptor_pool, const void* ptr, VALUE klass) {
1162
1954
  DescriptorPool* descriptor_pool = ruby_to_DescriptorPool(_descriptor_pool);
1163
1955
  VALUE key = ULL2NUM((intptr_t)ptr);
@@ -1199,6 +1991,16 @@ static VALUE get_oneofdef_obj(VALUE descriptor_pool, const upb_OneofDef* def) {
1199
1991
  return get_def_obj(descriptor_pool, def, cOneofDescriptor);
1200
1992
  }
1201
1993
 
1994
+ static VALUE get_servicedef_obj(VALUE descriptor_pool,
1995
+ const upb_ServiceDef* def) {
1996
+ return get_def_obj(descriptor_pool, def, cServiceDescriptor);
1997
+ }
1998
+
1999
+ static VALUE get_methoddef_obj(VALUE descriptor_pool,
2000
+ const upb_MethodDef* def) {
2001
+ return get_def_obj(descriptor_pool, def, cMethodDescriptor);
2002
+ }
2003
+
1202
2004
  // -----------------------------------------------------------------------------
1203
2005
  // Shared functions
1204
2006
  // -----------------------------------------------------------------------------
@@ -1274,6 +2076,8 @@ void Defs_register(VALUE module) {
1274
2076
  FieldDescriptor_register(module);
1275
2077
  OneofDescriptor_register(module);
1276
2078
  EnumDescriptor_register(module);
2079
+ ServiceDescriptor_register(module);
2080
+ MethodDescriptor_register(module);
1277
2081
 
1278
2082
  rb_gc_register_address(&c_only_cookie);
1279
2083
  c_only_cookie = rb_class_new_instance(0, NULL, rb_cObject);