google-protobuf 3.25.8 → 4.28.2

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 (59) hide show
  1. checksums.yaml +4 -4
  2. data/ext/google/protobuf_c/convert.c +40 -15
  3. data/ext/google/protobuf_c/defs.c +365 -26
  4. data/ext/google/protobuf_c/extconf.rb +1 -1
  5. data/ext/google/protobuf_c/glue.c +16 -0
  6. data/ext/google/protobuf_c/map.c +72 -27
  7. data/ext/google/protobuf_c/map.h +7 -3
  8. data/ext/google/protobuf_c/message.c +100 -111
  9. data/ext/google/protobuf_c/message.h +2 -6
  10. data/ext/google/protobuf_c/protobuf.c +30 -15
  11. data/ext/google/protobuf_c/protobuf.h +3 -7
  12. data/ext/google/protobuf_c/repeated_field.c +58 -23
  13. data/ext/google/protobuf_c/repeated_field.h +6 -2
  14. data/ext/google/protobuf_c/ruby-upb.c +13047 -10862
  15. data/ext/google/protobuf_c/ruby-upb.h +11114 -9028
  16. data/ext/google/protobuf_c/shared_convert.c +7 -2
  17. data/ext/google/protobuf_c/shared_message.c +3 -32
  18. data/ext/google/protobuf_c/shared_message.h +0 -4
  19. data/ext/google/protobuf_c/third_party/utf8_range/utf8_range.c +467 -0
  20. data/ext/google/protobuf_c/third_party/utf8_range/utf8_range.h +9 -8
  21. data/lib/google/protobuf/any_pb.rb +1 -22
  22. data/lib/google/protobuf/api_pb.rb +1 -24
  23. data/lib/google/protobuf/descriptor_pb.rb +3 -23
  24. data/lib/google/protobuf/duration_pb.rb +1 -22
  25. data/lib/google/protobuf/empty_pb.rb +1 -22
  26. data/lib/google/protobuf/ffi/descriptor.rb +4 -4
  27. data/lib/google/protobuf/ffi/descriptor_pool.rb +3 -1
  28. data/lib/google/protobuf/ffi/enum_descriptor.rb +3 -1
  29. data/lib/google/protobuf/ffi/ffi.rb +3 -6
  30. data/lib/google/protobuf/ffi/field_descriptor.rb +13 -2
  31. data/lib/google/protobuf/ffi/file_descriptor.rb +3 -13
  32. data/lib/google/protobuf/ffi/internal/arena.rb +0 -6
  33. data/lib/google/protobuf/ffi/internal/convert.rb +21 -30
  34. data/lib/google/protobuf/ffi/map.rb +50 -24
  35. data/lib/google/protobuf/ffi/message.rb +183 -64
  36. data/lib/google/protobuf/ffi/method_descriptor.rb +114 -0
  37. data/lib/google/protobuf/ffi/object_cache.rb +3 -3
  38. data/lib/google/protobuf/ffi/oneof_descriptor.rb +3 -1
  39. data/lib/google/protobuf/ffi/repeated_field.rb +47 -19
  40. data/lib/google/protobuf/ffi/service_descriptor.rb +107 -0
  41. data/lib/google/protobuf/field_mask_pb.rb +1 -22
  42. data/lib/google/protobuf/internal/object_cache.rb +99 -0
  43. data/lib/google/protobuf/plugin_pb.rb +2 -24
  44. data/lib/google/protobuf/repeated_field.rb +4 -5
  45. data/lib/google/protobuf/source_context_pb.rb +1 -22
  46. data/lib/google/protobuf/struct_pb.rb +1 -22
  47. data/lib/google/protobuf/timestamp_pb.rb +1 -22
  48. data/lib/google/protobuf/type_pb.rb +1 -24
  49. data/lib/google/protobuf/wrappers_pb.rb +1 -22
  50. data/lib/google/protobuf.rb +1 -1
  51. data/lib/google/protobuf_ffi.rb +3 -2
  52. data/lib/google/protobuf_native.rb +0 -1
  53. data/lib/google/tasks/ffi.rake +1 -3
  54. metadata +25 -12
  55. data/ext/google/protobuf_c/third_party/utf8_range/naive.c +0 -92
  56. data/ext/google/protobuf_c/third_party/utf8_range/range2-neon.c +0 -157
  57. data/ext/google/protobuf_c/third_party/utf8_range/range2-sse.c +0 -170
  58. data/lib/google/protobuf/descriptor_dsl.rb +0 -465
  59. data/lib/google/protobuf/object_cache.rb +0 -97
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4f5b33b08d0d2329353257e06dfad8b05af0039bf6c8a319bdcab7da7b7954e0
4
- data.tar.gz: a37f33cbba247a0f7e5e25991134e927fb28ffcc22bb8d9ffa15241709ab1664
3
+ metadata.gz: 50f7cd8abfe74257e6fa183325ec76d6590fa2e650139a7e8c06be67b1a37265
4
+ data.tar.gz: f19365b4373475b2c7d7570aceaa993cb0718fe37525ca392df3a2629dc48f85
5
5
  SHA512:
