google-protobuf 3.22.5 → 3.25.5

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/Rakefile +3 -0
  3. data/ext/google/protobuf_c/convert.c +23 -70
  4. data/ext/google/protobuf_c/convert.h +3 -28
  5. data/ext/google/protobuf_c/defs.c +175 -52
  6. data/ext/google/protobuf_c/defs.h +3 -28
  7. data/ext/google/protobuf_c/extconf.rb +2 -1
  8. data/ext/google/protobuf_c/glue.c +56 -0
  9. data/ext/google/protobuf_c/map.c +27 -28
  10. data/ext/google/protobuf_c/map.h +6 -28
  11. data/ext/google/protobuf_c/message.c +83 -83
  12. data/ext/google/protobuf_c/message.h +10 -28
  13. data/ext/google/protobuf_c/protobuf.c +39 -176
  14. data/ext/google/protobuf_c/protobuf.h +24 -32
  15. data/ext/google/protobuf_c/repeated_field.c +28 -29
  16. data/ext/google/protobuf_c/repeated_field.h +6 -28
  17. data/ext/google/protobuf_c/ruby-upb.c +2982 -2494
  18. data/ext/google/protobuf_c/ruby-upb.h +5838 -3467
  19. data/ext/google/protobuf_c/shared_convert.c +64 -0
  20. data/ext/google/protobuf_c/shared_convert.h +26 -0
  21. data/ext/google/protobuf_c/shared_message.c +65 -0
  22. data/ext/google/protobuf_c/shared_message.h +25 -0
  23. data/ext/google/protobuf_c/wrap_memcpy.c +3 -26
  24. data/lib/google/protobuf/any_pb.rb +24 -5
  25. data/lib/google/protobuf/api_pb.rb +26 -23
  26. data/lib/google/protobuf/descriptor_pb.rb +40 -252
  27. data/lib/google/protobuf/duration_pb.rb +24 -5
  28. data/lib/google/protobuf/empty_pb.rb +24 -3
  29. data/lib/google/protobuf/ffi/descriptor.rb +165 -0
  30. data/lib/google/protobuf/ffi/descriptor_pool.rb +75 -0
  31. data/lib/google/protobuf/ffi/enum_descriptor.rb +171 -0
  32. data/lib/google/protobuf/ffi/ffi.rb +213 -0
  33. data/lib/google/protobuf/ffi/field_descriptor.rb +319 -0
  34. data/lib/google/protobuf/ffi/file_descriptor.rb +59 -0
  35. data/lib/google/protobuf/ffi/internal/arena.rb +66 -0
  36. data/lib/google/protobuf/ffi/internal/convert.rb +305 -0
  37. data/lib/google/protobuf/ffi/internal/pointer_helper.rb +35 -0
  38. data/lib/google/protobuf/ffi/internal/type_safety.rb +25 -0
  39. data/lib/google/protobuf/ffi/map.rb +407 -0
  40. data/lib/google/protobuf/ffi/message.rb +662 -0
  41. data/lib/google/protobuf/ffi/object_cache.rb +30 -0
  42. data/lib/google/protobuf/ffi/oneof_descriptor.rb +95 -0
  43. data/lib/google/protobuf/ffi/repeated_field.rb +383 -0
  44. data/lib/google/protobuf/field_mask_pb.rb +24 -4
  45. data/lib/google/protobuf/message_exts.rb +3 -26
  46. data/lib/google/protobuf/object_cache.rb +97 -0
  47. data/lib/google/protobuf/plugin_pb.rb +25 -28
  48. data/lib/google/protobuf/repeated_field.rb +3 -26
  49. data/lib/google/protobuf/source_context_pb.rb +24 -4
  50. data/lib/google/protobuf/struct_pb.rb +24 -20
  51. data/lib/google/protobuf/timestamp_pb.rb +24 -5
  52. data/lib/google/protobuf/type_pb.rb +26 -68
  53. data/lib/google/protobuf/well_known_types.rb +5 -34
  54. data/lib/google/protobuf/wrappers_pb.rb +24 -28
  55. data/lib/google/protobuf.rb +27 -45
  56. data/lib/google/protobuf_ffi.rb +50 -0
  57. data/lib/google/protobuf_native.rb +20 -0
  58. data/lib/google/tasks/ffi.rake +102 -0
  59. metadata +72 -4
