google-protobuf 3.25.3 → 4.29.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/ext/google/protobuf_c/convert.c +46 -18
  3. data/ext/google/protobuf_c/defs.c +368 -30
  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 +74 -29
  7. data/ext/google/protobuf_c/map.h +7 -3
  8. data/ext/google/protobuf_c/message.c +120 -118
  9. data/ext/google/protobuf_c/message.h +2 -6
  10. data/ext/google/protobuf_c/protobuf.c +30 -17
  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 +13774 -11526
  15. data/ext/google/protobuf_c/ruby-upb.h +11198 -9048
  16. data/ext/google/protobuf_c/shared_convert.c +10 -5
  17. data/ext/google/protobuf_c/shared_convert.h +2 -2
  18. data/ext/google/protobuf_c/shared_message.c +3 -31
  19. data/ext/google/protobuf_c/shared_message.h +0 -4
  20. data/ext/google/protobuf_c/third_party/utf8_range/utf8_range.c +467 -0
  21. data/ext/google/protobuf_c/third_party/utf8_range/utf8_range.h +9 -8
  22. data/lib/google/protobuf/any_pb.rb +1 -22
  23. data/lib/google/protobuf/api_pb.rb +1 -24
  24. data/lib/google/protobuf/descriptor_pb.rb +3 -23
  25. data/lib/google/protobuf/duration_pb.rb +1 -22
  26. data/lib/google/protobuf/empty_pb.rb +1 -22
  27. data/lib/google/protobuf/ffi/descriptor.rb +4 -4
  28. data/lib/google/protobuf/ffi/descriptor_pool.rb +3 -1
  29. data/lib/google/protobuf/ffi/enum_descriptor.rb +3 -1
  30. data/lib/google/protobuf/ffi/ffi.rb +8 -6
  31. data/lib/google/protobuf/ffi/field_descriptor.rb +13 -2
  32. data/lib/google/protobuf/ffi/file_descriptor.rb +3 -13
  33. data/lib/google/protobuf/ffi/internal/arena.rb +0 -6
  34. data/lib/google/protobuf/ffi/internal/convert.rb +21 -30
  35. data/lib/google/protobuf/ffi/map.rb +50 -24
  36. data/lib/google/protobuf/ffi/message.rb +189 -66
  37. data/lib/google/protobuf/ffi/method_descriptor.rb +114 -0
  38. data/lib/google/protobuf/ffi/object_cache.rb +3 -3
  39. data/lib/google/protobuf/ffi/oneof_descriptor.rb +3 -1
  40. data/lib/google/protobuf/ffi/repeated_field.rb +47 -19
  41. data/lib/google/protobuf/ffi/service_descriptor.rb +107 -0
  42. data/lib/google/protobuf/field_mask_pb.rb +1 -22
  43. data/lib/google/protobuf/internal/object_cache.rb +99 -0
  44. data/lib/google/protobuf/plugin_pb.rb +2 -24
  45. data/lib/google/protobuf/repeated_field.rb +4 -5
  46. data/lib/google/protobuf/source_context_pb.rb +1 -22
  47. data/lib/google/protobuf/struct_pb.rb +1 -22
  48. data/lib/google/protobuf/timestamp_pb.rb +1 -22
  49. data/lib/google/protobuf/type_pb.rb +1 -24
  50. data/lib/google/protobuf/wrappers_pb.rb +1 -22
  51. data/lib/google/protobuf.rb +1 -1
  52. data/lib/google/protobuf_ffi.rb +3 -2
  53. data/lib/google/protobuf_native.rb +0 -1
  54. data/lib/google/tasks/ffi.rake +1 -3
  55. metadata +25 -12
  56. data/ext/google/protobuf_c/third_party/utf8_range/naive.c +0 -92
  57. data/ext/google/protobuf_c/third_party/utf8_range/range2-neon.c +0 -157
  58. data/ext/google/protobuf_c/third_party/utf8_range/range2-sse.c +0 -170
  59. data/lib/google/protobuf/descriptor_dsl.rb +0 -465
  60. data/lib/google/protobuf/object_cache.rb +0 -97
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7cabebe8487759e6e7876a1a4c69fd7751bb22aad693fbe82e91e14c984bbf8e
4
- data.tar.gz: 9e57bf2ee2ebef1063605d28ecb713c0851f94d0d66222d0fc24841b9b868089
3
+ metadata.gz: c85266e702141e736a1031dbf1b18b8d430fd48d7cc74e89d003b184165dc92e
4
+ data.tar.gz: d24556778881104315a347b997525a3baad6df159ebfb1db7bcb0e0ef0a085a2
5
5
  SHA512:
6
- metadata.gz: 8a76ee7003807d5b6e37da0bf6129a761f08ac00b26e9df59e33f8f6325a642dd501655accc7d2943ec233518e9d6d10fe6c21efbe6b91b860f101fff8fca9ee
7
- data.tar.gz: 41dd9a63af13bc7e88c765254fd15bc62f588cc3ab14b0696632fe93d2de00b3e1c9e7bfe01b48b13dc0943176bf86e2cfdba011046c94d11eefabd320e2391b
6
+ metadata.gz: f45523e01c1ccd6572b4917d2f532b676db6b515613c3252bdd50309d552ee9f7eff005248b8f7f076b818616bb2b9601d5a0c398dcf9ee198236c5399d5d85e
7
+ data.tar.gz: a2dfb8d26a0a0155e28b8cb4d6e086a12a3f942cdf70b805ee6543a7eed0f3f52288705578517e393e4be2774eef7d158ad3138ecdb36c333133e1c4f72b051e
@@ -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,11 +228,13 @@ 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:
211
- break;
236
+ rb_raise(cTypeError,
237
+ "Convert_RubyToUpb(): Unexpected type %d", (int)type_info.type);
212
238
  }
213
239
 
214
240
  return ret;
@@ -296,7 +322,8 @@ bool Msgval_IsEqual(upb_MessageValue val1, upb_MessageValue val2,
296
322
  if (upb_Status_IsOk(&status)) {
297
323
  return return_value;
298
324
  } else {
299
- rb_raise(rb_eRuntimeError, upb_Status_ErrorMessage(&status));
325
+ rb_raise(rb_eRuntimeError, "Msgval_IsEqual(): %s",
326
+ upb_Status_ErrorMessage(&status));
300
327
  }
301
328
  }
302
329
 
@@ -309,6 +336,7 @@ uint64_t Msgval_GetHash(upb_MessageValue val, TypeInfo type_info,
309
336
  if (upb_Status_IsOk(&status)) {
310
337
  return return_value;
311
338
  } else {
312
- rb_raise(rb_eRuntimeError, upb_Status_ErrorMessage(&status));
339
+ rb_raise(rb_eRuntimeError, "Msgval_GetHash(): %s",
340
+ upb_Status_ErrorMessage(&status));
313
341
  }
314
342
  }
@@ -7,7 +7,6 @@
7
7
 
8
8
  #include <ctype.h>
9
9
  #include <errno.h>
10
- #include <ruby/version.h>
11
10
 
12
11
  #include "convert.h"
13
12
  #include "message.h"
@@ -23,6 +22,9 @@ static VALUE get_enumdef_obj(VALUE descriptor_pool, const upb_EnumDef* def);
23
22
  static VALUE get_fielddef_obj(VALUE descriptor_pool, const upb_FieldDef* def);
24
23
  static VALUE get_filedef_obj(VALUE descriptor_pool, const upb_FileDef* def);
25
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);
26
28
 
27
29
  // A distinct object that is not accessible from Ruby. We use this as a
28
30
  // constructor argument to enforce that certain objects cannot be created from