6
- metadata.gz: 13227d168b9d7f3d8be570c0f8eb1a04277c1f246f96a68ab64fb2e389368975c10303cd50cc7733e61734b8e438412846fa4fba6fe41bb52e96b22d619fc44c
7
- data.tar.gz: 3b830b905ed89d30395e4ba61dc4f76cef3c74c86cf9656ce26c9ba399f320c91474c0e1f0ea5aa856646dfab4770ba0a0e55d9fd0c9f854411562a851740ba1
6
+ metadata.gz: cb6543ae37709a2a1e57498a2c4125bf1f8dca38efb0e80ca65389e34ef2a9b7613a5a57923d485f4dc0011bfe37a538480d1e2e999eb0f84945a10bef561c10
7
+ data.tar.gz: 051b5e72dc158ecb34e8a0627be5e7efe17245f1c6be5487d8c04ff746701138a62439e479633c0479f722c62d694b6ca5f32f06193e341f8067759c187aa578
@@ -104,6 +104,41 @@ unknownval:
104
104
  rb_raise(rb_eRangeError, "Unknown symbol value for enum field '%s'.", name);
105
105
  }
106
106
 
107
+ VALUE Convert_CheckStringUtf8(VALUE str) {
108
+ VALUE utf8 = rb_enc_from_encoding(rb_utf8_encoding());
109
+
110
+ if (rb_obj_encoding(str) == utf8) {
111
+ // Note: Just because a string is marked as having UTF-8 encoding does
112
+ // not mean that it is *valid* UTF-8. We have to check separately
113
+ // whether it is valid.
114
+ if (rb_enc_str_coderange(str) == ENC_CODERANGE_BROKEN) {
115
+ // TODO: For now
116
+ // we only warn for this case. We will remove the warning and throw an
117
+ // exception below in the 30.x release
118
+
119
+ rb_warn(
120
+ "String is invalid UTF-8. This will be an error in a future "
121
+ "version.");
122
+ // VALUE exc = rb_const_get_at(
123
+ // rb_cEncoding, rb_intern("InvalidByteSequenceError"));
124
+ // rb_raise(exc, "String is invalid UTF-8");
125
+ }
126
+ } else {
127
+ // Note: this will not duplicate underlying string data unless
128
+ // necessary.
129
+ //
130
+ // This will throw an exception if the conversion cannot be performed:
131
+ // - Encoding::UndefinedConversionError if certain characters cannot be
132
+ // converted to UTF-8.
133
+ // - Encoding::InvalidByteSequenceError if certain characters were invalid
134
+ // in the source encoding.
135
+ str = rb_str_encode(str, utf8, 0, Qnil);
136
+ PBRUBY_ASSERT(rb_enc_str_coderange(str) != ENC_CODERANGE_BROKEN);
137
+ }
138
+
139
+ return str;
140
+ }
141
+
107
142
  upb_MessageValue Convert_RubyToUpb(VALUE value, const char* name,
108
143
  TypeInfo type_info, upb_Arena* arena) {
109
144
  upb_MessageValue ret;
@@ -137,29 +172,18 @@ upb_MessageValue Convert_RubyToUpb(VALUE value, const char* name,
137
172
  }
138
173
  break;
139
174
  }
