google-protobuf 3.25.3 → 4.32.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/ext/google/protobuf_c/convert.c +39 -18
  3. data/ext/google/protobuf_c/defs.c +805 -128
  4. data/ext/google/protobuf_c/extconf.rb +20 -10
  5. data/ext/google/protobuf_c/glue.c +79 -0
  6. data/ext/google/protobuf_c/map.c +147 -65
  7. data/ext/google/protobuf_c/map.h +7 -3
  8. data/ext/google/protobuf_c/message.c +210 -174
  9. data/ext/google/protobuf_c/message.h +2 -6
  10. data/ext/google/protobuf_c/protobuf.c +33 -19
  11. data/ext/google/protobuf_c/protobuf.h +3 -15
  12. data/ext/google/protobuf_c/repeated_field.c +130 -58
  13. data/ext/google/protobuf_c/repeated_field.h +6 -2
  14. data/ext/google/protobuf_c/ruby-upb.c +10326 -7740
  15. data/ext/google/protobuf_c/ruby-upb.h +9952 -6435
  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 +207 -0
  21. data/ext/google/protobuf_c/third_party/utf8_range/utf8_range.h +9 -8
  22. data/ext/google/protobuf_c/third_party/utf8_range/utf8_range_neon.inc +117 -0
  23. data/ext/google/protobuf_c/third_party/utf8_range/utf8_range_sse.inc +272 -0
  24. data/lib/google/protobuf/any_pb.rb +2 -23
  25. data/lib/google/protobuf/api_pb.rb +3 -26
  26. data/lib/google/protobuf/descriptor_pb.rb +8 -24
  27. data/lib/google/protobuf/duration_pb.rb +2 -23
  28. data/lib/google/protobuf/empty_pb.rb +2 -23
  29. data/lib/google/protobuf/ffi/descriptor.rb +14 -4
  30. data/lib/google/protobuf/ffi/descriptor_pool.rb +5 -1
  31. data/lib/google/protobuf/ffi/enum_descriptor.rb +13 -1
  32. data/lib/google/protobuf/ffi/ffi.rb +7 -6
  33. data/lib/google/protobuf/ffi/field_descriptor.rb +29 -2
  34. data/lib/google/protobuf/ffi/file_descriptor.rb +39 -13
  35. data/lib/google/protobuf/ffi/internal/arena.rb +0 -6
  36. data/lib/google/protobuf/ffi/internal/convert.rb +17 -30
  37. data/lib/google/protobuf/ffi/internal/pointer_helper.rb +2 -1
  38. data/lib/google/protobuf/ffi/map.rb +52 -26
  39. data/lib/google/protobuf/ffi/message.rb +188 -67
  40. data/lib/google/protobuf/ffi/method_descriptor.rb +124 -0
  41. data/lib/google/protobuf/ffi/object_cache.rb +3 -3
  42. data/lib/google/protobuf/ffi/oneof_descriptor.rb +13 -1
  43. data/lib/google/protobuf/ffi/repeated_field.rb +47 -19
  44. data/lib/google/protobuf/ffi/service_descriptor.rb +117 -0
  45. data/lib/google/protobuf/field_mask_pb.rb +2 -23
  46. data/lib/google/protobuf/internal/object_cache.rb +99 -0
  47. data/lib/google/protobuf/message_exts.rb +4 -0
  48. data/lib/google/protobuf/plugin_pb.rb +3 -25
  49. data/lib/google/protobuf/repeated_field.rb +4 -5
  50. data/lib/google/protobuf/source_context_pb.rb +2 -23
  51. data/lib/google/protobuf/struct_pb.rb +2 -23
  52. data/lib/google/protobuf/timestamp_pb.rb +2 -23
  53. data/lib/google/protobuf/type_pb.rb +2 -25
  54. data/lib/google/protobuf/wrappers_pb.rb +2 -23
  55. data/lib/google/protobuf.rb +1 -1
  56. data/lib/google/protobuf_ffi.rb +6 -4
  57. data/lib/google/protobuf_native.rb +0 -1
  58. data/lib/google/tasks/ffi.rake +2 -4
  59. metadata +36 -22
  60. data/ext/google/protobuf_c/third_party/utf8_range/naive.c +0 -92
  61. data/ext/google/protobuf_c/third_party/utf8_range/range2-neon.c +0 -157
  62. data/ext/google/protobuf_c/third_party/utf8_range/range2-sse.c +0 -170
  63. data/ext/google/protobuf_c/wrap_memcpy.c +0 -29
  64. data/lib/google/protobuf/descriptor_dsl.rb +0 -465
  65. data/lib/google/protobuf/object_cache.rb +0 -97
@@ -44,9 +44,11 @@ static void Message_mark(void* _self) {
44
44
  rb_gc_mark(self->arena);
45
45
  }
46
46
 
47
+ static size_t Message_memsize(const void* _self) { return sizeof(Message); }
48
+
47
49
  static rb_data_type_t Message_type = {
48
50
  "Google::Protobuf::Message",
49
- {Message_mark, RUBY_DEFAULT_FREE, NULL},
51
+ {Message_mark, RUBY_DEFAULT_FREE, Message_memsize},
50
52
  .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
51
53
  };
52
54
 
@@ -78,11 +80,13 @@ const upb_Message* Message_Get(VALUE msg_rb, const upb_MessageDef** m) {
78
80
  }
79
81
 