@@ -1,32 +1,9 @@
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>
@@ -67,12 +44,14 @@ static VALUE rb_str_maybe_null(const char* s) {
67
44
  }
68
45
  return rb_str_new2(s);
69
46
  }
70
-
47
+ static ID options_instancevar_interned;
71
48
  // -----------------------------------------------------------------------------
72
49
  // DescriptorPool.
73
50
  // -----------------------------------------------------------------------------
74
51
 
75
52
  typedef struct {
53
+ // IMPORTANT: WB_PROTECTED objects must only use the RB_OBJ_WRITE()
54
+ // macro to update VALUE references, as to trigger write barriers.
76
55
  VALUE def_to_descriptor; // Hash table of def* -> Ruby descriptor.
77
56
  upb_DefPool* symtab;
78
57
  } DescriptorPool;
@@ -97,7 +76,7 @@ static void DescriptorPool_free(void* _self) {
97
76
  static const rb_data_type_t DescriptorPool_type = {
98
77
  "Google::Protobuf::DescriptorPool",
99
78
  {DescriptorPool_mark, DescriptorPool_free, NULL},
100
- .flags = RUBY_TYPED_FREE_IMMEDIATELY,
79
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
101
80
  };
102
81
 
103
82
  static DescriptorPool* ruby_to_DescriptorPool(VALUE val) {
@@ -125,11 +104,9 @@ static VALUE DescriptorPool_alloc(VALUE klass) {
125
104
  self->def_to_descriptor = Qnil;
126
105
  ret = TypedData_Wrap_Struct(klass, &DescriptorPool_type, self);
127
106
 
128
- self->def_to_descriptor = rb_hash_new();
107
+ RB_OBJ_WRITE(ret, &self->def_to_descriptor, rb_hash_new());
129
108
  self->symtab = upb_DefPool_New();
130
- ObjectCache_Add(self->symtab, ret);
131
-
132
- return ret;
109
+ return ObjectCache_TryAdd(self->symtab, ret);
133
110
  }
134
111
 
135
112
  /*
@@ -167,20 +144,26 @@ VALUE DescriptorPool_add_serialized_file(VALUE _self,
167
144
  * call-seq:
168
145
  * DescriptorPool.lookup(name) => descriptor
169
146
  *
170
- * Finds a Descriptor or EnumDescriptor by name and returns it, or nil if none
171
- * exists with the given name.
147
+ * Finds a Descriptor, EnumDescriptor or FieldDescriptor by name and returns it,
148
+ * or nil if none exists with the given name.
172
149
  */
173
150
  static VALUE DescriptorPool_lookup(VALUE _self, VALUE name) {
174
151
  DescriptorPool* self = ruby_to_DescriptorPool(_self);
175
152
  const char* name_str = get_str(name);
176
153
  const upb_MessageDef* msgdef;
177
154
  const upb_EnumDef* enumdef;
155
+ const upb_FieldDef* fielddef;
178
156
 
179
157
  msgdef = upb_DefPool_FindMessageByName(self->symtab, name_str);
180
158
  if (msgdef) {
181
159
  return get_msgdef_obj(_self, msgdef);
182
160
  }
183
161
 
162
+ fielddef = upb_DefPool_FindExtensionByName(self->symtab, name_str);
163
+ if (fielddef) {
164
+ return get_fielddef_obj(_self, fielddef);
165
+ }
166
+
184
167
  enumdef = upb_DefPool_FindEnumByName(self->symtab, name_str);
185
168
  if (enumdef) {
186
169
  return get_enumdef_obj(_self, enumdef);
@@ -215,6 +198,7 @@ static void DescriptorPool_register(VALUE module) {
215
198
 
216
199
  rb_gc_register_address(&generated_pool);
217
200
  generated_pool = rb_class_new_instance(0, NULL, klass);
201
+ options_instancevar_interned = rb_intern("options");
218
202
  }
219
203
 
220
204
  // -----------------------------------------------------------------------------
@@ -223,6 +207,8 @@ static void DescriptorPool_register(VALUE module) {
223
207
 
224
208
  typedef struct {
225
209
  const upb_MessageDef* msgdef;
210
+ // IMPORTANT: WB_PROTECTED objects must only use the RB_OBJ_WRITE()
211
+ // macro to update VALUE references, as to trigger write barriers.
226
212
  VALUE klass;
227
213
  VALUE descriptor_pool;
228
214
  } Descriptor;
@@ -238,7 +224,7 @@ static void Descriptor_mark(void* _self) {
238
224
  static const rb_data_type_t Descriptor_type = {
239
225
  "Google::Protobuf::Descriptor",
240
226
  {Descriptor_mark, RUBY_DEFAULT_FREE, NULL},
241
- .flags = RUBY_TYPED_FREE_IMMEDIATELY,
227
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
242
228
  };
243
229
 
244
230
  static Descriptor* ruby_to_Descriptor(VALUE val) {
@@ -247,6 +233,35 @@ static Descriptor* ruby_to_Descriptor(VALUE val) {
247
233
  return ret;
248
234
  }
249
235
 
236
+ // Decode and return a frozen instance of a Descriptor Option for the given pool
237
+ static VALUE decode_options(VALUE self, const char* option_type, int size,
238
+ const char* bytes, VALUE descriptor_pool) {
239
+ VALUE options_rb = rb_ivar_get(self, options_instancevar_interned);
240
+ if (options_rb != Qnil) {
241
+ return options_rb;
242
+ }
243
+
244
+ static const char* prefix = "google.protobuf.";
245
+ char fullname
246
+ [/*strlen(prefix)*/ 16 +
247
+ /*strln(longest option type supported e.g. "MessageOptions")*/ 14 +
248
+ /*null terminator*/ 1];
249
+
250
+ snprintf(fullname, sizeof(fullname), "%s%s", prefix, option_type);
251
+ const upb_MessageDef* msgdef = upb_DefPool_FindMessageByName(
252
+ ruby_to_DescriptorPool(descriptor_pool)->symtab, fullname);
253
+ if (!msgdef) {
254
+ rb_raise(rb_eRuntimeError, "Cannot find %s in DescriptorPool", option_type);
255
+ }
256
+
257
+ VALUE desc_rb = get_msgdef_obj(descriptor_pool, msgdef);
258
+ const Descriptor* desc = ruby_to_Descriptor(desc_rb);
259
+
260
+ options_rb = Message_decode_bytes(size, bytes, 0, desc->klass, true);
261
+ rb_ivar_set(self, options_instancevar_interned, options_rb);
262
+ return options_rb;
263
+ }
264
+
250
265
  /*
251
266
  * call-seq:
252
267
  * Descriptor.new => descriptor
@@ -280,7 +295,7 @@ static VALUE Descriptor_initialize(VALUE _self, VALUE cookie,
280
295
  "Descriptor objects may not be created from Ruby.");
281
296
  }
282
297
 
283
- self->descriptor_pool = descriptor_pool;
298
+ RB_OBJ_WRITE(_self, &self->descriptor_pool, descriptor_pool);
284
299
  self->msgdef = (const upb_MessageDef*)NUM2ULL(ptr);
285
300
 
286
301
  return Qnil;
@@ -390,11 +405,31 @@ static VALUE Descriptor_lookup_oneof(VALUE _self, VALUE name) {
390
405
  static VALUE Descriptor_msgclass(VALUE _self) {
391
406
  Descriptor* self = ruby_to_Descriptor(_self);
392
407
  if (self->klass == Qnil) {
393
- self->klass = build_class_from_descriptor(_self);
408
+ RB_OBJ_WRITE(_self, &self->klass, build_class_from_descriptor(_self));
394
409
  }
395
410
  return self->klass;
396
411
  }
397
412
 
413
+ /*
414
+ * call-seq:
415
+ * Descriptor.options => options
416
+ *
417
+ * Returns the `MessageOptions` for this `Descriptor`.
418
+ */
419
+ static VALUE Descriptor_options(VALUE _self) {
420
+ Descriptor* self = ruby_to_Descriptor(_self);
421
+ const google_protobuf_MessageOptions* opts =
422
+ upb_MessageDef_Options(self->msgdef);
423
+ upb_Arena* arena = upb_Arena_New();
424
+ size_t size;
425
+ char* serialized =
426
+ google_protobuf_MessageOptions_serialize(opts, arena, &size);
427
+ VALUE message_options = decode_options(_self, "MessageOptions", size,
428
+ serialized, self->descriptor_pool);
429
+ upb_Arena_Free(arena);
430
+ return message_options;
431
+ }
432
+
398
433
  static void Descriptor_register(VALUE module) {
399
434
  VALUE klass = rb_define_class_under(module, "Descriptor", rb_cObject);
400
435
  rb_define_alloc_func(klass, Descriptor_alloc);
@@ -406,6 +441,7 @@ static void Descriptor_register(VALUE module) {
406
441
  rb_define_method(klass, "msgclass", Descriptor_msgclass, 0);
407
442
  rb_define_method(klass, "name", Descriptor_name, 0);
408
443
  rb_define_method(klass, "file_descriptor", Descriptor_file_descriptor, 0);
444
+ rb_define_method(klass, "options", Descriptor_options, 0);
409
445
  rb_include_module(klass, rb_mEnumerable);
410
446
  rb_gc_register_address(&cDescriptor);
411
447
  cDescriptor = klass;
@@ -417,6 +453,8 @@ static void Descriptor_register(VALUE module) {
417
453
 
418
454
  typedef struct {
419
455
  const upb_FileDef* filedef;
456
+ // IMPORTANT: WB_PROTECTED objects must only use the RB_OBJ_WRITE()
457
+ // macro to update VALUE references, as to trigger write barriers.
420
458
  VALUE descriptor_pool; // Owns the upb_FileDef.
421
459
  } FileDescriptor;
422
460
 
@@ -430,7 +468,7 @@ static void FileDescriptor_mark(void* _self) {
430
468
  static const rb_data_type_t FileDescriptor_type = {
431
469
  "Google::Protobuf::FileDescriptor",
432
470
  {FileDescriptor_mark, RUBY_DEFAULT_FREE, NULL},
433
- .flags = RUBY_TYPED_FREE_IMMEDIATELY,
471
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
434
472
  };
435
473
 
436
474
  static FileDescriptor* ruby_to_FileDescriptor(VALUE val) {
@@ -463,7 +501,7 @@ static VALUE FileDescriptor_initialize(VALUE _self, VALUE cookie,
463
501
  "Descriptor objects may not be created from Ruby.");
464
502
  }
465
503
 
466
- self->descriptor_pool = descriptor_pool;
504
+ RB_OBJ_WRITE(_self, &self->descriptor_pool, descriptor_pool);
467
505
  self->filedef = (const upb_FileDef*)NUM2ULL(ptr);
468
506
 
469
507
  return Qnil;
@@ -503,12 +541,31 @@ static VALUE FileDescriptor_syntax(VALUE _self) {
503
541
  }
504
542
  }
505
543
 
544
+ /*
545
+ * call-seq:
546
+ * FileDescriptor.options => options
547
+ *
548
+ * Returns the `FileOptions` for this `FileDescriptor`.
549
+ */
550
+ static VALUE FileDescriptor_options(VALUE _self) {
551
+ FileDescriptor* self = ruby_to_FileDescriptor(_self);
552
+ const google_protobuf_FileOptions* opts = upb_FileDef_Options(self->filedef);
553
+ upb_Arena* arena = upb_Arena_New();
554
+ size_t size;
555
+ char* serialized = google_protobuf_FileOptions_serialize(opts, arena, &size);
556
+ VALUE file_options = decode_options(_self, "FileOptions", size, serialized,
557
+ self->descriptor_pool);
558
+ upb_Arena_Free(arena);
559
+ return file_options;
560
+ }
561
+
506
562
  static void FileDescriptor_register(VALUE module) {
507
563
  VALUE klass = rb_define_class_under(module, "FileDescriptor", rb_cObject);
508
564
  rb_define_alloc_func(klass, FileDescriptor_alloc);
509
565
  rb_define_method(klass, "initialize", FileDescriptor_initialize, 3);
510
566
  rb_define_method(klass, "name", FileDescriptor_name, 0);
511
567
  rb_define_method(klass, "syntax", FileDescriptor_syntax, 0);
568
+ rb_define_method(klass, "options", FileDescriptor_options, 0);
512
569
  rb_gc_register_address(&cFileDescriptor);
513
570
  cFileDescriptor = klass;
514
571
  }
@@ -519,6 +576,8 @@ static void FileDescriptor_register(VALUE module) {
519
576
 
520
577
  typedef struct {
521
578
  const upb_FieldDef* fielddef;
579
+ // IMPORTANT: WB_PROTECTED objects must only use the RB_OBJ_WRITE()
580
+ // macro to update VALUE references, as to trigger write barriers.
522
581
  VALUE descriptor_pool; // Owns the upb_FieldDef.
523
582
  } FieldDescriptor;
524
583
 
@@ -532,7 +591,7 @@ static void FieldDescriptor_mark(void* _self) {
532
591
  static const rb_data_type_t FieldDescriptor_type = {
533
592
  "Google::Protobuf::FieldDescriptor",
534
593
  {FieldDescriptor_mark, RUBY_DEFAULT_FREE, NULL},
535
- .flags = RUBY_TYPED_FREE_IMMEDIATELY,
594
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
536
595
  };
537
596
 
538
597
  static FieldDescriptor* ruby_to_FieldDescriptor(VALUE val) {
@@ -557,7 +616,7 @@ static VALUE FieldDescriptor_alloc(VALUE klass) {
557
616
 
558
617
  /*
559
618
  * call-seq:
560
- * EnumDescriptor.new(c_only_cookie, pool, ptr) => EnumDescriptor
619
+ * FieldDescriptor.new(c_only_cookie, pool, ptr) => FieldDescriptor
561
620
  *
562
621
  * Creates a descriptor wrapper object. May only be called from C.
563
622
  */
@@ -570,7 +629,7 @@ static VALUE FieldDescriptor_initialize(VALUE _self, VALUE cookie,
570
629
  "Descriptor objects may not be created from Ruby.");
571
630
  }
572
631
 
573
- self->descriptor_pool = descriptor_pool;
632
+ RB_OBJ_WRITE(_self, &self->descriptor_pool, descriptor_pool);
574
633
  self->fielddef = (const upb_FieldDef*)NUM2ULL(ptr);
575
634
 
576
635
  return Qnil;
@@ -595,7 +654,7 @@ upb_CType ruby_to_fieldtype(VALUE type) {
595
654
 
596
655
  #define CONVERT(upb, ruby) \
597
656
  if (SYM2ID(type) == rb_intern(#ruby)) { \
598
- return kUpb_CType_##upb; \
657
+ return kUpb_CType_##upb; \
599
658
  }
600
659
 
601
660
  CONVERT(Float, float);
@@ -618,7 +677,7 @@ upb_CType ruby_to_fieldtype(VALUE type) {
618
677
 
619
678
  static VALUE descriptortype_to_ruby(upb_FieldType type) {
620
679
  switch (type) {
621
- #define CONVERT(upb, ruby) \
680
+ #define CONVERT(upb, ruby) \
622
681
  case kUpb_FieldType_##upb: \
623
682
  return ID2SYM(rb_intern(#ruby));
624
683
  CONVERT(Float, float);
@@ -703,7 +762,7 @@ static VALUE FieldDescriptor_label(VALUE _self) {
703
762
  FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
704
763
  switch (upb_FieldDef_Label(self->fielddef)) {
705
764
  #define CONVERT(upb, ruby) \
706
- case kUpb_Label_##upb: \
765
+ case kUpb_Label_##upb: \
707
766
  return ID2SYM(rb_intern(#ruby));
708
767
 
709
768
  CONVERT(Optional, optional);
@@ -858,6 +917,25 @@ static VALUE FieldDescriptor_set(VALUE _self, VALUE msg_rb, VALUE value) {
858
917
  return Qnil;
859
918
  }
860
919
 
920
+ /*
921
+ * call-seq:
922
+ * FieldDescriptor.options => options
923
+ *
924
+ * Returns the `FieldOptions` for this `FieldDescriptor`.
925
+ */
926
+ static VALUE FieldDescriptor_options(VALUE _self) {
927
+ FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
928
+ const google_protobuf_FieldOptions* opts =
929
+ upb_FieldDef_Options(self->fielddef);
930
+ upb_Arena* arena = upb_Arena_New();
931
+ size_t size;
932
+ char* serialized = google_protobuf_FieldOptions_serialize(opts, arena, &size);
933
+ VALUE field_options = decode_options(_self, "FieldOptions", size, serialized,
934
+ self->descriptor_pool);
935
+ upb_Arena_Free(arena);
936
+ return field_options;
937
+ }
938
+
861
939
  static void FieldDescriptor_register(VALUE module) {
862
940
  VALUE klass = rb_define_class_under(module, "FieldDescriptor", rb_cObject);
863
941
  rb_define_alloc_func(klass, FieldDescriptor_alloc);
@@ -874,6 +952,7 @@ static void FieldDescriptor_register(VALUE module) {
874
952
  rb_define_method(klass, "clear", FieldDescriptor_clear, 1);
875
953
  rb_define_method(klass, "get", FieldDescriptor_get, 1);
876
954
  rb_define_method(klass, "set", FieldDescriptor_set, 2);
955
+ rb_define_method(klass, "options", FieldDescriptor_options, 0);
877
956
  rb_gc_register_address(&cFieldDescriptor);
878
957
  cFieldDescriptor = klass;
879
958
  }
@@ -884,6 +963,8 @@ static void FieldDescriptor_register(VALUE module) {
884
963
 
885
964
  typedef struct {
886
965
  const upb_OneofDef* oneofdef;
966
+ // IMPORTANT: WB_PROTECTED objects must only use the RB_OBJ_WRITE()
967
+ // macro to update VALUE references, as to trigger write barriers.
887
968
  VALUE descriptor_pool; // Owns the upb_OneofDef.
888
969
  } OneofDescriptor;
889
970
 
@@ -897,7 +978,7 @@ static void OneofDescriptor_mark(void* _self) {
897
978
  static const rb_data_type_t OneofDescriptor_type = {
898
979
  "Google::Protobuf::OneofDescriptor",
899
980
  {OneofDescriptor_mark, RUBY_DEFAULT_FREE, NULL},
900
- .flags = RUBY_TYPED_FREE_IMMEDIATELY,
981
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
901
982
  };
902
983
 
903
984
  static OneofDescriptor* ruby_to_OneofDescriptor(VALUE val) {
@@ -936,7 +1017,7 @@ static VALUE OneofDescriptor_initialize(VALUE _self, VALUE cookie,
936
1017
  "Descriptor objects may not be created from Ruby.");
937
1018
  }
938
1019
 
939
- self->descriptor_pool = descriptor_pool;
1020
+ RB_OBJ_WRITE(_self, &self->descriptor_pool, descriptor_pool);
940
1021
  self->oneofdef = (const upb_OneofDef*)NUM2ULL(ptr);
941
1022
 
942
1023
  return Qnil;
@@ -971,12 +1052,32 @@ static VALUE OneofDescriptor_each(VALUE _self) {
971
1052
  return Qnil;
972
1053
  }
973
1054
 
1055
+ /*
1056
+ * call-seq:
1057
+ * OneofDescriptor.options => options
1058
+ *
1059
+ * Returns the `OneofOptions` for this `OneofDescriptor`.
1060
+ */
1061
+ static VALUE OneOfDescriptor_options(VALUE _self) {
1062
+ OneofDescriptor* self = ruby_to_OneofDescriptor(_self);
1063
+ const google_protobuf_OneofOptions* opts =
1064
+ upb_OneofDef_Options(self->oneofdef);
1065
+ upb_Arena* arena = upb_Arena_New();
1066
+ size_t size;
1067
+ char* serialized = google_protobuf_OneofOptions_serialize(opts, arena, &size);
1068
+ VALUE oneof_options = decode_options(_self, "OneofOptions", size, serialized,
1069
+ self->descriptor_pool);
1070
+ upb_Arena_Free(arena);
1071
+ return oneof_options;
1072
+ }
1073
+
974
1074
  static void OneofDescriptor_register(VALUE module) {
975
1075
  VALUE klass = rb_define_class_under(module, "OneofDescriptor", rb_cObject);
976
1076
  rb_define_alloc_func(klass, OneofDescriptor_alloc);
977
1077
  rb_define_method(klass, "initialize", OneofDescriptor_initialize, 3);
978
1078
  rb_define_method(klass, "name", OneofDescriptor_name, 0);
979
1079
  rb_define_method(klass, "each", OneofDescriptor_each, 0);
1080
+ rb_define_method(klass, "options", OneOfDescriptor_options, 0);
980
1081
  rb_include_module(klass, rb_mEnumerable);
981
1082
  rb_gc_register_address(&cOneofDescriptor);
982
1083
  cOneofDescriptor = klass;
@@ -988,6 +1089,8 @@ static void OneofDescriptor_register(VALUE module) {
988
1089
 
989
1090
  typedef struct {
990
1091
  const upb_EnumDef* enumdef;
1092
+ // IMPORTANT: WB_PROTECTED objects must only use the RB_OBJ_WRITE()
1093
+ // macro to update VALUE references, as to trigger write barriers.
991
1094
  VALUE module; // begins as nil
992
1095
  VALUE descriptor_pool; // Owns the upb_EnumDef.
993
1096
  } EnumDescriptor;
@@ -1003,7 +1106,7 @@ static void EnumDescriptor_mark(void* _self) {
1003
1106
  static const rb_data_type_t EnumDescriptor_type = {
1004
1107
  "Google::Protobuf::EnumDescriptor",
1005
1108
  {EnumDescriptor_mark, RUBY_DEFAULT_FREE, NULL},
1006
- .flags = RUBY_TYPED_FREE_IMMEDIATELY,
1109
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
1007
1110
  };
1008
1111
 
1009
1112
  static EnumDescriptor* ruby_to_EnumDescriptor(VALUE val) {
@@ -1042,7 +1145,7 @@ static VALUE EnumDescriptor_initialize(VALUE _self, VALUE cookie,
1042
1145
  "Descriptor objects may not be created from Ruby.");
1043
1146
  }
1044
1147
 
1045
- self->descriptor_pool = descriptor_pool;
1148
+ RB_OBJ_WRITE(_self, &self->descriptor_pool, descriptor_pool);
1046
1149
  self->enumdef = (const upb_EnumDef*)NUM2ULL(ptr);
1047
1150
 
1048
1151
  return Qnil;
@@ -1081,7 +1184,7 @@ static VALUE EnumDescriptor_name(VALUE _self) {
1081
1184
  static VALUE EnumDescriptor_lookup_name(VALUE _self, VALUE name) {
1082
1185
  EnumDescriptor* self = ruby_to_EnumDescriptor(_self);
1083
1186
  const char* name_str = rb_id2name(SYM2ID(name));
1084
- const upb_EnumValueDef *ev =
1187
+ const upb_EnumValueDef* ev =
1085
1188
  upb_EnumDef_FindValueByName(self->enumdef, name_str);
1086
1189
  if (ev) {
1087
1190
  return INT2NUM(upb_EnumValueDef_Number(ev));
@@ -1100,7 +1203,8 @@ static VALUE EnumDescriptor_lookup_name(VALUE _self, VALUE name) {
1100
1203
  static VALUE EnumDescriptor_lookup_value(VALUE _self, VALUE number) {
1101
1204
  EnumDescriptor* self = ruby_to_EnumDescriptor(_self);
1102
1205
  int32_t val = NUM2INT(number);
1103
- const upb_EnumValueDef* ev = upb_EnumDef_FindValueByNumber(self->enumdef, val);
1206
+ const upb_EnumValueDef* ev =
1207
+ upb_EnumDef_FindValueByNumber(self->enumdef, val);
1104
1208
  if (ev) {
1105
1209
  return ID2SYM(rb_intern(upb_EnumValueDef_Name(ev)));
1106
1210
  } else {
@@ -1138,11 +1242,29 @@ static VALUE EnumDescriptor_each(VALUE _self) {
1138
1242
  static VALUE EnumDescriptor_enummodule(VALUE _self) {
1139
1243
  EnumDescriptor* self = ruby_to_EnumDescriptor(_self);
1140
1244
  if (self->module == Qnil) {
1141
- self->module = build_module_from_enumdesc(_self);
1245
+ RB_OBJ_WRITE(_self, &self->module, build_module_from_enumdesc(_self));
1142
1246
  }
1143
1247
  return self->module;
1144
1248
  }
1145
1249
 
1250
+ /*
1251
+ * call-seq:
1252
+ * EnumDescriptor.options => options
1253
+ *
1254
+ * Returns the `EnumOptions` for this `EnumDescriptor`.
1255
+ */
1256
+ static VALUE EnumDescriptor_options(VALUE _self) {
1257
+ EnumDescriptor* self = ruby_to_EnumDescriptor(_self);
1258
+ const google_protobuf_EnumOptions* opts = upb_EnumDef_Options(self->enumdef);
1259
+ upb_Arena* arena = upb_Arena_New();
1260
+ size_t size;
1261
+ char* serialized = google_protobuf_EnumOptions_serialize(opts, arena, &size);
1262
+ VALUE enum_options = decode_options(_self, "EnumOptions", size, serialized,
1263
+ self->descriptor_pool);
1264
+ upb_Arena_Free(arena);
1265
+ return enum_options;
1266
+ }
1267
+
1146
1268
  static void EnumDescriptor_register(VALUE module) {
1147
1269
  VALUE klass = rb_define_class_under(module, "EnumDescriptor", rb_cObject);
1148
1270
  rb_define_alloc_func(klass, EnumDescriptor_alloc);
@@ -1153,6 +1275,7 @@ static void EnumDescriptor_register(VALUE module) {
1153
1275
  rb_define_method(klass, "each", EnumDescriptor_each, 0);
1154
1276
  rb_define_method(klass, "enummodule", EnumDescriptor_enummodule, 0);
1155
1277
  rb_define_method(klass, "file_descriptor", EnumDescriptor_file_descriptor, 0);
1278
+ rb_define_method(klass, "options", EnumDescriptor_options, 0);
1156
1279
  rb_include_module(klass, rb_mEnumerable);
1157
1280
  rb_gc_register_address(&cEnumDescriptor);
1158
1281
  cEnumDescriptor = klass;
@@ -1,38 +1,13 @@
1
1
  // Protocol Buffers - Google's data interchange format
2
2
  // Copyright 2008 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
  #ifndef RUBY_PROTOBUF_DEFS_H_
32
9
  #define RUBY_PROTOBUF_DEFS_H_
33
10
 
34
- #include <ruby/ruby.h>
35
-
36
11
  #include "protobuf.h"
37
12
  #include "ruby-upb.h"
38
13
 
@@ -22,6 +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"]
25
+ "naive.c", "range2-neon.c", "range2-sse.c", "shared_convert.c",
26
+ "shared_message.c"]
26
27
 
27
28
  create_makefile(ext_name)
@@ -0,0 +1,56 @@
1
+ // Protocol Buffers - Google's data interchange format
2
+ // Copyright 2023 Google Inc. All rights reserved.
3
+ //
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
7
+
8
+ // -----------------------------------------------------------------------------
9
+ // Exposing inlined UPB functions. Strictly free of dependencies on
10
+ // Ruby interpreter internals.
11
+
12
+ #include "ruby-upb.h"
13
+
14
+ upb_Arena* Arena_create() { return upb_Arena_Init(NULL, 0, &upb_alloc_global); }
15
+
16
+ google_protobuf_FileDescriptorProto* FileDescriptorProto_parse(
17
+ const char* serialized_file_proto, size_t length, upb_Arena* arena) {
18
+ return google_protobuf_FileDescriptorProto_parse(serialized_file_proto,
19
+ length, arena);
20
+ }
21
+
22
+ char* EnumDescriptor_serialized_options(const upb_EnumDef* enumdef,
23
+ size_t* size, upb_Arena* arena) {
24
+ const google_protobuf_EnumOptions* opts = upb_EnumDef_Options(enumdef);
25
+ char* serialized = google_protobuf_EnumOptions_serialize(opts, arena, size);
26
+ return serialized;
27
+ }
28
+
29
+ char* FileDescriptor_serialized_options(const upb_FileDef* filedef,
30
+ size_t* size, upb_Arena* arena) {
31
+ const google_protobuf_FileOptions* opts = upb_FileDef_Options(filedef);
32
+ char* serialized = google_protobuf_FileOptions_serialize(opts, arena, size);
33
+ return serialized;
34
+ }
35
+
36
+ char* Descriptor_serialized_options(const upb_MessageDef* msgdef, size_t* size,
37
+ upb_Arena* arena) {
38
+ const google_protobuf_MessageOptions* opts = upb_MessageDef_Options(msgdef);
39
+ char* serialized =
40
+ google_protobuf_MessageOptions_serialize(opts, arena, size);
41
+ return serialized;
42
+ }
43
+
44
+ char* OneOfDescriptor_serialized_options(const upb_OneofDef* oneofdef,
45
+ size_t* size, upb_Arena* arena) {
46
+ const google_protobuf_OneofOptions* opts = upb_OneofDef_Options(oneofdef);
47
+ char* serialized = google_protobuf_OneofOptions_serialize(opts, arena, size);
48
+ return serialized;
49
+ }
50
+
51
+ char* FieldDescriptor_serialized_options(const upb_FieldDef* fielddef,
52
+ size_t* size, upb_Arena* arena) {
53
+ const google_protobuf_FieldOptions* opts = upb_FieldDef_Options(fielddef);
54
+ char* serialized = google_protobuf_FieldOptions_serialize(opts, arena, size);
55
+ return serialized;
56
+ }