google-protobuf 3.21.6 → 3.25.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) 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 +178 -55
  6. data/ext/google/protobuf_c/defs.h +3 -28
  7. data/ext/google/protobuf_c/extconf.rb +4 -4
  8. data/ext/google/protobuf_c/glue.c +56 -0
  9. data/ext/google/protobuf_c/map.c +54 -70
  10. data/ext/google/protobuf_c/map.h +6 -28
  11. data/ext/google/protobuf_c/message.c +186 -162
  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 +12326 -9027
  18. data/ext/google/protobuf_c/ruby-upb.h +11950 -4518
  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/third_party/utf8_range/LICENSE +1 -0
  24. data/ext/google/protobuf_c/third_party/utf8_range/naive.c +0 -0
  25. data/ext/google/protobuf_c/third_party/utf8_range/range2-neon.c +1 -1
  26. data/ext/google/protobuf_c/third_party/utf8_range/range2-sse.c +0 -0
  27. data/ext/google/protobuf_c/third_party/utf8_range/utf8_range.h +13 -1
  28. data/ext/google/protobuf_c/wrap_memcpy.c +3 -26
  29. data/lib/google/protobuf/any_pb.rb +24 -5
  30. data/lib/google/protobuf/api_pb.rb +26 -23
  31. data/lib/google/protobuf/descriptor_dsl.rb +0 -0
  32. data/lib/google/protobuf/descriptor_pb.rb +43 -226
  33. data/lib/google/protobuf/duration_pb.rb +24 -5
  34. data/lib/google/protobuf/empty_pb.rb +24 -3
  35. data/lib/google/protobuf/ffi/descriptor.rb +165 -0
  36. data/lib/google/protobuf/ffi/descriptor_pool.rb +75 -0
  37. data/lib/google/protobuf/ffi/enum_descriptor.rb +171 -0
  38. data/lib/google/protobuf/ffi/ffi.rb +213 -0
  39. data/lib/google/protobuf/ffi/field_descriptor.rb +319 -0
  40. data/lib/google/protobuf/ffi/file_descriptor.rb +59 -0
  41. data/lib/google/protobuf/ffi/internal/arena.rb +66 -0
  42. data/lib/google/protobuf/ffi/internal/convert.rb +305 -0
  43. data/lib/google/protobuf/ffi/internal/pointer_helper.rb +35 -0
  44. data/lib/google/protobuf/ffi/internal/type_safety.rb +25 -0
  45. data/lib/google/protobuf/ffi/map.rb +407 -0
  46. data/lib/google/protobuf/ffi/message.rb +662 -0
  47. data/lib/google/protobuf/ffi/object_cache.rb +30 -0
  48. data/lib/google/protobuf/ffi/oneof_descriptor.rb +95 -0
  49. data/lib/google/protobuf/ffi/repeated_field.rb +383 -0
  50. data/lib/google/protobuf/field_mask_pb.rb +24 -4
  51. data/lib/google/protobuf/message_exts.rb +8 -26
  52. data/lib/google/protobuf/object_cache.rb +97 -0
  53. data/lib/google/protobuf/plugin_pb.rb +47 -0
  54. data/lib/google/protobuf/repeated_field.rb +3 -26
  55. data/lib/google/protobuf/source_context_pb.rb +24 -4
  56. data/lib/google/protobuf/struct_pb.rb +24 -20
  57. data/lib/google/protobuf/timestamp_pb.rb +24 -5
  58. data/lib/google/protobuf/type_pb.rb +26 -68
  59. data/lib/google/protobuf/well_known_types.rb +5 -34
  60. data/lib/google/protobuf/wrappers_pb.rb +24 -28
  61. data/lib/google/protobuf.rb +27 -45
  62. data/lib/google/protobuf_ffi.rb +50 -0
  63. data/lib/google/protobuf_native.rb +20 -0
  64. data/lib/google/tasks/ffi.rake +102 -0
  65. metadata +75 -12
  66. data/tests/basic.rb +0 -739
  67. data/tests/generated_code_test.rb +0 -23
  68. data/tests/stress.rb +0 -38
@@ -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);
@@ -811,7 +870,7 @@ static VALUE FieldDescriptor_has(VALUE _self, VALUE msg_rb) {
811
870
  rb_raise(rb_eArgError, "does not track presence");
812
871
  }
813
872
 
814
- return upb_Message_Has(msg, self->fielddef) ? Qtrue : Qfalse;
873
+ return upb_Message_HasFieldByDef(msg, self->fielddef) ? Qtrue : Qfalse;
815
874
  }
816
875
 
817
876
  /*
@@ -829,7 +888,7 @@ static VALUE FieldDescriptor_clear(VALUE _self, VALUE msg_rb) {
829
888
  rb_raise(cTypeError, "has method called on wrong message type");
830
889
  }
831
890
 
832
- upb_Message_ClearField(msg, self->fielddef);
891
+ upb_Message_ClearFieldByDef(msg, self->fielddef);
833
892
  return Qnil;
834
893
  }
835
894
 
@@ -854,10 +913,29 @@ static VALUE FieldDescriptor_set(VALUE _self, VALUE msg_rb, VALUE value) {
854
913
 
855
914
  msgval = Convert_RubyToUpb(value, upb_FieldDef_Name(self->fielddef),
856
915
  TypeInfo_get(self->fielddef), arena);
857
- upb_Message_Set(msg, self->fielddef, msgval, arena);
916
+ upb_Message_SetFieldByDef(msg, self->fielddef, msgval, arena);
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
 
@@ -6,23 +6,23 @@ ext_name = "google/protobuf_c"
6
6
 
7
7
  dir_config(ext_name)
8
8
 
9
- if RUBY_PLATFORM =~ /darwin/ || RUBY_PLATFORM =~ /linux/
9
+ if RUBY_PLATFORM =~ /darwin/ || RUBY_PLATFORM =~ /linux/ || RUBY_PLATFORM =~ /freebsd/
10
10
  $CFLAGS += " -std=gnu99 -O3 -DNDEBUG -fvisibility=hidden -Wall -Wsign-compare -Wno-declaration-after-statement"
11
11
  else
12
12
  $CFLAGS += " -std=gnu99 -O3 -DNDEBUG"
13
13
  end
14
14
 
15
-
16
15
  if RUBY_PLATFORM =~ /linux/
17
16
  # Instruct the linker to point memcpy calls at our __wrap_memcpy wrapper.
18
17
  $LDFLAGS += " -Wl,-wrap,memcpy"
19
18
  end
20
19
 
21
20
  $VPATH << "$(srcdir)/third_party/utf8_range"
22
- $INCFLAGS << "$(srcdir)/third_party/utf8_range"
21
+ $INCFLAGS += " -I$(srcdir)/third_party/utf8_range"
23
22
 
24
23
  $srcs = ["protobuf.c", "convert.c", "defs.c", "message.c",
25
24
  "repeated_field.c", "map.c", "ruby-upb.c", "wrap_memcpy.c",
26
- "naive.c", "range2-neon.c", "range2-sse.c"]
25
+ "naive.c", "range2-neon.c", "range2-sse.c", "shared_convert.c",
26
+ "shared_message.c"]
27
27
 
28
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
+ }