80
82
  upb_Message* Message_GetMutable(VALUE msg_rb, const upb_MessageDef** m) {
81
- rb_check_frozen(msg_rb);
82
- return (upb_Message*)Message_Get(msg_rb, m);
83
+ const upb_Message* upb_msg = Message_Get(msg_rb, m);
84
+ Protobuf_CheckNotFrozen(msg_rb, upb_Message_IsFrozen(upb_msg));
85
+ return (upb_Message*)upb_msg;
83
86
  }
84
87
 
85
- void Message_InitPtr(VALUE self_, upb_Message* msg, VALUE arena) {
88
+ void Message_InitPtr(VALUE self_, const upb_Message* msg, VALUE arena) {
89
+ PBRUBY_ASSERT(arena != Qnil);
86
90
  Message* self = ruby_to_Message(self_);
87
91
  self->msg = msg;
88
92
  RB_OBJ_WRITE(self_, &self->arena, arena);
@@ -103,7 +107,7 @@ void Message_CheckClass(VALUE klass) {
103
107
  }
104
108
  }
105
109
 
106
- VALUE Message_GetRubyWrapper(upb_Message* msg, const upb_MessageDef* m,
110
+ VALUE Message_GetRubyWrapper(const upb_Message* msg, const upb_MessageDef* m,
107
111
  VALUE arena) {
108
112
  if (msg == NULL) return Qnil;
109
113
 
@@ -114,7 +118,6 @@ VALUE Message_GetRubyWrapper(upb_Message* msg, const upb_MessageDef* m,
114
118
  val = Message_alloc(klass);
115
119
  Message_InitPtr(val, msg, arena);
116
120
  }
117
-
118
121
  return val;
119
122
  }
120
123
 
@@ -246,7 +249,7 @@ static int extract_method_call(VALUE method_name, Message* self,
246
249
  static VALUE Message_oneof_accessor(VALUE _self, const upb_OneofDef* o,
247
250
  int accessor_type) {
248
251
  Message* self = ruby_to_Message(_self);
249
- const upb_FieldDef* oneof_field = upb_Message_WhichOneof(self->msg, o);
252
+ const upb_FieldDef* oneof_field = upb_Message_WhichOneofByDef(self->msg, o);
250
253
 
251
254
  switch (accessor_type) {
252
255
  case METHOD_PRESENCE:
@@ -286,13 +289,42 @@ static void Message_setfield(upb_Message* msg, const upb_FieldDef* f, VALUE val,
286
289
  upb_Message_SetFieldByDef(msg, f, msgval, arena);
287
290
  }
288
291
 
292
+ VALUE Message_getfield_frozen(const upb_Message* msg, const upb_FieldDef* f,
293
+ VALUE arena) {
294
+ upb_MessageValue msgval = upb_Message_GetFieldByDef(msg, f);
295
+ if (upb_FieldDef_IsMap(f)) {
296
+ if (msgval.map_val == NULL) {
297
+ return Map_EmptyFrozen(f);
298
+ }
299
+ const upb_FieldDef* key_f = map_field_key(f);
300
+ const upb_FieldDef* val_f = map_field_value(f);
301
+ upb_CType key_type = upb_FieldDef_CType(key_f);
302
+ TypeInfo value_type_info = TypeInfo_get(val_f);
303
+ return Map_GetRubyWrapper(msgval.map_val, key_type, value_type_info, arena);
304
+ }
305
+ if (upb_FieldDef_IsRepeated(f)) {
306
+ if (msgval.array_val == NULL) {
307
+ return RepeatedField_EmptyFrozen(f);
308
+ }
309
+ return RepeatedField_GetRubyWrapper(msgval.array_val, TypeInfo_get(f),
310
+ arena);
311
+ }
312
+ VALUE ret;
313
+ if (upb_FieldDef_IsSubMessage(f)) {
314
+ const upb_MessageDef* m = upb_FieldDef_MessageSubDef(f);
315
+ ret = Message_GetRubyWrapper(msgval.msg_val, m, arena);
316
+ } else {
317
+ ret = Convert_UpbToRuby(msgval, TypeInfo_get(f), Qnil);
318
+ }
319
+ return ret;
320
+ }
321
+
289
322
  VALUE Message_getfield(VALUE _self, const upb_FieldDef* f) {
290
323
  Message* self = ruby_to_Message(_self);
291
- // This is a special-case: upb_Message_Mutable() for map & array are logically
292
- // const (they will not change what is serialized) but physically
293
- // non-const, as they do allocate a repeated field or map. The logical
294
- // constness means it's ok to do even if the message is frozen.
295
- upb_Message* msg = (upb_Message*)self->msg;
324
+ if (upb_Message_IsFrozen(self->msg)) {
325
+ return Message_getfield_frozen(self->msg, f, self->arena);
326
+ }
327
+ upb_Message* msg = Message_GetMutable(_self, NULL);
296
328
  upb_Arena* arena = Arena_get(self->arena);
297
329
  if (upb_FieldDef_IsMap(f)) {
298
330
  upb_Map* map = upb_Message_Mutable(msg, f, arena).map;
@@ -305,12 +337,12 @@ VALUE Message_getfield(VALUE _self, const upb_FieldDef* f) {
305
337
  upb_Array* arr = upb_Message_Mutable(msg, f, arena).array;
306
338
  return RepeatedField_GetRubyWrapper(arr, TypeInfo_get(f), self->arena);
307
339
  } else if (upb_FieldDef_IsSubMessage(f)) {
308
- if (!upb_Message_HasFieldByDef(self->msg, f)) return Qnil;
340
+ if (!upb_Message_HasFieldByDef(msg, f)) return Qnil;
309
341
  upb_Message* submsg = upb_Message_Mutable(msg, f, arena).msg;
310
342
  const upb_MessageDef* m = upb_FieldDef_MessageSubDef(f);
311
343
  return Message_GetRubyWrapper(submsg, m, self->arena);
312
344
  } else {
313
- upb_MessageValue msgval = upb_Message_GetFieldByDef(self->msg, f);
345
+ upb_MessageValue msgval = upb_Message_GetFieldByDef(msg, f);
314
346
  return Convert_UpbToRuby(msgval, TypeInfo_get(f), self->arena);
315
347
  }
316
348
  }
@@ -330,7 +362,8 @@ static VALUE Message_field_accessor(VALUE _self, const upb_FieldDef* f,
330
362
  if (!upb_FieldDef_HasPresence(f)) {
331
363
  rb_raise(rb_eRuntimeError, "Field does not have presence.");
332
364
  }
333
- return upb_Message_HasFieldByDef(Message_Get(_self, NULL), f);
365
+ return upb_Message_HasFieldByDef(Message_Get(_self, NULL), f) ? Qtrue
366
+ : Qfalse;
334
367
  case METHOD_WRAPPER_GETTER: {
335
368
  Message* self = ruby_to_Message(_self);
336
369
  if (upb_Message_HasFieldByDef(self->msg, f)) {
@@ -365,7 +398,7 @@ static VALUE Message_field_accessor(VALUE _self, const upb_FieldDef* f,
365
398
  upb_MessageValue msgval =
366
399
  upb_Message_GetFieldByDef(Message_Get(_self, NULL), f);
367
400
 
368
- if (upb_FieldDef_Label(f) == kUpb_Label_Repeated) {
401
+ if (upb_FieldDef_IsRepeated(f)) {
369
402
  // Map repeated fields to a new type with ints
370
403
  VALUE arr = rb_ary_new();
371
404
  size_t i, n = upb_Array_Size(msgval.array_val);
@@ -387,11 +420,10 @@ static VALUE Message_field_accessor(VALUE _self, const upb_FieldDef* f,
387
420
  }
388
421
 
389
422
  /*
390
- * call-seq:
391
- * Message.method_missing(*args)
423
+ * ruby-doc: AbstractMessage
392
424
  *
393
- * Provides accessors and setters and methods to clear and check for presence of
394
- * message fields according to their field names.
425
+ * The {AbstractMessage} class is the parent class for all Protobuf messages,
426
+ * and is generated from C code.
395
427
  *
396
428
  * For any field whose name does not conflict with a built-in method, an
397
429
  * accessor is provided with the same name as the field, and a setter is
@@ -434,7 +466,6 @@ static VALUE Message_method_missing(int argc, VALUE* argv, VALUE _self) {
434
466
  if (argc != 2) {
435
467
  rb_raise(rb_eArgError, "Expected 2 arguments, received %d", argc);
436
468
  }
437
- rb_check_frozen(_self);
438
469
  break;
439
470
  default:
440
471
  if (argc != 1) {
@@ -488,7 +519,8 @@ static int Map_initialize_kwarg(VALUE key, VALUE val, VALUE _self) {
488
519
  k = Convert_RubyToUpb(key, "", map_init->key_type, NULL);
489
520
 
490
521
  if (map_init->val_type.type == kUpb_CType_Message && TYPE(val) == T_HASH) {
491
- upb_MiniTable* t = upb_MessageDef_MiniTable(map_init->val_type.def.msgdef);
522
+ const upb_MiniTable* t =
523
+ upb_MessageDef_MiniTable(map_init->val_type.def.msgdef);
492
524
  upb_Message* msg = upb_Message_New(t, map_init->arena);
493
525
  Message_InitFromValue(msg, map_init->val_type.def.msgdef, val,
494
526
  map_init->arena);
@@ -519,7 +551,7 @@ static upb_MessageValue MessageValue_FromValue(VALUE val, TypeInfo info,
519
551
  upb_Arena* arena) {
520
552
  if (info.type == kUpb_CType_Message) {
521
553
  upb_MessageValue msgval;
522
- upb_MiniTable* t = upb_MessageDef_MiniTable(info.def.msgdef);
554
+ const upb_MiniTable* t = upb_MessageDef_MiniTable(info.def.msgdef);
523
555
  upb_Message* msg = upb_Message_New(t, arena);
524
556
  Message_InitFromValue(msg, info.def.msgdef, val, arena);
525
557
  msgval.msg_val = msg;
@@ -559,7 +591,7 @@ static void Message_InitFieldFromValue(upb_Message* msg, const upb_FieldDef* f,
559
591
  if (upb_FieldDef_IsMap(f)) {
560
592
  upb_Map* map = upb_Message_Mutable(msg, f, arena).map;
561
593
  Map_InitFromValue(map, f, val, arena);
562
- } else if (upb_FieldDef_Label(f) == kUpb_Label_Repeated) {
594
+ } else if (upb_FieldDef_IsRepeated(f)) {
563
595
  upb_Array* arr = upb_Message_Mutable(msg, f, arena).array;
564
596
  RepeatedField_InitFromValue(arr, f, val, arena);
565
597
  } else if (upb_FieldDef_IsSubMessage(f)) {
@@ -620,22 +652,18 @@ void Message_InitFromValue(upb_Message* msg, const upb_MessageDef* m, VALUE val,
620
652
  }
621
653
 
622
654
  /*
623
- * call-seq:
624
- * Message.new(kwargs) => new_message
655
+ * ruby-doc: AbstractMessage#initialize
625
656
  *
626
657
  * Creates a new instance of the given message class. Keyword arguments may be
627
658
  * provided with keywords corresponding to field names.
628
659
  *
629
- * Note that no literal Message class exists. Only concrete classes per message
630
- * type exist, as provided by the #msgclass method on Descriptors after they
631
- * have been added to a pool. The method definitions described here on the
632
- * Message class are provided on each concrete message class.
660
+ * @param kwargs the list of field keys and values.
633
661
  */
634
662
  static VALUE Message_initialize(int argc, VALUE* argv, VALUE _self) {
635
663
  Message* self = ruby_to_Message(_self);
636
664
  VALUE arena_rb = Arena_new();
637
665
  upb_Arena* arena = Arena_get(arena_rb);
638
- upb_MiniTable* t = upb_MessageDef_MiniTable(self->msgdef);
666
+ const upb_MiniTable* t = upb_MessageDef_MiniTable(self->msgdef);
639
667
  upb_Message* msg = upb_Message_New(t, arena);
640
668
 
641
669
  Message_InitPtr(_self, msg, arena_rb);
@@ -651,45 +679,32 @@ static VALUE Message_initialize(int argc, VALUE* argv, VALUE _self) {
651
679
  }
652
680
 
653
681
  /*
654
- * call-seq:
655
- * Message.dup => new_message
682
+ * ruby-doc: AbstractMessage#dup
656
683
  *
657
684
  * Performs a shallow copy of this message and returns the new copy.
685
+ *
686
+ * @return [AbstractMessage]
658
687
  */
659
688
  static VALUE Message_dup(VALUE _self) {
660
689
  Message* self = ruby_to_Message(_self);
661
690
  VALUE new_msg = rb_class_new_instance(0, NULL, CLASS_OF(_self));
662
691
  Message* new_msg_self = ruby_to_Message(new_msg);
663
- size_t size = upb_MessageDef_MiniTable(self->msgdef)->size;
664
-
665
- // TODO
666
- // TODO
667
- memcpy((upb_Message*)new_msg_self->msg, self->msg, size);
692
+ const upb_MiniTable* m = upb_MessageDef_MiniTable(self->msgdef);
693
+ upb_Message_ShallowCopy((upb_Message*)new_msg_self->msg, self->msg, m);
668
694
  Arena_fuse(self->arena, Arena_get(new_msg_self->arena));
669
695
  return new_msg;
670
696
  }
671
697
 
672
- // Support function for Message_eq, and also used by other #eq functions.
673
- bool Message_Equal(const upb_Message* m1, const upb_Message* m2,
674
- const upb_MessageDef* m) {
675
- upb_Status status;
676
- upb_Status_Clear(&status);
677
- bool return_value = shared_Message_Equal(m1, m2, m, &status);
678
- if (upb_Status_IsOk(&status)) {
679
- return return_value;
680
- } else {
681
- rb_raise(cParseError, upb_Status_ErrorMessage(&status));
682
- }
683
- }
684
-
685
698
  /*
686
- * call-seq:
687
- * Message.==(other) => boolean
699
+ * ruby-doc: AbstractMessage#==
688
700
  *
689
701
  * Performs a deep comparison of this message with another. Messages are equal
690
702
  * if they have the same type and if each field is equal according to the :==
691
703
  * method's semantics (a more efficient comparison may actually be done if the
692
704
  * field is of a primitive type).
705
+ *
706
+ * @param other [AbstractMessage]
707
+ * @return [Boolean]
693
708
  */
694
709
  static VALUE Message_eq(VALUE _self, VALUE _other) {
695
710
  if (CLASS_OF(_self) != CLASS_OF(_other)) return Qfalse;
@@ -698,7 +713,10 @@ static VALUE Message_eq(VALUE _self, VALUE _other) {
698
713
  Message* other = ruby_to_Message(_other);
699
714
  assert(self->msgdef == other->msgdef);
700
715
 
701
- return Message_Equal(self->msg, other->msg, self->msgdef) ? Qtrue : Qfalse;
716
+ const upb_MiniTable* m = upb_MessageDef_MiniTable(self->msgdef);
717
+ const int options = 0;
718
+ return upb_Message_IsEqual(self->msg, other->msg, m, options) ? Qtrue
719
+ : Qfalse;
702
720
  }
703
721
 
704
722
  uint64_t Message_Hash(const upb_Message* msg, const upb_MessageDef* m,
@@ -709,15 +727,17 @@ uint64_t Message_Hash(const upb_Message* msg, const upb_MessageDef* m,
709
727
  if (upb_Status_IsOk(&status)) {
710
728
  return return_value;
711
729
  } else {
712
- rb_raise(cParseError, upb_Status_ErrorMessage(&status));
730
+ rb_raise(cParseError, "Message_Hash(): %s",
731
+ upb_Status_ErrorMessage(&status));
713
732
  }
714
733
  }
715
734
 
716
735
  /*
717
- * call-seq:
718
- * Message.hash => hash_value
736
+ * ruby-doc: AbstractMessage#hash
719
737
  *
720
738
  * Returns a hash value that represents this message's field values.
739
+ *
740
+ * @return [Integer]
721
741
  */
722
742
  static VALUE Message_hash(VALUE _self) {
723
743
  Message* self = ruby_to_Message(_self);
@@ -728,12 +748,13 @@ static VALUE Message_hash(VALUE _self) {
728
748
  }
729
749
 
730
750
  /*
731
- * call-seq:
732
- * Message.inspect => string
751
+ * ruby-doc: AbstractMessage#inspect
733
752
  *
734
753
  * Returns a human-readable string representing this message. It will be
735
754
  * formatted as "<MessageType: field1: value1, field2: value2, ...>". Each
736
755
  * field's value is represented according to its own #inspect method.
756
+ *
757
+ * @return [String]
737
758
  */
738
759
  static VALUE Message_inspect(VALUE _self) {
739
760
  Message* self = ruby_to_Message(_self);
@@ -766,58 +787,34 @@ static VALUE Message_CreateHash(const upb_Message* msg,
766
787
  if (!msg) return Qnil;
767
788
 
768
789
  VALUE hash = rb_hash_new();
769
- int n = upb_MessageDef_FieldCount(m);
770
- bool is_proto2;
771
-
772
- // We currently have a few behaviors that are specific to proto2.
773
- // This is unfortunate, we should key behaviors off field attributes (like
774
- // whether a field has presence), not proto2 vs. proto3. We should see if we
775
- // can change this without breaking users.
776
- is_proto2 = upb_MessageDef_Syntax(m) == kUpb_Syntax_Proto2;
777
-
778
- for (int i = 0; i < n; i++) {
779
- const upb_FieldDef* field = upb_MessageDef_Field(m, i);
780
- TypeInfo type_info = TypeInfo_get(field);
781
- upb_MessageValue msgval;
782
- VALUE msg_value;
783
- VALUE msg_key;
784
-
785
- if (!is_proto2 && upb_FieldDef_IsSubMessage(field) &&
786
- !upb_FieldDef_IsRepeated(field) &&
787
- !upb_Message_HasFieldByDef(msg, field)) {
788
- // TODO: Legacy behavior, remove when we fix the is_proto2 differences.
789
- msg_key = ID2SYM(rb_intern(upb_FieldDef_Name(field)));
790
- rb_hash_aset(hash, msg_key, Qnil);
791
- continue;
792
- }
790
+ size_t iter = kUpb_Message_Begin;
791
+ const upb_DefPool* pool = upb_FileDef_Pool(upb_MessageDef_File(m));
792
+ const upb_FieldDef* field;
793
+ upb_MessageValue val;
793
794
 
794
- // Do not include fields that are not present (oneof or optional fields).
795
- if (is_proto2 && upb_FieldDef_HasPresence(field) &&
796
- !upb_Message_HasFieldByDef(msg, field)) {
795
+ while (upb_Message_Next(msg, m, pool, &field, &val, &iter)) {
796
+ if (upb_FieldDef_IsExtension(field)) {
797
+ // TODO: allow extensions once we have decided what naming scheme the
798
+ // symbol should use. eg. :"[pkg.ext]"
797
799
  continue;
798
800
  }
799
801
 
800
- msg_key = ID2SYM(rb_intern(upb_FieldDef_Name(field)));
801
- msgval = upb_Message_GetFieldByDef(msg, field);
802
-
803
- // Proto2 omits empty map/repeated filds also.
802
+ TypeInfo type_info = TypeInfo_get(field);
803
+ VALUE msg_value;
804
804
 
805
805
  if (upb_FieldDef_IsMap(field)) {
806
806
  const upb_MessageDef* entry_m = upb_FieldDef_MessageSubDef(field);
807
807
  const upb_FieldDef* key_f = upb_MessageDef_FindFieldByNumber(entry_m, 1);
808
808
  const upb_FieldDef* val_f = upb_MessageDef_FindFieldByNumber(entry_m, 2);
809
809
  upb_CType key_type = upb_FieldDef_CType(key_f);
810
- msg_value = Map_CreateHash(msgval.map_val, key_type, TypeInfo_get(val_f));
810
+ msg_value = Map_CreateHash(val.map_val, key_type, TypeInfo_get(val_f));
811
811
  } else if (upb_FieldDef_IsRepeated(field)) {
812
- if (is_proto2 &&
813
- (!msgval.array_val || upb_Array_Size(msgval.array_val) == 0)) {
814
- continue;
815
- }
816
- msg_value = RepeatedField_CreateArray(msgval.array_val, type_info);
812
+ msg_value = RepeatedField_CreateArray(val.array_val, type_info);
817
813
  } else {
818
- msg_value = Scalar_CreateHash(msgval, type_info);
814
+ msg_value = Scalar_CreateHash(val, type_info);
819
815
  }
820
816
 
817
+ VALUE msg_key = ID2SYM(rb_intern(upb_FieldDef_Name(field)));
821
818
  rb_hash_aset(hash, msg_key, msg_value);
822
819
  }
823
820
 
@@ -833,10 +830,11 @@ VALUE Scalar_CreateHash(upb_MessageValue msgval, TypeInfo type_info) {
833
830
  }
834
831
 
835
832
  /*
836
- * call-seq:
837
- * Message.to_h => {}
833
+ * ruby-doc: AbstractMessage#to_h
838
834
  *
839
835
  * Returns the message as a Ruby Hash object, with keys as symbols.
836
+ *
837
+ * @return [Hash]
840
838
  */
841
839
  static VALUE Message_to_h(VALUE _self) {
842
840
  Message* self = ruby_to_Message(_self);
@@ -844,53 +842,56 @@ static VALUE Message_to_h(VALUE _self) {
844
842
  }
845
843
 
846
844
  /*
847
- * call-seq:
848
- * Message.freeze => self
845
+ * ruby-doc: AbstractMessage#frozen?
849
846
  *
850
- * Freezes the message object. We have to intercept this so we can pin the
851
- * Ruby object into memory so we don't forget it's frozen.
847
+ * Returns true if the message is frozen in either Ruby or the underlying
848
+ * representation. Freezes the Ruby message object if it is not already frozen
849
+ * in Ruby but it is frozen in the underlying representation.
850
+ *
851
+ * @return [Boolean]
852
852
  */
853
- static VALUE Message_freeze(VALUE _self) {
853
+ VALUE Message_frozen(VALUE _self) {
854
854
  Message* self = ruby_to_Message(_self);
855
- if (!RB_OBJ_FROZEN(_self)) {
856
- Arena_Pin(self->arena, _self);
857
- RB_OBJ_FREEZE(_self);
855
+ if (!upb_Message_IsFrozen(self->msg)) {
856
+ PBRUBY_ASSERT(!RB_OBJ_FROZEN(_self));
857
+ return Qfalse;
858
858
  }
859
- return _self;
859
+
860
+ // Lazily freeze the Ruby wrapper.
861
+ if (!RB_OBJ_FROZEN(_self)) RB_OBJ_FREEZE(_self);
862
+ return Qtrue;
860
863
  }
861
864
 
862
865
  /*
863
- * Deep freezes the message object recursively.
864
- * Internal use only.
866
+ * ruby-doc: AbstractMessage#freeze
867
+ *
868
+ * Freezes the message object. We have to intercept this so we can freeze the
869
+ * underlying representation, not just the Ruby wrapper.
870
+ *
871
+ * @return [self]
865
872
  */
866
- VALUE Message_internal_deep_freeze(VALUE _self) {
873
+ VALUE Message_freeze(VALUE _self) {
867
874
  Message* self = ruby_to_Message(_self);
868
- Message_freeze(_self);
869
-
870
- int n = upb_MessageDef_FieldCount(self->msgdef);
871
- for (int i = 0; i < n; i++) {
872
- const upb_FieldDef* f = upb_MessageDef_Field(self->msgdef, i);
873
- VALUE field = Message_getfield(_self, f);
874
-
875
- if (field != Qnil) {
876
- if (upb_FieldDef_IsMap(f)) {
877
- Map_internal_deep_freeze(field);
878
- } else if (upb_FieldDef_IsRepeated(f)) {
879
- RepeatedField_internal_deep_freeze(field);
880
- } else if (upb_FieldDef_IsSubMessage(f)) {
881
- Message_internal_deep_freeze(field);
882
- }
883
- }
875
+ if (RB_OBJ_FROZEN(_self)) {
876
+ PBRUBY_ASSERT(upb_Message_IsFrozen(self->msg));
877
+ return _self;
878
+ }
879
+ if (!upb_Message_IsFrozen(self->msg)) {
880
+ upb_Message_Freeze(Message_GetMutable(_self, NULL),
881
+ upb_MessageDef_MiniTable(self->msgdef));
884
882
  }
883
+ RB_OBJ_FREEZE(_self);
885
884
  return _self;
886
885
  }
887
886
 
888
887
  /*
889
- * call-seq:
890
- * Message.[](index) => value
888
+ * ruby-doc: AbstractMessage#[]
891
889
  *
892
890
  * Accesses a field's value by field name. The provided field name should be a
893
891
  * string.
892
+ *
893
+ * @param index [Integer]
894
+ * @return [Object]
894
895
  */
895
896
  static VALUE Message_index(VALUE _self, VALUE field_name) {
896
897
  Message* self = ruby_to_Message(_self);
@@ -907,11 +908,14 @@ static VALUE Message_index(VALUE _self, VALUE field_name) {
907
908
  }
908
909
 
909
910
  /*
910
- * call-seq:
911
- * Message.[]=(index, value)
911
+ * ruby-doc: AbstractMessage#[]=
912
912
  *
913
913
  * Sets a field's value by field name. The provided field name should be a
914
914
  * string.
915
+ *
916
+ * @param index [Integer]
917
+ * @param value [Object]
918
+ * @return [nil]
915
919
  */
916
920
  static VALUE Message_index_set(VALUE _self, VALUE field_name, VALUE value) {
917
921
  Message* self = ruby_to_Message(_self);
@@ -933,14 +937,16 @@ static VALUE Message_index_set(VALUE _self, VALUE field_name, VALUE value) {
933
937
  }
934
938
 
935
939
  /*
936
- * call-seq:
937
- * MessageClass.decode(data, options) => message
940
+ * ruby-doc: AbstractMessage.decode
938
941
  *
939
942
  * Decodes the given data (as a string containing bytes in protocol buffers wire
940
943
  * format) under the interpretation given by this message class's definition
941
944
  * and returns a message object with the corresponding field values.
942
- * @param options [Hash] options for the decoder
943
- * recursion_limit: set to maximum decoding depth for message (default is 64)
945
+ * @param data [String]
946
+ * @param options [Hash]
947
+ * @option recursion_limit [Integer] set to maximum decoding depth for message
948
+ * (default is 64)
949
+ * @return [AbstractMessage]
944
950
  */
945
951
  static VALUE Message_decode(int argc, VALUE* argv, VALUE klass) {
946
952
  VALUE data = argv[0];
@@ -987,31 +993,29 @@ VALUE Message_decode_bytes(int size, const char* bytes, int options,
987
993
  rb_raise(cParseError, "Error occurred during parsing");
988
994
  }
989
995
  if (freeze) {
990
- Message_internal_deep_freeze(msg_rb);
996
+ Message_freeze(msg_rb);
991
997
  }
992
998
  return msg_rb;
993
999
  }
994
1000
 
995
1001
  /*
996
- * call-seq:
997
- * MessageClass.decode_json(data, options = {}) => message
1002
+ * ruby-doc: AbstractMessage.decode_json
998
1003
  *
999
1004
  * Decodes the given data (as a string containing bytes in protocol buffers wire
1000
1005
  * format) under the interpretration given by this message class's definition
1001
1006
  * and returns a message object with the corresponding field values.
1002
1007
  *
1003
- * @param options [Hash] options for the decoder
1004
- * ignore_unknown_fields: set true to ignore unknown fields (default is to
1005
- * raise an error)
1008
+ * @param data [String]
1009
+ * @param options [Hash]
1010
+ * @option ignore_unknown_fields [Boolean] set true to ignore unknown fields
1011
+ * (default is to raise an error)
1012
+ * @return [AbstractMessage]
1006
1013
  */
1007
1014
  static VALUE Message_decode_json(int argc, VALUE* argv, VALUE klass) {
1008
1015
  VALUE data = argv[0];
1009
1016
  int options = 0;
1010
1017
  upb_Status status;
1011
1018
 
1012
- // TODO: use this message's pool instead.
1013
- const upb_DefPool* symtab = DescriptorPool_GetSymtab(generated_pool);
1014
-
1015
1019
  if (argc < 1 || argc > 2) {
1016
1020
  rb_raise(rb_eArgError, "Expected 1 or 2 arguments.");
1017
1021
  }
@@ -1045,24 +1049,35 @@ static VALUE Message_decode_json(int argc, VALUE* argv, VALUE klass) {
1045
1049
  }
1046
1050
 
1047
1051
  upb_Status_Clear(&status);
1048
- if (!upb_JsonDecode(RSTRING_PTR(data), RSTRING_LEN(data),
1049
- (upb_Message*)msg->msg, msg->msgdef, symtab, options,
1050
- Arena_get(msg->arena), &status)) {
1051
- rb_raise(cParseError, "Error occurred during parsing: %s",
1052
- upb_Status_ErrorMessage(&status));
1052
+ const upb_DefPool* pool = upb_FileDef_Pool(upb_MessageDef_File(msg->msgdef));
1053
+
1054
+ int result = upb_JsonDecodeDetectingNonconformance(
1055
+ RSTRING_PTR(data), RSTRING_LEN(data), (upb_Message*)msg->msg,
1056
+ msg->msgdef, pool, options, Arena_get(msg->arena), &status);
1057
+
1058
+ switch (result) {
1059
+ case kUpb_JsonDecodeResult_Ok:
1060
+ break;
1061
+ case kUpb_JsonDecodeResult_Error:
1062
+ rb_raise(cParseError, "Error occurred during parsing: %s",
1063
+ upb_Status_ErrorMessage(&status));
1064
+ break;
1053
1065
  }
1054
1066
 
1055
1067
  return msg_rb;
1056
1068
  }
1057
1069
 
1058
1070
  /*
1059
- * call-seq:
1060
- * MessageClass.encode(msg, options) => bytes
1071
+ * ruby-doc: AbstractMessage.encode
1061
1072
  *
1062
1073
  * Encodes the given message object to its serialized form in protocol buffers
1063
1074
  * wire format.
1064
- * @param options [Hash] options for the encoder
1065
- * recursion_limit: set to maximum encoding depth for message (default is 64)
1075
+ *
1076
+ * @param msg [AbstractMessage]
1077
+ * @param options [Hash]
1078
+ * @option recursion_limit [Integer] set to maximum encoding depth for message
1079
+ * (default is 64)
1080
+ * @return [String]
1066
1081
  */
1067
1082
  static VALUE Message_encode(int argc, VALUE* argv, VALUE klass) {
1068
1083
  Message* msg = ruby_to_Message(argv[0]);
@@ -1109,14 +1124,17 @@ static VALUE Message_encode(int argc, VALUE* argv, VALUE klass) {
1109
1124
  }
1110
1125
 
1111
1126
  /*
1112
- * call-seq:
1113
- * MessageClass.encode_json(msg, options = {}) => json_string
1127
+ * ruby-doc: AbstractMessage.encode_json
1114
1128
  *
1115
1129
  * Encodes the given message object into its serialized JSON representation.
1116
- * @param options [Hash] options for the decoder
1117
- * preserve_proto_fieldnames: set true to use original fieldnames (default is
1118
- * to camelCase) emit_defaults: set true to emit 0/false values (default is to
1119
- * omit them)
1130
+ *
1131
+ * @param msg [AbstractMessage]
1132
+ * @param options [Hash]
1133
+ * @option preserve_proto_fieldnames [Boolean] set true to use original
1134
+ * fieldnames (default is to camelCase)
1135
+ * @option emit_defaults [Boolean] set true to emit 0/false values (default is
1136
+ * to omit them)
1137
+ * @return [String]
1120
1138
  */
1121
1139
  static VALUE Message_encode_json(int argc, VALUE* argv, VALUE klass) {
1122
1140
  Message* msg = ruby_to_Message(argv[0]);
@@ -1125,9 +1143,6 @@ static VALUE Message_encode_json(int argc, VALUE* argv, VALUE klass) {
1125
1143
  size_t size;
1126
1144
  upb_Status status;
1127
1145
 
1128
- // TODO: use this message's pool instead.
1129
- const upb_DefPool* symtab = DescriptorPool_GetSymtab(generated_pool);
1130
-
1131
1146
  if (argc < 1 || argc > 2) {
1132
1147
  rb_raise(rb_eArgError, "Expected 1 or 2 arguments.");
1133
1148
  }
@@ -1162,8 +1177,9 @@ static VALUE Message_encode_json(int argc, VALUE* argv, VALUE klass) {
1162
1177
  }
1163
1178
 
1164
1179
  upb_Status_Clear(&status);
1165
- size = upb_JsonEncode(msg->msg, msg->msgdef, symtab, options, buf,
1166
- sizeof(buf), &status);
1180
+ const upb_DefPool* pool = upb_FileDef_Pool(upb_MessageDef_File(msg->msgdef));
1181
+ size = upb_JsonEncode(msg->msg, msg->msgdef, pool, options, buf, sizeof(buf),
1182
+ &status);
1167
1183
 
1168
1184
  if (!upb_Status_IsOk(&status)) {
1169
1185
  rb_raise(cParseError, "Error occurred during encoding: %s",
@@ -1173,7 +1189,7 @@ static VALUE Message_encode_json(int argc, VALUE* argv, VALUE klass) {
1173
1189
  VALUE ret;
1174
1190
  if (size >= sizeof(buf)) {
1175
1191
  char* buf2 = malloc(size + 1);
1176
- upb_JsonEncode(msg->msg, msg->msgdef, symtab, options, buf2, size + 1,
1192
+ upb_JsonEncode(msg->msg, msg->msgdef, pool, options, buf2, size + 1,
1177
1193
  &status);
1178
1194
  ret = rb_str_new(buf2, size);
1179
1195
  free(buf2);
@@ -1186,11 +1202,12 @@ static VALUE Message_encode_json(int argc, VALUE* argv, VALUE klass) {
1186
1202
  }
1187
1203
 
1188
1204
  /*
1189
- * call-seq:
1190
- * Message.descriptor => descriptor
1205
+ * ruby-doc: AbstractMessage.descriptor
1191
1206
  *
1192
1207
  * Class method that returns the Descriptor instance corresponding to this
1193
1208
  * message class's type.
1209
+ *
1210
+ * @return [Descriptor]
1194
1211
  */
1195
1212
  static VALUE Message_descriptor(VALUE klass) {
1196
1213
  return rb_ivar_get(klass, descriptor_instancevar_interned);
@@ -1213,12 +1230,26 @@ VALUE build_class_from_descriptor(VALUE descriptor) {
1213
1230
  return klass;
1214
1231
  }
1215
1232
 
1233
+ /* ruby-doc: Enum
1234
+ *
1235
+ * There isn't really a concrete `Enum` module generated by Protobuf. Instead,
1236
+ * you can use this documentation as an indicator of methods that are defined on
1237
+ * each `Enum` module that is generated. E.g. if you have:
1238
+ *
1239
+ * enum my_enum_type
1240
+ *
1241
+ * in your Proto file and generate Ruby code, a module
1242
+ * called `MyEnumType` will be generated with the following methods available.
1243
+ */
1244
+
1216
1245
  /*
1217
- * call-seq:
1218
- * Enum.lookup(number) => name
1246
+ * ruby-doc: Enum.lookup
1219
1247
  *
1220
1248
  * This module method, provided on each generated enum module, looks up an enum
1221
1249
  * value by number and returns its name as a Ruby symbol, or nil if not found.
1250
+ *
1251
+ * @param number [Integer]
1252
+ * @return [String]
1222
1253
  */
1223
1254
  static VALUE enum_lookup(VALUE self, VALUE number) {
1224
1255
  int32_t num = NUM2INT(number);
@@ -1233,11 +1264,13 @@ static VALUE enum_lookup(VALUE self, VALUE number) {
1233
1264
  }
1234
1265
 
1235
1266
  /*
1236
- * call-seq:
1237
- * Enum.resolve(name) => number
1267
+ * ruby-doc: Enum.resolve
1238
1268
  *
1239
1269
  * This module method, provided on each generated enum module, looks up an enum
1240
1270
  * value by name (as a Ruby symbol) and returns its name, or nil if not found.
1271
+ *
1272
+ * @param name [String]
1273
+ * @return [Integer]
1241
1274
  */
1242
1275
  static VALUE enum_resolve(VALUE self, VALUE sym) {
1243
1276
  const char* name = rb_id2name(SYM2ID(sym));
@@ -1252,11 +1285,13 @@ static VALUE enum_resolve(VALUE self, VALUE sym) {
1252
1285
  }
1253
1286
 
1254
1287
  /*
1255
- * call-seq:
1256
- * Enum.descriptor
1288
+ * ruby-doc: Enum.descriptor
1257
1289
  *
1258
1290
  * This module method, provided on each generated enum module, returns the
1259
- * EnumDescriptor corresponding to this enum type.
1291
+ * {EnumDescriptor} corresponding to this enum type.
1292
+ *
1293
+ * @return [EnumDescriptor]
1294
+ *
1260
1295
  */
1261
1296
  static VALUE enum_descriptor(VALUE self) {
1262
1297
  return rb_ivar_get(self, descriptor_instancevar_interned);
@@ -1399,6 +1434,7 @@ static void Message_define_class(VALUE klass) {
1399
1434
  rb_define_method(klass, "==", Message_eq, 1);
1400
1435
  rb_define_method(klass, "eql?", Message_eq, 1);
1401
1436
  rb_define_method(klass, "freeze", Message_freeze, 0);
1437
+ rb_define_method(klass, "frozen?", Message_frozen, 0);
1402
1438
  rb_define_method(klass, "hash", Message_hash, 0);
1403
1439
  rb_define_method(klass, "to_h", Message_to_h, 0);
1404
1440
  rb_define_method(klass, "inspect", Message_inspect, 0);