@@ -153,6 +155,7 @@ static VALUE DescriptorPool_lookup(VALUE _self, VALUE name) {
153
155
  const upb_MessageDef* msgdef;
154
156
  const upb_EnumDef* enumdef;
155
157
  const upb_FieldDef* fielddef;
158
+ const upb_ServiceDef* servicedef;
156
159
 
157
160
  msgdef = upb_DefPool_FindMessageByName(self->symtab, name_str);
158
161
  if (msgdef) {
@@ -169,6 +172,11 @@ static VALUE DescriptorPool_lookup(VALUE _self, VALUE name) {
169
172
  return get_enumdef_obj(_self, enumdef);
170
173
  }
171
174
 
175
+ servicedef = upb_DefPool_FindServiceByName(self->symtab, name_str);
176
+ if (servicedef) {
177
+ return get_servicedef_obj(_self, servicedef);
178
+ }
179
+
172
180
  return Qnil;
173
181
  }
174
182
 
@@ -257,7 +265,20 @@ static VALUE decode_options(VALUE self, const char* option_type, int size,
257
265
  VALUE desc_rb = get_msgdef_obj(descriptor_pool, msgdef);
258
266
  const Descriptor* desc = ruby_to_Descriptor(desc_rb);
259
267
 
260
- options_rb = Message_decode_bytes(size, bytes, 0, desc->klass, true);
268
+ options_rb = Message_decode_bytes(size, bytes, 0, desc->klass, false);
269
+
270
+ // Strip features from the options proto to keep it internal.
271
+ const upb_MessageDef* decoded_desc = NULL;
272
+ upb_Message* options = Message_GetMutable(options_rb, &decoded_desc);
273
+ PBRUBY_ASSERT(options != NULL);
274
+ PBRUBY_ASSERT(decoded_desc == msgdef);
275
+ const upb_FieldDef* field =
276
+ upb_MessageDef_FindFieldByName(decoded_desc, "features");
277
+ PBRUBY_ASSERT(field != NULL);
278
+ upb_Message_ClearFieldByDef(options, field);
279
+
280
+ Message_freeze(options_rb);
281
+
261
282
  rb_ivar_set(self, options_instancevar_interned, options_rb);
262
283
  return options_rb;
263
284
  }
@@ -489,7 +510,7 @@ static VALUE FileDescriptor_alloc(VALUE klass) {
489
510
  * call-seq:
490
511
  * FileDescriptor.new => file
491
512
  *
492
- * Returns a new file descriptor. The syntax must be set before it's passed
513
+ * Returns a new file descriptor. May
493
514
  * to a builder.
494
515
  */
495
516
  static VALUE FileDescriptor_initialize(VALUE _self, VALUE cookie,
@@ -519,28 +540,6 @@ static VALUE FileDescriptor_name(VALUE _self) {
519
540
  return name == NULL ? Qnil : rb_str_new2(name);
520
541
  }
521
542
 
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
543
  /*
545
544
  * call-seq:
546
545
  * FileDescriptor.options => options
@@ -564,7 +563,6 @@ static void FileDescriptor_register(VALUE module) {
564
563
  rb_define_alloc_func(klass, FileDescriptor_alloc);
565
564
  rb_define_method(klass, "initialize", FileDescriptor_initialize, 3);
566
565
  rb_define_method(klass, "name", FileDescriptor_name, 0);
567
- rb_define_method(klass, "syntax", FileDescriptor_syntax, 0);
568
566
  rb_define_method(klass, "options", FileDescriptor_options, 0);
569
567
  rb_gc_register_address(&cFileDescriptor);
570
568
  cFileDescriptor = klass;
@@ -727,7 +725,7 @@ static VALUE FieldDescriptor__type(VALUE _self) {
727
725
  static VALUE FieldDescriptor_default(VALUE _self) {
728
726
  FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
729
727
  const upb_FieldDef* f = self->fielddef;
730
- upb_MessageValue default_val = {0};
728
+ upb_MessageValue default_val = upb_MessageValue_Zero();
731
729
  if (upb_FieldDef_IsSubMessage(f)) {
732
730
  return Qnil;
733
731
  } else if (!upb_FieldDef_IsRepeated(f)) {
@@ -736,6 +734,28 @@ static VALUE FieldDescriptor_default(VALUE _self) {
736
734
  return Convert_UpbToRuby(default_val, TypeInfo_get(self->fielddef), Qnil);
737
735
  }
738
736
 
737
+ /*
738
+ * call-seq:
739
+ * FieldDescriptor.has_presence? => bool
740
+ *
741
+ * Returns whether this field tracks presence.
742
+ */
743
+ static VALUE FieldDescriptor_has_presence(VALUE _self) {
744
+ FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
745
+ return upb_FieldDef_HasPresence(self->fielddef) ? Qtrue : Qfalse;
746
+ }
747
+
748
+ /*
749
+ * call-seq:
750
+ * FieldDescriptor.is_packed? => bool
751
+ *
752
+ * Returns whether this is a repeated field that uses packed encoding.
753
+ */
754
+ static VALUE FieldDescriptor_is_packed(VALUE _self) {
755
+ FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
756
+ return upb_FieldDef_IsPacked(self->fielddef) ? Qtrue : Qfalse;
757
+ }
758
+
739
759
  /*
740
760
  * call-seq:
741
761
  * FieldDescriptor.json_name => json_name
@@ -862,7 +882,7 @@ static VALUE FieldDescriptor_get(VALUE _self, VALUE msg_rb) {
862
882
  static VALUE FieldDescriptor_has(VALUE _self, VALUE msg_rb) {
863
883
  FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
864
884
  const upb_MessageDef* m;
865
- const upb_MessageDef* msg = Message_Get(msg_rb, &m);
885
+ const upb_Message* msg = Message_Get(msg_rb, &m);
866
886
 
867
887
  if (m != upb_FieldDef_ContainingType(self->fielddef)) {
868
888
  rb_raise(cTypeError, "has method called on wrong message type");
@@ -882,7 +902,7 @@ static VALUE FieldDescriptor_has(VALUE _self, VALUE msg_rb) {
882
902
  static VALUE FieldDescriptor_clear(VALUE _self, VALUE msg_rb) {
883
903
  FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
884
904
  const upb_MessageDef* m;
885
- upb_MessageDef* msg = Message_GetMutable(msg_rb, &m);
905
+ upb_Message* msg = Message_GetMutable(msg_rb, &m);
886
906
 
887
907
  if (m != upb_FieldDef_ContainingType(self->fielddef)) {
888
908
  rb_raise(cTypeError, "has method called on wrong message type");
@@ -903,7 +923,7 @@ static VALUE FieldDescriptor_clear(VALUE _self, VALUE msg_rb) {
903
923
  static VALUE FieldDescriptor_set(VALUE _self, VALUE msg_rb, VALUE value) {
904
924
  FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
905
925
  const upb_MessageDef* m;
906
- upb_MessageDef* msg = Message_GetMutable(msg_rb, &m);
926
+ upb_Message* msg = Message_GetMutable(msg_rb, &m);
907
927
  upb_Arena* arena = Arena_get(Message_GetArena(msg_rb));
908
928
  upb_MessageValue msgval;
909
929
 
@@ -943,6 +963,8 @@ static void FieldDescriptor_register(VALUE module) {
943
963
  rb_define_method(klass, "name", FieldDescriptor_name, 0);
944
964
  rb_define_method(klass, "type", FieldDescriptor__type, 0);
945
965
  rb_define_method(klass, "default", FieldDescriptor_default, 0);
966
+ rb_define_method(klass, "has_presence?", FieldDescriptor_has_presence, 0);
967
+ rb_define_method(klass, "is_packed?", FieldDescriptor_is_packed, 0);
946
968
  rb_define_method(klass, "json_name", FieldDescriptor_json_name, 0);
947
969
  rb_define_method(klass, "label", FieldDescriptor_label, 0);
948
970
  rb_define_method(klass, "number", FieldDescriptor_number, 0);
@@ -1163,6 +1185,17 @@ static VALUE EnumDescriptor_file_descriptor(VALUE _self) {
1163
1185
  upb_EnumDef_File(self->enumdef));
1164
1186
  }
1165
1187
 
1188
+ /*
1189
+ * call-seq:
1190
+ * EnumDescriptor.is_closed? => bool
1191
+ *
1192
+ * Returns whether this enum is open or closed.
1193
+ */
1194
+ static VALUE EnumDescriptor_is_closed(VALUE _self) {
1195
+ EnumDescriptor* self = ruby_to_EnumDescriptor(_self);
1196
+ return upb_EnumDef_IsClosed(self->enumdef) ? Qtrue : Qfalse;
1197
+ }
1198
+
1166
1199
  /*
1167
1200
  * call-seq:
1168
1201
  * EnumDescriptor.name => name
@@ -1275,12 +1308,305 @@ static void EnumDescriptor_register(VALUE module) {
1275
1308
  rb_define_method(klass, "each", EnumDescriptor_each, 0);
1276
1309
  rb_define_method(klass, "enummodule", EnumDescriptor_enummodule, 0);
1277
1310
  rb_define_method(klass, "file_descriptor", EnumDescriptor_file_descriptor, 0);
1311
+ rb_define_method(klass, "is_closed?", EnumDescriptor_is_closed, 0);
1278
1312
  rb_define_method(klass, "options", EnumDescriptor_options, 0);
1279
1313
  rb_include_module(klass, rb_mEnumerable);
1280
1314
  rb_gc_register_address(&cEnumDescriptor);
1281
1315
  cEnumDescriptor = klass;
1282
1316
  }
1283
1317
 
1318
+ // -----------------------------------------------------------------------------
1319
+ // ServiceDescriptor
1320
+ // -----------------------------------------------------------------------------
1321
+
1322
+ typedef struct {
1323
+ const upb_ServiceDef* servicedef;
1324
+ // IMPORTANT: WB_PROTECTED objects must only use the RB_OBJ_WRITE()
1325
+ // macro to update VALUE references, as to trigger write barriers.
1326
+ VALUE module; // begins as nil
1327
+ VALUE descriptor_pool; // Owns the upb_ServiceDef.
1328
+ } ServiceDescriptor;
1329
+
1330
+ static VALUE cServiceDescriptor = Qnil;
1331
+
1332
+ static void ServiceDescriptor_mark(void* _self) {
1333
+ ServiceDescriptor* self = _self;
1334
+ rb_gc_mark(self->module);
1335
+ rb_gc_mark(self->descriptor_pool);
1336
+ }
1337
+
1338
+ static const rb_data_type_t ServiceDescriptor_type = {
1339
+ "Google::Protobuf::ServicDescriptor",
1340
+ {ServiceDescriptor_mark, RUBY_DEFAULT_FREE, NULL},
1341
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
1342
+ };
1343
+
1344
+ static ServiceDescriptor* ruby_to_ServiceDescriptor(VALUE val) {
1345
+ ServiceDescriptor* ret;
1346
+ TypedData_Get_Struct(val, ServiceDescriptor, &ServiceDescriptor_type, ret);
1347
+ return ret;
1348
+ }
1349
+
1350
+ static VALUE ServiceDescriptor_alloc(VALUE klass) {
1351
+ ServiceDescriptor* self = ALLOC(ServiceDescriptor);
1352
+ VALUE ret = TypedData_Wrap_Struct(klass, &ServiceDescriptor_type, self);
1353
+ self->servicedef = NULL;
1354
+ self->module = Qnil;
1355
+ self->descriptor_pool = Qnil;
1356
+ return ret;
1357
+ }
1358
+
1359
+ /*
1360
+ * call-seq:
1361
+ * ServiceDescriptor.new(c_only_cookie, ptr) => ServiceDescriptor
1362
+ *
1363
+ * Creates a descriptor wrapper object. May only be called from C.
1364
+ */
1365
+ static VALUE ServiceDescriptor_initialize(VALUE _self, VALUE cookie,
1366
+ VALUE descriptor_pool, VALUE ptr) {
1367
+ ServiceDescriptor* self = ruby_to_ServiceDescriptor(_self);
1368
+
1369
+ if (cookie != c_only_cookie) {
1370
+ rb_raise(rb_eRuntimeError,
1371
+ "Descriptor objects may not be created from Ruby.");
1372
+ }
1373
+
1374
+ RB_OBJ_WRITE(_self, &self->descriptor_pool, descriptor_pool);
1375
+ self->servicedef = (const upb_ServiceDef*)NUM2ULL(ptr);
1376
+
1377
+ return Qnil;
1378
+ }
1379
+
1380
+ /*
1381
+ * call-seq:
1382
+ * ServiceDescriptor.name => name
1383
+ *
1384
+ * Returns the name of this service.
1385
+ */
1386
+ static VALUE ServiceDescriptor_name(VALUE _self) {
1387
+ ServiceDescriptor* self = ruby_to_ServiceDescriptor(_self);
1388
+ return rb_str_maybe_null(upb_ServiceDef_FullName(self->servicedef));
1389
+ }
1390
+
1391
+ /*
1392
+ * call-seq:
1393
+ * ServiceDescriptor.file_descriptor
1394
+ *
1395
+ * Returns the FileDescriptor object this service belongs to.
1396
+ */
1397
+ static VALUE ServiceDescriptor_file_descriptor(VALUE _self) {
1398
+ ServiceDescriptor* self = ruby_to_ServiceDescriptor(_self);
1399
+ return get_filedef_obj(self->descriptor_pool,
1400
+ upb_ServiceDef_File(self->servicedef));
1401
+ }
1402
+
1403
+ /*
1404
+ * call-seq:
1405
+ * ServiceDescriptor.each(&block)
1406
+ *
1407
+ * Iterates over methods in this service, yielding to the block on each one.
1408
+ */
1409
+ static VALUE ServiceDescriptor_each(VALUE _self) {
1410
+ ServiceDescriptor* self = ruby_to_ServiceDescriptor(_self);
1411
+
1412
+ int n = upb_ServiceDef_MethodCount(self->servicedef);
1413
+ for (int i = 0; i < n; i++) {
1414
+ const upb_MethodDef* method = upb_ServiceDef_Method(self->servicedef, i);
1415
+ VALUE obj = get_methoddef_obj(self->descriptor_pool, method);
1416
+ rb_yield(obj);
1417
+ }
1418
+ return Qnil;
1419
+ }
1420
+
1421
+ /*
1422
+ * call-seq:
1423
+ * ServiceDescriptor.options => options
1424
+ *
1425
+ * Returns the `ServiceOptions` for this `ServiceDescriptor`.
1426
+ */
1427
+ static VALUE ServiceDescriptor_options(VALUE _self) {
1428
+ ServiceDescriptor* self = ruby_to_ServiceDescriptor(_self);
1429
+ const google_protobuf_ServiceOptions* opts =
1430
+ upb_ServiceDef_Options(self->servicedef);
1431
+ upb_Arena* arena = upb_Arena_New();
1432
+ size_t size;
1433
+ char* serialized =
1434
+ google_protobuf_ServiceOptions_serialize(opts, arena, &size);
1435
+ VALUE service_options = decode_options(_self, "ServiceOptions", size,
1436
+ serialized, self->descriptor_pool);
1437
+ upb_Arena_Free(arena);
1438
+ return service_options;
1439
+ }
1440
+
1441
+ static void ServiceDescriptor_register(VALUE module) {
1442
+ VALUE klass = rb_define_class_under(module, "ServiceDescriptor", rb_cObject);
1443
+ rb_define_alloc_func(klass, ServiceDescriptor_alloc);
1444
+ rb_define_method(klass, "initialize", ServiceDescriptor_initialize, 3);
1445
+ rb_define_method(klass, "name", ServiceDescriptor_name, 0);
1446
+ rb_define_method(klass, "each", ServiceDescriptor_each, 0);
1447
+ rb_define_method(klass, "file_descriptor", ServiceDescriptor_file_descriptor,
1448
+ 0);
1449
+ rb_define_method(klass, "options", ServiceDescriptor_options, 0);
1450
+ rb_include_module(klass, rb_mEnumerable);
1451
+ rb_gc_register_address(&cServiceDescriptor);
1452
+ cServiceDescriptor = klass;
1453
+ }
1454
+
1455
+ // -----------------------------------------------------------------------------
1456
+ // MethodDescriptor
1457
+ // -----------------------------------------------------------------------------
1458
+
1459
+ typedef struct {
1460
+ const upb_MethodDef* methoddef;
1461
+ // IMPORTANT: WB_PROTECTED objects must only use the RB_OBJ_WRITE()
1462
+ // macro to update VALUE references, as to trigger write barriers.
1463
+ VALUE module; // begins as nil
1464
+ VALUE descriptor_pool; // Owns the upb_MethodDef.
1465
+ } MethodDescriptor;
1466
+
1467
+ static VALUE cMethodDescriptor = Qnil;
1468
+
1469
+ static void MethodDescriptor_mark(void* _self) {
1470
+ MethodDescriptor* self = _self;
1471
+ rb_gc_mark(self->module);
1472
+ rb_gc_mark(self->descriptor_pool);
1473
+ }
1474
+
1475
+ static const rb_data_type_t MethodDescriptor_type = {
1476
+ "Google::Protobuf::MethodDescriptor",
1477
+ {MethodDescriptor_mark, RUBY_DEFAULT_FREE, NULL},
1478
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
1479
+ };
1480
+
1481
+ static MethodDescriptor* ruby_to_MethodDescriptor(VALUE val) {
1482
+ MethodDescriptor* ret;
1483
+ TypedData_Get_Struct(val, MethodDescriptor, &MethodDescriptor_type, ret);
1484
+ return ret;
1485
+ }
1486
+
1487
+ static VALUE MethodDescriptor_alloc(VALUE klass) {
1488
+ MethodDescriptor* self = ALLOC(MethodDescriptor);
1489
+ VALUE ret = TypedData_Wrap_Struct(klass, &MethodDescriptor_type, self);
1490
+ self->methoddef = NULL;
1491
+ self->module = Qnil;
1492
+ self->descriptor_pool = Qnil;
1493
+ return ret;
1494
+ }
1495
+
1496
+ /*
1497
+ * call-seq:
1498
+ * MethodDescriptor.new(c_only_cookie, ptr) => MethodDescriptor
1499
+ *
1500
+ * Creates a descriptor wrapper object. May only be called from C.
1501
+ */
1502
+ static VALUE MethodDescriptor_initialize(VALUE _self, VALUE cookie,
1503
+ VALUE descriptor_pool, VALUE ptr) {
1504
+ MethodDescriptor* self = ruby_to_MethodDescriptor(_self);
1505
+
1506
+ if (cookie != c_only_cookie) {
1507
+ rb_raise(rb_eRuntimeError,
1508
+ "Descriptor objects may not be created from Ruby.");
1509
+ }
1510
+
1511
+ RB_OBJ_WRITE(_self, &self->descriptor_pool, descriptor_pool);
1512
+ self->methoddef = (const upb_MethodDef*)NUM2ULL(ptr);
1513
+
1514
+ return Qnil;
1515
+ }
1516
+
1517
+ /*
1518
+ * call-seq:
1519
+ * MethodDescriptor.name => name
1520
+ *
1521
+ * Returns the name of this method
1522
+ */
1523
+ static VALUE MethodDescriptor_name(VALUE _self) {
1524
+ MethodDescriptor* self = ruby_to_MethodDescriptor(_self);
1525
+ return rb_str_maybe_null(upb_MethodDef_Name(self->methoddef));
1526
+ }
1527
+
1528
+ /*
1529
+ * call-seq:
1530
+ * MethodDescriptor.options => options
1531
+ *
1532
+ * Returns the `MethodOptions` for this `MethodDescriptor`.
1533
+ */
1534
+ static VALUE MethodDescriptor_options(VALUE _self) {
1535
+ MethodDescriptor* self = ruby_to_MethodDescriptor(_self);
1536
+ const google_protobuf_MethodOptions* opts =
1537
+ upb_MethodDef_Options(self->methoddef);
1538
+ upb_Arena* arena = upb_Arena_New();
1539
+ size_t size;
1540
+ char* serialized =
1541
+ google_protobuf_MethodOptions_serialize(opts, arena, &size);
1542
+ VALUE method_options = decode_options(_self, "MethodOptions", size,
1543
+ serialized, self->descriptor_pool);
1544
+ upb_Arena_Free(arena);
1545
+ return method_options;
1546
+ }
1547
+
1548
+ /*
1549
+ * call-seq:
1550
+ * MethodDescriptor.input_type => Descriptor
1551
+ *
1552
+ * Returns the `Descriptor` for the request message type of this method
1553
+ */
1554
+ static VALUE MethodDescriptor_input_type(VALUE _self) {
1555
+ MethodDescriptor* self = ruby_to_MethodDescriptor(_self);
1556
+ const upb_MessageDef* type = upb_MethodDef_InputType(self->methoddef);
1557
+ return get_msgdef_obj(self->descriptor_pool, type);
1558
+ }
1559
+
1560
+ /*
1561
+ * call-seq:
1562
+ * MethodDescriptor.output_type => Descriptor
1563
+ *
1564
+ * Returns the `Descriptor` for the response message type of this method
1565
+ */
1566
+ static VALUE MethodDescriptor_output_type(VALUE _self) {
1567
+ MethodDescriptor* self = ruby_to_MethodDescriptor(_self);
1568
+ const upb_MessageDef* type = upb_MethodDef_OutputType(self->methoddef);
1569
+ return get_msgdef_obj(self->descriptor_pool, type);
1570
+ }
1571
+
1572
+ /*
1573
+ * call-seq:
1574
+ * MethodDescriptor.client_streaming => bool
1575
+ *
1576
+ * Returns whether or not this is a streaming request method
1577
+ */
1578
+ static VALUE MethodDescriptor_client_streaming(VALUE _self) {
1579
+ MethodDescriptor* self = ruby_to_MethodDescriptor(_self);
1580
+ return upb_MethodDef_ClientStreaming(self->methoddef) ? Qtrue : Qfalse;
1581
+ }
1582
+
1583
+ /*
1584
+ * call-seq:
1585
+ * MethodDescriptor.server_streaming => bool
1586
+ *
1587
+ * Returns whether or not this is a streaming response method
1588
+ */
1589
+ static VALUE MethodDescriptor_server_streaming(VALUE _self) {
1590
+ MethodDescriptor* self = ruby_to_MethodDescriptor(_self);
1591
+ return upb_MethodDef_ServerStreaming(self->methoddef) ? Qtrue : Qfalse;
1592
+ }
1593
+
1594
+ static void MethodDescriptor_register(VALUE module) {
1595
+ VALUE klass = rb_define_class_under(module, "MethodDescriptor", rb_cObject);
1596
+ rb_define_alloc_func(klass, MethodDescriptor_alloc);
1597
+ rb_define_method(klass, "initialize", MethodDescriptor_initialize, 3);
1598
+ rb_define_method(klass, "name", MethodDescriptor_name, 0);
1599
+ rb_define_method(klass, "options", MethodDescriptor_options, 0);
1600
+ rb_define_method(klass, "input_type", MethodDescriptor_input_type, 0);
1601
+ rb_define_method(klass, "output_type", MethodDescriptor_output_type, 0);
1602
+ rb_define_method(klass, "client_streaming", MethodDescriptor_client_streaming,
1603
+ 0);
1604
+ rb_define_method(klass, "server_streaming", MethodDescriptor_server_streaming,
1605
+ 0);
1606
+ rb_gc_register_address(&cMethodDescriptor);
1607
+ cMethodDescriptor = klass;
1608
+ }
1609
+
1284
1610
  static VALUE get_def_obj(VALUE _descriptor_pool, const void* ptr, VALUE klass) {
1285
1611
  DescriptorPool* descriptor_pool = ruby_to_DescriptorPool(_descriptor_pool);
1286
1612
  VALUE key = ULL2NUM((intptr_t)ptr);
@@ -1322,6 +1648,16 @@ static VALUE get_oneofdef_obj(VALUE descriptor_pool, const upb_OneofDef* def) {
1322
1648
  return get_def_obj(descriptor_pool, def, cOneofDescriptor);
1323
1649
  }
1324
1650
 
1651
+ static VALUE get_servicedef_obj(VALUE descriptor_pool,
1652
+ const upb_ServiceDef* def) {
1653
+ return get_def_obj(descriptor_pool, def, cServiceDescriptor);
1654
+ }
1655
+
1656
+ static VALUE get_methoddef_obj(VALUE descriptor_pool,
1657
+ const upb_MethodDef* def) {
1658
+ return get_def_obj(descriptor_pool, def, cMethodDescriptor);
1659
+ }
1660
+
1325
1661
  // -----------------------------------------------------------------------------
1326
1662
  // Shared functions
1327
1663
  // -----------------------------------------------------------------------------
@@ -1397,6 +1733,8 @@ void Defs_register(VALUE module) {
1397
1733
  FieldDescriptor_register(module);
1398
1734
  OneofDescriptor_register(module);
1399
1735
  EnumDescriptor_register(module);
1736
+ ServiceDescriptor_register(module);
1737
+ MethodDescriptor_register(module);
1400
1738
 
1401
1739
  rb_gc_register_address(&c_only_cookie);
1402
1740
  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
+ }