140
- case kUpb_CType_String: {
141
- VALUE utf8 = rb_enc_from_encoding(rb_utf8_encoding());
175
+ case kUpb_CType_String:
142
176
  if (rb_obj_class(value) == rb_cSymbol) {
143
177
  value = rb_funcall(value, rb_intern("to_s"), 0);
144
- } else if (rb_obj_class(value) != rb_cString) {
178
+ } else if (!rb_obj_is_kind_of(value, rb_cString)) {
145
179
  rb_raise(cTypeError,
146
180
  "Invalid argument for string field '%s' (given %s).", name,
147
181
  rb_class2name(CLASS_OF(value)));
148
182
  }
149
183
 
150
- if (rb_obj_encoding(value) != utf8) {
151
- // Note: this will not duplicate underlying string data unless
152
- // necessary.
153
- value = rb_str_encode(value, utf8, 0, Qnil);
154
-
155
- if (rb_enc_str_coderange(value) == ENC_CODERANGE_BROKEN) {
156
- rb_raise(rb_eEncodingError, "String is invalid UTF-8");
157
- }
158
- }
159
-
184
+ value = Convert_CheckStringUtf8(value);
160
185
  ret.str_val = Convert_StringData(value, arena);
161
186
  break;
162
- }
163
187
  case kUpb_CType_Bytes: {
164
188
  VALUE bytes = rb_enc_from_encoding(rb_ascii8bit_encoding());
165
189
  if (rb_obj_class(value) != rb_cString) {
@@ -204,7 +228,8 @@ upb_MessageValue Convert_RubyToUpb(VALUE value, const char* name,
204
228
  ret.uint64_val = NUM2ULL(value);
205
229
  break;
206
230
  default:
207
- break;
231
+ rb_raise(cTypeError, "Convert_RubyToUpb(): Unexpected type %d",
232
+ (int)type_info.type);
208
233
  }
209
234
  break;
210
235
  default:
@@ -23,6 +23,9 @@ static VALUE get_enumdef_obj(VALUE descriptor_pool, const upb_EnumDef* def);
23
23
  static VALUE get_fielddef_obj(VALUE descriptor_pool, const upb_FieldDef* def);
24
24
  static VALUE get_filedef_obj(VALUE descriptor_pool, const upb_FileDef* def);
25
25
  static VALUE get_oneofdef_obj(VALUE descriptor_pool, const upb_OneofDef* def);
26
+ static VALUE get_servicedef_obj(VALUE descriptor_pool,
27
+ const upb_ServiceDef* def);
28
+ static VALUE get_methoddef_obj(VALUE descriptor_pool, const upb_MethodDef* def);
26
29
 
27
30
  // A distinct object that is not accessible from Ruby. We use this as a
28
31
  // constructor argument to enforce that certain objects cannot be created from
@@ -153,6 +156,7 @@ static VALUE DescriptorPool_lookup(VALUE _self, VALUE name) {
153
156
  const upb_MessageDef* msgdef;
154
157
  const upb_EnumDef* enumdef;
155
158
  const upb_FieldDef* fielddef;
159
+ const upb_ServiceDef* servicedef;
156
160
 
157
161
  msgdef = upb_DefPool_FindMessageByName(self->symtab, name_str);
158
162
  if (msgdef) {
@@ -169,6 +173,11 @@ static VALUE DescriptorPool_lookup(VALUE _self, VALUE name) {
169
173
  return get_enumdef_obj(_self, enumdef);
170
174
  }
171
175
 
176
+ servicedef = upb_DefPool_FindServiceByName(self->symtab, name_str);
177
+ if (servicedef) {
178
+ return get_servicedef_obj(_self, servicedef);
179
+ }
180
+
172
181
  return Qnil;
173
182
  }
174
183
 
@@ -257,7 +266,20 @@ static VALUE decode_options(VALUE self, const char* option_type, int size,
257
266
  VALUE desc_rb = get_msgdef_obj(descriptor_pool, msgdef);
258
267
  const Descriptor* desc = ruby_to_Descriptor(desc_rb);
259
268
 
260
- options_rb = Message_decode_bytes(size, bytes, 0, desc->klass, true);
269
+ options_rb = Message_decode_bytes(size, bytes, 0, desc->klass, false);
270
+
271
+ // Strip features from the options proto to keep it internal.
272
+ const upb_MessageDef* decoded_desc = NULL;
273
+ upb_Message* options = Message_GetMutable(options_rb, &decoded_desc);
274
+ PBRUBY_ASSERT(options != NULL);
275
+ PBRUBY_ASSERT(decoded_desc == msgdef);
276
+ const upb_FieldDef* field =
277
+ upb_MessageDef_FindFieldByName(decoded_desc, "features");
278
+ PBRUBY_ASSERT(field != NULL);
279
+ upb_Message_ClearFieldByDef(options, field);
280
+
281
+ Message_freeze(options_rb);
282
+
261
283
  rb_ivar_set(self, options_instancevar_interned, options_rb);
262
284
  return options_rb;
263
285
  }
@@ -489,7 +511,7 @@ static VALUE FileDescriptor_alloc(VALUE klass) {
489
511
  * call-seq:
490
512
  * FileDescriptor.new => file
491
513
  *
492
- * Returns a new file descriptor. The syntax must be set before it's passed
514
+ * Returns a new file descriptor. May
493
515
  * to a builder.
494
516
  */
495
517
  static VALUE FileDescriptor_initialize(VALUE _self, VALUE cookie,
@@ -519,28 +541,6 @@ static VALUE FileDescriptor_name(VALUE _self) {
519
541
  return name == NULL ? Qnil : rb_str_new2(name);
520
542
  }
521
543
 
522
- /*
523
- * call-seq:
524
- * FileDescriptor.syntax => syntax
525
- *
526
- * Returns this file descriptors syntax.
527
- *
528
- * Valid syntax versions are:
529
- * :proto2 or :proto3.
530
- */
531
- static VALUE FileDescriptor_syntax(VALUE _self) {
532
- FileDescriptor* self = ruby_to_FileDescriptor(_self);
533
-
534
- switch (upb_FileDef_Syntax(self->filedef)) {
535
- case kUpb_Syntax_Proto3:
536
- return ID2SYM(rb_intern("proto3"));
537
- case kUpb_Syntax_Proto2:
538
- return ID2SYM(rb_intern("proto2"));
539
- default:
540
- return Qnil;
541
- }
542
- }
543
-
544
544
  /*
545
545
  * call-seq:
546
546
  * FileDescriptor.options => options
@@ -564,7 +564,6 @@ static void FileDescriptor_register(VALUE module) {
564
564
  rb_define_alloc_func(klass, FileDescriptor_alloc);
565
565
  rb_define_method(klass, "initialize", FileDescriptor_initialize, 3);
566
566
  rb_define_method(klass, "name", FileDescriptor_name, 0);
567
- rb_define_method(klass, "syntax", FileDescriptor_syntax, 0);
568
567
  rb_define_method(klass, "options", FileDescriptor_options, 0);
569
568
  rb_gc_register_address(&cFileDescriptor);
570
569
  cFileDescriptor = klass;
@@ -727,7 +726,7 @@ static VALUE FieldDescriptor__type(VALUE _self) {
727
726
  static VALUE FieldDescriptor_default(VALUE _self) {
728
727
  FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
729
728
  const upb_FieldDef* f = self->fielddef;
730
- upb_MessageValue default_val = {0};
729
+ upb_MessageValue default_val = upb_MessageValue_Zero();
731
730
  if (upb_FieldDef_IsSubMessage(f)) {
732
731
  return Qnil;
733
732
  } else if (!upb_FieldDef_IsRepeated(f)) {
@@ -736,6 +735,28 @@ static VALUE FieldDescriptor_default(VALUE _self) {
736
735
  return Convert_UpbToRuby(default_val, TypeInfo_get(self->fielddef), Qnil);
737
736
  }
738
737
 
738
+ /*
739
+ * call-seq:
740
+ * FieldDescriptor.has_presence? => bool
741
+ *
742
+ * Returns whether this field tracks presence.
743
+ */
744
+ static VALUE FieldDescriptor_has_presence(VALUE _self) {
745
+ FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
746
+ return upb_FieldDef_HasPresence(self->fielddef) ? Qtrue : Qfalse;
747
+ }
748
+
749
+ /*
750
+ * call-seq:
751
+ * FieldDescriptor.is_packed? => bool
752
+ *
753
+ * Returns whether this is a repeated field that uses packed encoding.
754
+ */
755
+ static VALUE FieldDescriptor_is_packed(VALUE _self) {
756
+ FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
757
+ return upb_FieldDef_IsPacked(self->fielddef) ? Qtrue : Qfalse;
758
+ }
759
+
739
760
  /*
740
761
  * call-seq:
741
762
  * FieldDescriptor.json_name => json_name
@@ -943,6 +964,8 @@ static void FieldDescriptor_register(VALUE module) {
943
964
  rb_define_method(klass, "name", FieldDescriptor_name, 0);
944
965
  rb_define_method(klass, "type", FieldDescriptor__type, 0);
945
966
  rb_define_method(klass, "default", FieldDescriptor_default, 0);
967
+ rb_define_method(klass, "has_presence?", FieldDescriptor_has_presence, 0);
968
+ rb_define_method(klass, "is_packed?", FieldDescriptor_is_packed, 0);
946
969
  rb_define_method(klass, "json_name", FieldDescriptor_json_name, 0);
947
970
  rb_define_method(klass, "label", FieldDescriptor_label, 0);
948
971
  rb_define_method(klass, "number", FieldDescriptor_number, 0);
@@ -1163,6 +1186,17 @@ static VALUE EnumDescriptor_file_descriptor(VALUE _self) {
1163
1186
  upb_EnumDef_File(self->enumdef));
1164
1187
  }
1165
1188
 
1189
+ /*
1190
+ * call-seq:
1191
+ * EnumDescriptor.is_closed? => bool
1192
+ *
1193
+ * Returns whether this enum is open or closed.
1194
+ */
1195
+ static VALUE EnumDescriptor_is_closed(VALUE _self) {
1196
+ EnumDescriptor* self = ruby_to_EnumDescriptor(_self);
1197
+ return upb_EnumDef_IsClosed(self->enumdef) ? Qtrue : Qfalse;
1198
+ }
1199
+
1166
1200
  /*
1167
1201
  * call-seq:
1168
1202
  * EnumDescriptor.name => name
@@ -1275,12 +1309,305 @@ static void EnumDescriptor_register(VALUE module) {
1275
1309
  rb_define_method(klass, "each", EnumDescriptor_each, 0);
1276
1310
  rb_define_method(klass, "enummodule", EnumDescriptor_enummodule, 0);
1277
1311
  rb_define_method(klass, "file_descriptor", EnumDescriptor_file_descriptor, 0);
1312
+ rb_define_method(klass, "is_closed?", EnumDescriptor_is_closed, 0);
1278
1313
  rb_define_method(klass, "options", EnumDescriptor_options, 0);
1279
1314
  rb_include_module(klass, rb_mEnumerable);
1280
1315
  rb_gc_register_address(&cEnumDescriptor);
1281
1316
  cEnumDescriptor = klass;
1282
1317
  }
1283
1318
 
1319
+ // -----------------------------------------------------------------------------
1320
+ // ServiceDescriptor
1321
+ // -----------------------------------------------------------------------------
1322
+
1323
+ typedef struct {
1324
+ const upb_ServiceDef* servicedef;
1325
+ // IMPORTANT: WB_PROTECTED objects must only use the RB_OBJ_WRITE()
1326
+ // macro to update VALUE references, as to trigger write barriers.
1327
+ VALUE module; // begins as nil
1328
+ VALUE descriptor_pool; // Owns the upb_ServiceDef.
1329
+ } ServiceDescriptor;
1330
+
1331
+ static VALUE cServiceDescriptor = Qnil;
1332
+
1333
+ static void ServiceDescriptor_mark(void* _self) {
1334
+ ServiceDescriptor* self = _self;
1335
+ rb_gc_mark(self->module);
1336
+ rb_gc_mark(self->descriptor_pool);
1337
+ }
1338
+
1339
+ static const rb_data_type_t ServiceDescriptor_type = {
1340
+ "Google::Protobuf::ServicDescriptor",
1341
+ {ServiceDescriptor_mark, RUBY_DEFAULT_FREE, NULL},
1342
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
1343
+ };
1344
+
1345
+ static ServiceDescriptor* ruby_to_ServiceDescriptor(VALUE val) {
1346
+ ServiceDescriptor* ret;
1347
+ TypedData_Get_Struct(val, ServiceDescriptor, &ServiceDescriptor_type, ret);
1348
+ return ret;
1349
+ }
1350
+
1351
+ static VALUE ServiceDescriptor_alloc(VALUE klass) {
1352
+ ServiceDescriptor* self = ALLOC(ServiceDescriptor);
1353
+ VALUE ret = TypedData_Wrap_Struct(klass, &ServiceDescriptor_type, self);
1354
+ self->servicedef = NULL;
1355
+ self->module = Qnil;
1356
+ self->descriptor_pool = Qnil;
1357
+ return ret;
1358
+ }
1359
+
1360
+ /*
1361
+ * call-seq:
1362
+ * ServiceDescriptor.new(c_only_cookie, ptr) => ServiceDescriptor
1363
+ *
1364
+ * Creates a descriptor wrapper object. May only be called from C.
1365
+ */
1366
+ static VALUE ServiceDescriptor_initialize(VALUE _self, VALUE cookie,
1367
+ VALUE descriptor_pool, VALUE ptr) {
1368
+ ServiceDescriptor* self = ruby_to_ServiceDescriptor(_self);
1369
+
1370
+ if (cookie != c_only_cookie) {
1371
+ rb_raise(rb_eRuntimeError,
1372
+ "Descriptor objects may not be created from Ruby.");
1373
+ }
1374
+
1375
+ RB_OBJ_WRITE(_self, &self->descriptor_pool, descriptor_pool);
1376
+ self->servicedef = (const upb_ServiceDef*)NUM2ULL(ptr);
1377
+
1378
+ return Qnil;
1379
+ }
1380
+
1381
+ /*
1382
+ * call-seq:
1383
+ * ServiceDescriptor.name => name
1384
+ *
1385
+ * Returns the name of this service.
1386
+ */
1387
+ static VALUE ServiceDescriptor_name(VALUE _self) {
1388
+ ServiceDescriptor* self = ruby_to_ServiceDescriptor(_self);
1389
+ return rb_str_maybe_null(upb_ServiceDef_FullName(self->servicedef));
1390
+ }
1391
+
1392
+ /*
1393
+ * call-seq:
1394
+ * ServiceDescriptor.file_descriptor
1395
+ *
1396
+ * Returns the FileDescriptor object this service belongs to.
1397
+ */
1398
+ static VALUE ServiceDescriptor_file_descriptor(VALUE _self) {
1399
+ ServiceDescriptor* self = ruby_to_ServiceDescriptor(_self);
1400
+ return get_filedef_obj(self->descriptor_pool,
1401
+ upb_ServiceDef_File(self->servicedef));
1402
+ }
1403
+
1404
+ /*
1405
+ * call-seq:
1406
+ * ServiceDescriptor.each(&block)
1407
+ *
1408
+ * Iterates over methods in this service, yielding to the block on each one.
1409
+ */
1410
+ static VALUE ServiceDescriptor_each(VALUE _self) {
1411
+ ServiceDescriptor* self = ruby_to_ServiceDescriptor(_self);
1412
+
1413
+ int n = upb_ServiceDef_MethodCount(self->servicedef);
1414
+ for (int i = 0; i < n; i++) {
1415
+ const upb_MethodDef* method = upb_ServiceDef_Method(self->servicedef, i);
1416
+ VALUE obj = get_methoddef_obj(self->descriptor_pool, method);
1417
+ rb_yield(obj);
1418
+ }
1419
+ return Qnil;
1420
+ }
1421
+
1422
+ /*
1423
+ * call-seq:
1424
+ * ServiceDescriptor.options => options
1425
+ *
1426
+ * Returns the `ServiceOptions` for this `ServiceDescriptor`.
1427
+ */
1428
+ static VALUE ServiceDescriptor_options(VALUE _self) {
1429
+ ServiceDescriptor* self = ruby_to_ServiceDescriptor(_self);
1430
+ const google_protobuf_ServiceOptions* opts =
1431
+ upb_ServiceDef_Options(self->servicedef);
1432
+ upb_Arena* arena = upb_Arena_New();
1433
+ size_t size;
1434
+ char* serialized =
1435
+ google_protobuf_ServiceOptions_serialize(opts, arena, &size);
1436
+ VALUE service_options = decode_options(_self, "ServiceOptions", size,
1437
+ serialized, self->descriptor_pool);
1438
+ upb_Arena_Free(arena);
1439
+ return service_options;
1440
+ }
1441
+
1442
+ static void ServiceDescriptor_register(VALUE module) {
1443
+ VALUE klass = rb_define_class_under(module, "ServiceDescriptor", rb_cObject);
1444
+ rb_define_alloc_func(klass, ServiceDescriptor_alloc);
1445
+ rb_define_method(klass, "initialize", ServiceDescriptor_initialize, 3);
1446
+ rb_define_method(klass, "name", ServiceDescriptor_name, 0);
1447
+ rb_define_method(klass, "each", ServiceDescriptor_each, 0);
1448
+ rb_define_method(klass, "file_descriptor", ServiceDescriptor_file_descriptor,
1449
+ 0);
1450
+ rb_define_method(klass, "options", ServiceDescriptor_options, 0);
1451
+ rb_include_module(klass, rb_mEnumerable);
1452
+ rb_gc_register_address(&cServiceDescriptor);
1453
+ cServiceDescriptor = klass;
1454
+ }
1455
+
1456
+ // -----------------------------------------------------------------------------
1457
+ // MethodDescriptor
1458
+ // -----------------------------------------------------------------------------
1459
+
1460
+ typedef struct {
1461
+ const upb_MethodDef* methoddef;
1462
+ // IMPORTANT: WB_PROTECTED objects must only use the RB_OBJ_WRITE()
1463
+ // macro to update VALUE references, as to trigger write barriers.
1464
+ VALUE module; // begins as nil
1465
+ VALUE descriptor_pool; // Owns the upb_MethodDef.
1466
+ } MethodDescriptor;
1467
+
1468
+ static VALUE cMethodDescriptor = Qnil;
1469
+
1470
+ static void MethodDescriptor_mark(void* _self) {
1471
+ MethodDescriptor* self = _self;
1472
+ rb_gc_mark(self->module);
1473
+ rb_gc_mark(self->descriptor_pool);
1474
+ }
1475
+
1476
+ static const rb_data_type_t MethodDescriptor_type = {
1477
+ "Google::Protobuf::MethodDescriptor",
1478
+ {MethodDescriptor_mark, RUBY_DEFAULT_FREE, NULL},
1479
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
1480
+ };
1481
+
1482
+ static MethodDescriptor* ruby_to_MethodDescriptor(VALUE val) {
1483
+ MethodDescriptor* ret;
1484
+ TypedData_Get_Struct(val, MethodDescriptor, &MethodDescriptor_type, ret);
1485
+ return ret;
1486
+ }
1487
+
1488
+ static VALUE MethodDescriptor_alloc(VALUE klass) {
1489
+ MethodDescriptor* self = ALLOC(MethodDescriptor);
1490
+ VALUE ret = TypedData_Wrap_Struct(klass, &MethodDescriptor_type, self);
1491
+ self->methoddef = NULL;
1492
+ self->module = Qnil;
1493
+ self->descriptor_pool = Qnil;
1494
+ return ret;
1495
+ }
1496
+
1497
+ /*
1498
+ * call-seq:
1499
+ * MethodDescriptor.new(c_only_cookie, ptr) => MethodDescriptor
1500
+ *
1501
+ * Creates a descriptor wrapper object. May only be called from C.
1502
+ */
1503
+ static VALUE MethodDescriptor_initialize(VALUE _self, VALUE cookie,
1504
+ VALUE descriptor_pool, VALUE ptr) {
1505
+ MethodDescriptor* self = ruby_to_MethodDescriptor(_self);
1506
+
1507
+ if (cookie != c_only_cookie) {
1508
+ rb_raise(rb_eRuntimeError,
1509
+ "Descriptor objects may not be created from Ruby.");
1510
+ }
1511
+
1512
+ RB_OBJ_WRITE(_self, &self->descriptor_pool, descriptor_pool);
1513
+ self->methoddef = (const upb_MethodDef*)NUM2ULL(ptr);
1514
+
1515
+ return Qnil;
1516
+ }
1517
+
1518
+ /*
1519
+ * call-seq:
1520
+ * MethodDescriptor.name => name
1521
+ *
1522
+ * Returns the name of this method
1523
+ */
1524
+ static VALUE MethodDescriptor_name(VALUE _self) {
1525
+ MethodDescriptor* self = ruby_to_MethodDescriptor(_self);
1526
+ return rb_str_maybe_null(upb_MethodDef_Name(self->methoddef));
1527
+ }
1528
+
1529
+ /*
1530
+ * call-seq:
1531
+ * MethodDescriptor.options => options
1532
+ *
1533
+ * Returns the `MethodOptions` for this `MethodDescriptor`.
1534
+ */
1535
+ static VALUE MethodDescriptor_options(VALUE _self) {
1536
+ MethodDescriptor* self = ruby_to_MethodDescriptor(_self);
1537
+ const google_protobuf_MethodOptions* opts =
1538
+ upb_MethodDef_Options(self->methoddef);
1539
+ upb_Arena* arena = upb_Arena_New();
1540
+ size_t size;
1541
+ char* serialized =
1542
+ google_protobuf_MethodOptions_serialize(opts, arena, &size);
1543
+ VALUE method_options = decode_options(_self, "MethodOptions", size,
1544
+ serialized, self->descriptor_pool);
1545
+ upb_Arena_Free(arena);
1546
+ return method_options;
1547
+ }
1548
+
1549
+ /*
1550
+ * call-seq:
1551
+ * MethodDescriptor.input_type => Descriptor
1552
+ *
1553
+ * Returns the `Descriptor` for the request message type of this method
1554
+ */
1555
+ static VALUE MethodDescriptor_input_type(VALUE _self) {
1556
+ MethodDescriptor* self = ruby_to_MethodDescriptor(_self);
1557
+ const upb_MessageDef* type = upb_MethodDef_InputType(self->methoddef);
1558
+ return get_msgdef_obj(self->descriptor_pool, type);
1559
+ }
1560
+
1561
+ /*
1562
+ * call-seq:
1563
+ * MethodDescriptor.output_type => Descriptor
1564
+ *
1565
+ * Returns the `Descriptor` for the response message type of this method
1566
+ */
1567
+ static VALUE MethodDescriptor_output_type(VALUE _self) {
1568
+ MethodDescriptor* self = ruby_to_MethodDescriptor(_self);
1569
+ const upb_MessageDef* type = upb_MethodDef_OutputType(self->methoddef);
1570
+ return get_msgdef_obj(self->descriptor_pool, type);
1571
+ }
1572
+
1573
+ /*
1574
+ * call-seq:
1575
+ * MethodDescriptor.client_streaming => bool
1576
+ *
1577
+ * Returns whether or not this is a streaming request method
1578
+ */
1579
+ static VALUE MethodDescriptor_client_streaming(VALUE _self) {
1580
+ MethodDescriptor* self = ruby_to_MethodDescriptor(_self);
1581
+ return upb_MethodDef_ClientStreaming(self->methoddef) ? Qtrue : Qfalse;
1582
+ }
1583
+
1584
+ /*
1585
+ * call-seq:
1586
+ * MethodDescriptor.server_streaming => bool
1587
+ *
1588
+ * Returns whether or not this is a streaming response method
1589
+ */
1590
+ static VALUE MethodDescriptor_server_streaming(VALUE _self) {
1591
+ MethodDescriptor* self = ruby_to_MethodDescriptor(_self);
1592
+ return upb_MethodDef_ServerStreaming(self->methoddef) ? Qtrue : Qfalse;
1593
+ }
1594
+
1595
+ static void MethodDescriptor_register(VALUE module) {
1596
+ VALUE klass = rb_define_class_under(module, "MethodDescriptor", rb_cObject);
1597
+ rb_define_alloc_func(klass, MethodDescriptor_alloc);
1598
+ rb_define_method(klass, "initialize", MethodDescriptor_initialize, 3);
1599
+ rb_define_method(klass, "name", MethodDescriptor_name, 0);
1600
+ rb_define_method(klass, "options", MethodDescriptor_options, 0);
1601
+ rb_define_method(klass, "input_type", MethodDescriptor_input_type, 0);
1602
+ rb_define_method(klass, "output_type", MethodDescriptor_output_type, 0);
1603
+ rb_define_method(klass, "client_streaming", MethodDescriptor_client_streaming,
1604
+ 0);
1605
+ rb_define_method(klass, "server_streaming", MethodDescriptor_server_streaming,
1606
+ 0);
1607
+ rb_gc_register_address(&cMethodDescriptor);
1608
+ cMethodDescriptor = klass;
1609
+ }
1610
+
1284
1611
  static VALUE get_def_obj(VALUE _descriptor_pool, const void* ptr, VALUE klass) {
1285
1612
  DescriptorPool* descriptor_pool = ruby_to_DescriptorPool(_descriptor_pool);
1286
1613
  VALUE key = ULL2NUM((intptr_t)ptr);
@@ -1322,6 +1649,16 @@ static VALUE get_oneofdef_obj(VALUE descriptor_pool, const upb_OneofDef* def) {
1322
1649
  return get_def_obj(descriptor_pool, def, cOneofDescriptor);
1323
1650
  }
1324
1651
 
1652
+ static VALUE get_servicedef_obj(VALUE descriptor_pool,
1653
+ const upb_ServiceDef* def) {
1654
+ return get_def_obj(descriptor_pool, def, cServiceDescriptor);
1655
+ }
1656
+
1657
+ static VALUE get_methoddef_obj(VALUE descriptor_pool,
1658
+ const upb_MethodDef* def) {
1659
+ return get_def_obj(descriptor_pool, def, cMethodDescriptor);
1660
+ }
1661
+
1325
1662
  // -----------------------------------------------------------------------------
1326
1663
  // Shared functions
1327
1664
  // -----------------------------------------------------------------------------
@@ -1397,6 +1734,8 @@ void Defs_register(VALUE module) {
1397
1734
  FieldDescriptor_register(module);
1398
1735
  OneofDescriptor_register(module);
1399
1736
  EnumDescriptor_register(module);
1737
+ ServiceDescriptor_register(module);
1738
+ MethodDescriptor_register(module);
1400
1739
 
1401
1740
  rb_gc_register_address(&c_only_cookie);
1402
1741
  c_only_cookie = rb_class_new_instance(0, NULL, rb_cObject);
@@ -22,7 +22,7 @@ $INCFLAGS += " -I$(srcdir)/third_party/utf8_range"
22
22
 
23
23
  $srcs = ["protobuf.c", "convert.c", "defs.c", "message.c",
24
24
  "repeated_field.c", "map.c", "ruby-upb.c", "wrap_memcpy.c",
25
- "naive.c", "range2-neon.c", "range2-sse.c", "shared_convert.c",
25
+ "utf8_range.c", "shared_convert.c",
26
26
  "shared_message.c"]
27
27
 
28
28
  create_makefile(ext_name)
@@ -54,3 +54,19 @@ char* FieldDescriptor_serialized_options(const upb_FieldDef* fielddef,
54
54
  char* serialized = google_protobuf_FieldOptions_serialize(opts, arena, size);
55
55
  return serialized;
56
56
  }
57
+
58
+ char* ServiceDescriptor_serialized_options(const upb_ServiceDef* servicedef,
59
+ size_t* size, upb_Arena* arena) {
60
+ const google_protobuf_ServiceOptions* opts =
61
+ upb_ServiceDef_Options(servicedef);
62
+ char* serialized =
63
+ google_protobuf_ServiceOptions_serialize(opts, arena, size);
64
+ return serialized;
65
+ }
66
+
67
+ char* MethodDescriptor_serialized_options(const upb_MethodDef* methoddef,
68
+ size_t* size, upb_Arena* arena) {
69
+ const google_protobuf_MethodOptions* opts = upb_MethodDef_Options(methoddef);
70
+ char* serialized = google_protobuf_MethodOptions_serialize(opts, arena, size);
71
+ return serialized;
72
+ }