google-protobuf 3.20.3 → 3.24.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.

Potentially problematic release.


This version of google-protobuf might be problematic. Click here for more details.

Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/ext/google/protobuf_c/convert.c +0 -0
  3. data/ext/google/protobuf_c/convert.h +0 -2
  4. data/ext/google/protobuf_c/defs.c +36 -25
  5. data/ext/google/protobuf_c/defs.h +0 -2
  6. data/ext/google/protobuf_c/extconf.rb +2 -3
  7. data/ext/google/protobuf_c/map.c +31 -44
  8. data/ext/google/protobuf_c/map.h +0 -2
  9. data/ext/google/protobuf_c/message.c +140 -106
  10. data/ext/google/protobuf_c/message.h +0 -2
  11. data/ext/google/protobuf_c/protobuf.c +36 -150
  12. data/ext/google/protobuf_c/protobuf.h +21 -6
  13. data/ext/google/protobuf_c/repeated_field.c +5 -2
  14. data/ext/google/protobuf_c/repeated_field.h +0 -2
  15. data/ext/google/protobuf_c/ruby-upb.c +11686 -8578
  16. data/ext/google/protobuf_c/ruby-upb.h +11727 -4588
  17. data/ext/google/protobuf_c/third_party/utf8_range/LICENSE +1 -0
  18. data/ext/google/protobuf_c/third_party/utf8_range/naive.c +0 -0
  19. data/ext/google/protobuf_c/third_party/utf8_range/range2-neon.c +1 -1
  20. data/ext/google/protobuf_c/third_party/utf8_range/range2-sse.c +0 -0
  21. data/ext/google/protobuf_c/third_party/utf8_range/utf8_range.h +12 -0
  22. data/ext/google/protobuf_c/wrap_memcpy.c +0 -0
  23. data/lib/google/protobuf/any_pb.rb +24 -5
  24. data/lib/google/protobuf/api_pb.rb +26 -23
  25. data/lib/google/protobuf/descriptor_dsl.rb +0 -0
  26. data/lib/google/protobuf/descriptor_pb.rb +40 -226
  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/field_mask_pb.rb +24 -4
  30. data/lib/google/protobuf/message_exts.rb +5 -0
  31. data/lib/google/protobuf/object_cache.rb +120 -0
  32. data/lib/google/protobuf/plugin_pb.rb +47 -0
  33. data/lib/google/protobuf/repeated_field.rb +15 -2
  34. data/lib/google/protobuf/source_context_pb.rb +24 -4
  35. data/lib/google/protobuf/struct_pb.rb +24 -20
  36. data/lib/google/protobuf/timestamp_pb.rb +24 -5
  37. data/lib/google/protobuf/type_pb.rb +26 -68
  38. data/lib/google/protobuf/well_known_types.rb +2 -8
  39. data/lib/google/protobuf/wrappers_pb.rb +24 -28
  40. data/lib/google/protobuf.rb +1 -0
  41. metadata +8 -12
  42. data/tests/basic.rb +0 -739
  43. data/tests/generated_code_test.rb +0 -23
  44. data/tests/stress.rb +0 -38
@@ -37,6 +37,7 @@
37
37
  #include "repeated_field.h"
38
38
 
39
39
  static VALUE cParseError = Qnil;
40
+ static VALUE cAbstractMessage = Qnil;
40
41
  static ID descriptor_instancevar_interned;
41
42
 
42
43
  static VALUE initialize_rb_class_with_no_args(VALUE klass) {
@@ -52,6 +53,8 @@ VALUE MessageOrEnum_GetDescriptor(VALUE klass) {
52
53
  // -----------------------------------------------------------------------------
53
54
 
54
55
  typedef struct {
56
+ // IMPORTANT: WB_PROTECTED objects must only use the RB_OBJ_WRITE()
57
+ // macro to update VALUE references, as to trigger write barriers.
55
58
  VALUE arena;
56
59
  const upb_Message* msg; // Can get as mutable when non-frozen.
57
60
  const upb_MessageDef*
@@ -64,9 +67,9 @@ static void Message_mark(void* _self) {
64
67
  }
65
68
 
66
69
  static rb_data_type_t Message_type = {
67
- "Message",
70
+ "Google::Protobuf::Message",
68
71
  {Message_mark, RUBY_DEFAULT_FREE, NULL},
69
- .flags = RUBY_TYPED_FREE_IMMEDIATELY,
72
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
70
73
  };
71
74
 
72
75
  static Message* ruby_to_Message(VALUE msg_rb) {
@@ -104,8 +107,10 @@ upb_Message* Message_GetMutable(VALUE msg_rb, const upb_MessageDef** m) {
104
107
  void Message_InitPtr(VALUE self_, upb_Message* msg, VALUE arena) {
105
108
  Message* self = ruby_to_Message(self_);
106
109
  self->msg = msg;
107
- self->arena = arena;
108
- ObjectCache_Add(msg, self_);
110
+ RB_OBJ_WRITE(self_, &self->arena, arena);
111
+ VALUE stored = ObjectCache_TryAdd(msg, self_);
112
+ (void)stored;
113
+ PBRUBY_ASSERT(stored == self_);
109
114
  }
110
115
 
111
116
  VALUE Message_GetArena(VALUE msg_rb) {
@@ -145,7 +150,8 @@ void Message_PrintMessage(StringBuilder* b, const upb_Message* msg,
145
150
  for (int i = 0; i < n; i++) {
146
151
  const upb_FieldDef* field = upb_MessageDef_Field(m, i);
147
152
 
148
- if (upb_FieldDef_HasPresence(field) && !upb_Message_Has(msg, field)) {
153
+ if (upb_FieldDef_HasPresence(field) &&
154
+ !upb_Message_HasFieldByDef(msg, field)) {
149
155
  continue;
150
156
  }
151
157
 
@@ -155,7 +161,7 @@ void Message_PrintMessage(StringBuilder* b, const upb_Message* msg,
155
161
  first = false;
156
162
  }
157
163
 
158
- upb_MessageValue msgval = upb_Message_Get(msg, field);
164
+ upb_MessageValue msgval = upb_Message_GetFieldByDef(msg, field);
159
165
 
160
166
  StringBuilder_Printf(b, "%s: ", upb_FieldDef_Name(field));
161
167
 
@@ -241,15 +247,6 @@ static int extract_method_call(VALUE method_name, Message* self,
241
247
  if (Match(m, name, f, o, "clear_", "")) return METHOD_CLEAR;
242
248
  if (Match(m, name, f, o, "has_", "?") &&
243
249
  (*o || (*f && upb_FieldDef_HasPresence(*f)))) {
244
- // Disallow oneof hazzers for proto3.
245
- // TODO(haberman): remove this test when we are enabling oneof hazzers for
246
- // proto3.
247
- if (*f && !upb_FieldDef_IsSubMessage(*f) &&
248
- upb_FieldDef_RealContainingOneof(*f) &&
249
- upb_MessageDef_Syntax(upb_FieldDef_ContainingType(*f)) !=
250
- kUpb_Syntax_Proto2) {
251
- return METHOD_UNKNOWN;
252
- }
253
250
  return METHOD_PRESENCE;
254
251
  }
255
252
  if (Match(m, name, f, o, "", "_as_value") && *f &&
@@ -278,7 +275,8 @@ static VALUE Message_oneof_accessor(VALUE _self, const upb_OneofDef* o,
278
275
  return oneof_field == NULL ? Qfalse : Qtrue;
279
276
  case METHOD_CLEAR:
280
277
  if (oneof_field != NULL) {
281
- upb_Message_ClearField(Message_GetMutable(_self, NULL), oneof_field);
278
+ upb_Message_ClearFieldByDef(Message_GetMutable(_self, NULL),
279
+ oneof_field);
282
280
  }
283
281
  return Qnil;
284
282
  case METHOD_GETTER:
@@ -301,13 +299,13 @@ static void Message_setfield(upb_Message* msg, const upb_FieldDef* f, VALUE val,
301
299
  } else {
302
300
  if (val == Qnil &&
303
301
  (upb_FieldDef_IsSubMessage(f) || upb_FieldDef_RealContainingOneof(f))) {
304
- upb_Message_ClearField(msg, f);
302
+ upb_Message_ClearFieldByDef(msg, f);
305
303
  return;
306
304
  }
307
305
  msgval =
308
306
  Convert_RubyToUpb(val, upb_FieldDef_Name(f), TypeInfo_get(f), arena);
309
307
  }
310
- upb_Message_Set(msg, f, msgval, arena);
308
+ upb_Message_SetFieldByDef(msg, f, msgval, arena);
311
309
  }
312
310
 
313
311
  VALUE Message_getfield(VALUE _self, const upb_FieldDef* f) {
@@ -329,12 +327,12 @@ VALUE Message_getfield(VALUE _self, const upb_FieldDef* f) {
329
327
  upb_Array* arr = upb_Message_Mutable(msg, f, arena).array;
330
328
  return RepeatedField_GetRubyWrapper(arr, TypeInfo_get(f), self->arena);
331
329
  } else if (upb_FieldDef_IsSubMessage(f)) {
332
- if (!upb_Message_Has(self->msg, f)) return Qnil;
330
+ if (!upb_Message_HasFieldByDef(self->msg, f)) return Qnil;
333
331
  upb_Message* submsg = upb_Message_Mutable(msg, f, arena).msg;
334
332
  const upb_MessageDef* m = upb_FieldDef_MessageSubDef(f);
335
333
  return Message_GetRubyWrapper(submsg, m, self->arena);
336
334
  } else {
337
- upb_MessageValue msgval = upb_Message_Get(self->msg, f);
335
+ upb_MessageValue msgval = upb_Message_GetFieldByDef(self->msg, f);
338
336
  return Convert_UpbToRuby(msgval, TypeInfo_get(f), self->arena);
339
337
  }
340
338
  }
@@ -348,23 +346,24 @@ static VALUE Message_field_accessor(VALUE _self, const upb_FieldDef* f,
348
346
  Message_setfield(Message_GetMutable(_self, NULL), f, argv[1], arena);
349
347
  return Qnil;
350
348
  case METHOD_CLEAR:
351
- upb_Message_ClearField(Message_GetMutable(_self, NULL), f);
349
+ upb_Message_ClearFieldByDef(Message_GetMutable(_self, NULL), f);
352
350
  return Qnil;
353
351
  case METHOD_PRESENCE:
354
352
  if (!upb_FieldDef_HasPresence(f)) {
355
353
  rb_raise(rb_eRuntimeError, "Field does not have presence.");
356
354
  }
357
- return upb_Message_Has(Message_Get(_self, NULL), f);
355
+ return upb_Message_HasFieldByDef(Message_Get(_self, NULL), f);
358
356
  case METHOD_WRAPPER_GETTER: {
359
357
  Message* self = ruby_to_Message(_self);
360
- if (upb_Message_Has(self->msg, f)) {
358
+ if (upb_Message_HasFieldByDef(self->msg, f)) {
361
359
  PBRUBY_ASSERT(upb_FieldDef_IsSubMessage(f) &&
362
360
  !upb_FieldDef_IsRepeated(f));
363
- upb_MessageValue wrapper = upb_Message_Get(self->msg, f);
361
+ upb_MessageValue wrapper = upb_Message_GetFieldByDef(self->msg, f);
364
362
  const upb_MessageDef* wrapper_m = upb_FieldDef_MessageSubDef(f);
365
363
  const upb_FieldDef* value_f =
366
364
  upb_MessageDef_FindFieldByNumber(wrapper_m, 1);
367
- upb_MessageValue value = upb_Message_Get(wrapper.msg_val, value_f);
365
+ upb_MessageValue value =
366
+ upb_Message_GetFieldByDef(wrapper.msg_val, value_f);
368
367
  return Convert_UpbToRuby(value, TypeInfo_get(value_f), self->arena);
369
368
  } else {
370
369
  return Qnil;
@@ -373,19 +372,20 @@ static VALUE Message_field_accessor(VALUE _self, const upb_FieldDef* f,
373
372
  case METHOD_WRAPPER_SETTER: {
374
373
  upb_Message* msg = Message_GetMutable(_self, NULL);
375
374
  if (argv[1] == Qnil) {
376
- upb_Message_ClearField(msg, f);
375
+ upb_Message_ClearFieldByDef(msg, f);
377
376
  } else {
378
377
  const upb_FieldDef* val_f =
379
378
  upb_MessageDef_FindFieldByNumber(upb_FieldDef_MessageSubDef(f), 1);
380
379
  upb_MessageValue msgval = Convert_RubyToUpb(
381
380
  argv[1], upb_FieldDef_Name(f), TypeInfo_get(val_f), arena);
382
381
  upb_Message* wrapper = upb_Message_Mutable(msg, f, arena).msg;
383
- upb_Message_Set(wrapper, val_f, msgval, arena);
382
+ upb_Message_SetFieldByDef(wrapper, val_f, msgval, arena);
384
383
  }
385
384
  return Qnil;
386
385
  }
387
386
  case METHOD_ENUM_GETTER: {
388
- upb_MessageValue msgval = upb_Message_Get(Message_Get(_self, NULL), f);
387
+ upb_MessageValue msgval =
388
+ upb_Message_GetFieldByDef(Message_Get(_self, NULL), f);
389
389
 
390
390
  if (upb_FieldDef_Label(f) == kUpb_Label_Repeated) {
391
391
  // Map repeated fields to a new type with ints
@@ -510,8 +510,8 @@ static int Map_initialize_kwarg(VALUE key, VALUE val, VALUE _self) {
510
510
  k = Convert_RubyToUpb(key, "", map_init->key_type, NULL);
511
511
 
512
512
  if (map_init->val_type.type == kUpb_CType_Message && TYPE(val) == T_HASH) {
513
- upb_Message* msg =
514
- upb_Message_New(map_init->val_type.def.msgdef, map_init->arena);
513
+ upb_MiniTable* t = upb_MessageDef_MiniTable(map_init->val_type.def.msgdef);
514
+ upb_Message* msg = upb_Message_New(t, map_init->arena);
515
515
  Message_InitFromValue(msg, map_init->val_type.def.msgdef, val,
516
516
  map_init->arena);
517
517
  v.msg_val = msg;
@@ -541,7 +541,8 @@ static upb_MessageValue MessageValue_FromValue(VALUE val, TypeInfo info,
541
541
  upb_Arena* arena) {
542
542
  if (info.type == kUpb_CType_Message) {
543
543
  upb_MessageValue msgval;
544
- upb_Message* msg = upb_Message_New(info.def.msgdef, arena);
544
+ upb_MiniTable* t = upb_MessageDef_MiniTable(info.def.msgdef);
545
+ upb_Message* msg = upb_Message_New(t, arena);
545
546
  Message_InitFromValue(msg, info.def.msgdef, val, arena);
546
547
  msgval.msg_val = msg;
547
548
  return msgval;
@@ -593,7 +594,7 @@ static void Message_InitFieldFromValue(upb_Message* msg, const upb_FieldDef* f,
593
594
  } else {
594
595
  upb_MessageValue msgval =
595
596
  Convert_RubyToUpb(val, upb_FieldDef_Name(f), TypeInfo_get(f), arena);
596
- upb_Message_Set(msg, f, msgval, arena);
597
+ upb_Message_SetFieldByDef(msg, f, msgval, arena);
597
598
  }
598
599
  }
599
600
 
@@ -656,7 +657,8 @@ static VALUE Message_initialize(int argc, VALUE* argv, VALUE _self) {
656
657
  Message* self = ruby_to_Message(_self);
657
658
  VALUE arena_rb = Arena_new();
658
659
  upb_Arena* arena = Arena_get(arena_rb);
659
- upb_Message* msg = upb_Message_New(self->msgdef, arena);
660
+ upb_MiniTable* t = upb_MessageDef_MiniTable(self->msgdef);
661
+ upb_Message* msg = upb_Message_New(t, arena);
660
662
 
661
663
  Message_InitPtr(_self, msg, arena_rb);
662
664
 
@@ -695,15 +697,20 @@ bool Message_Equal(const upb_Message* m1, const upb_Message* m2,
695
697
  if (m1 == m2) return true;
696
698
 
697
699
  size_t size1, size2;
698
- int encode_opts = kUpb_Encode_SkipUnknown | kUpb_Encode_Deterministic;
700
+ int encode_opts =
701
+ kUpb_EncodeOption_SkipUnknown | kUpb_EncodeOption_Deterministic;
699
702
  upb_Arena* arena_tmp = upb_Arena_New();
700
703
  const upb_MiniTable* layout = upb_MessageDef_MiniTable(m);
701
704
 
702
705
  // Compare deterministically serialized payloads with no unknown fields.
703
- char* data1 = upb_Encode(m1, layout, encode_opts, arena_tmp, &size1);
704
- char* data2 = upb_Encode(m2, layout, encode_opts, arena_tmp, &size2);
705
-
706
- if (data1 && data2) {
706
+ char* data1;
707
+ char* data2;
708
+ upb_EncodeStatus status1 =
709
+ upb_Encode(m1, layout, encode_opts, arena_tmp, &data1, &size1);
710
+ upb_EncodeStatus status2 =
711
+ upb_Encode(m2, layout, encode_opts, arena_tmp, &data2, &size2);
712
+
713
+ if (status1 == kUpb_EncodeStatus_Ok && status2 == kUpb_EncodeStatus_Ok) {
707
714
  bool ret = (size1 == size2) && (memcmp(data1, data2, size1) == 0);
708
715
  upb_Arena_Free(arena_tmp);
709
716
  return ret;
@@ -735,15 +742,16 @@ static VALUE Message_eq(VALUE _self, VALUE _other) {
735
742
  uint64_t Message_Hash(const upb_Message* msg, const upb_MessageDef* m,
736
743
  uint64_t seed) {
737
744
  upb_Arena* arena = upb_Arena_New();
738
- const char* data;
745
+ char* data;
739
746
  size_t size;
740
747
 
741
748
  // Hash a deterministically serialized payloads with no unknown fields.
742
- data = upb_Encode(msg, upb_MessageDef_MiniTable(m),
743
- kUpb_Encode_SkipUnknown | kUpb_Encode_Deterministic, arena,
744
- &size);
749
+ upb_EncodeStatus status = upb_Encode(
750
+ msg, upb_MessageDef_MiniTable(m),
751
+ kUpb_EncodeOption_SkipUnknown | kUpb_EncodeOption_Deterministic, arena,
752
+ &data, &size);
745
753
 
746
- if (data) {
754
+ if (status == kUpb_EncodeStatus_Ok) {
747
755
  uint64_t ret = _upb_Hash(data, size, seed);
748
756
  upb_Arena_Free(arena);
749
757
  return ret;
@@ -823,7 +831,8 @@ static VALUE Message_CreateHash(const upb_Message* msg,
823
831
  VALUE msg_key;
824
832
 
825
833
  if (!is_proto2 && upb_FieldDef_IsSubMessage(field) &&
826
- !upb_FieldDef_IsRepeated(field) && !upb_Message_Has(msg, field)) {
834
+ !upb_FieldDef_IsRepeated(field) &&
835
+ !upb_Message_HasFieldByDef(msg, field)) {
827
836
  // TODO: Legacy behavior, remove when we fix the is_proto2 differences.
828
837
  msg_key = ID2SYM(rb_intern(upb_FieldDef_Name(field)));
829
838
  rb_hash_aset(hash, msg_key, Qnil);
@@ -832,12 +841,12 @@ static VALUE Message_CreateHash(const upb_Message* msg,
832
841
 
833
842
  // Do not include fields that are not present (oneof or optional fields).
834
843
  if (is_proto2 && upb_FieldDef_HasPresence(field) &&
835
- !upb_Message_Has(msg, field)) {
844
+ !upb_Message_HasFieldByDef(msg, field)) {
836
845
  continue;
837
846
  }
838
847
 
839
848
  msg_key = ID2SYM(rb_intern(upb_FieldDef_Name(field)));
840
- msgval = upb_Message_Get(msg, field);
849
+ msgval = upb_Message_GetFieldByDef(msg, field);
841
850
 
842
851
  // Proto2 omits empty map/repeated filds also.
843
852
 
@@ -940,7 +949,7 @@ static VALUE Message_index_set(VALUE _self, VALUE field_name, VALUE value) {
940
949
  }
941
950
 
942
951
  val = Convert_RubyToUpb(value, upb_FieldDef_Name(f), TypeInfo_get(f), arena);
943
- upb_Message_Set(Message_GetMutable(_self, NULL), f, val, arena);
952
+ upb_Message_SetFieldByDef(Message_GetMutable(_self, NULL), f, val, arena);
944
953
 
945
954
  return Qnil;
946
955
  }
@@ -969,10 +978,11 @@ static VALUE Message_decode(int argc, VALUE* argv, VALUE klass) {
969
978
  rb_raise(rb_eArgError, "Expected hash arguments.");
970
979
  }
971
980
 
972
- VALUE depth = rb_hash_lookup(hash_args, ID2SYM(rb_intern("recursion_limit")));
981
+ VALUE depth =
982
+ rb_hash_lookup(hash_args, ID2SYM(rb_intern("recursion_limit")));
973
983
 
974
984
  if (depth != Qnil && TYPE(depth) == T_FIXNUM) {
975
- options |= UPB_DECODE_MAXDEPTH(FIX2INT(depth));
985
+ options |= upb_DecodeOptions_MaxDepth(FIX2INT(depth));
976
986
  }
977
987
  }
978
988
 
@@ -983,9 +993,10 @@ static VALUE Message_decode(int argc, VALUE* argv, VALUE klass) {
983
993
  VALUE msg_rb = initialize_rb_class_with_no_args(klass);
984
994
  Message* msg = ruby_to_Message(msg_rb);
985
995
 
986
- upb_DecodeStatus status = upb_Decode(
987
- RSTRING_PTR(data), RSTRING_LEN(data), (upb_Message*)msg->msg,
988
- upb_MessageDef_MiniTable(msg->msgdef), NULL, options, Arena_get(msg->arena));
996
+ upb_DecodeStatus status =
997
+ upb_Decode(RSTRING_PTR(data), RSTRING_LEN(data), (upb_Message*)msg->msg,
998
+ upb_MessageDef_MiniTable(msg->msgdef), NULL, options,
999
+ Arena_get(msg->arena));
989
1000
 
990
1001
  if (status != kUpb_DecodeStatus_Ok) {
991
1002
  rb_raise(cParseError, "Error occurred during parsing");
@@ -1069,7 +1080,7 @@ static VALUE Message_decode_json(int argc, VALUE* argv, VALUE klass) {
1069
1080
  static VALUE Message_encode(int argc, VALUE* argv, VALUE klass) {
1070
1081
  Message* msg = ruby_to_Message(argv[0]);
1071
1082
  int options = 0;
1072
- const char* data;
1083
+ char* data;
1073
1084
  size_t size;
1074
1085
 
1075
1086
  if (CLASS_OF(argv[0]) != klass) {
@@ -1085,19 +1096,21 @@ static VALUE Message_encode(int argc, VALUE* argv, VALUE klass) {
1085
1096
  if (TYPE(hash_args) != T_HASH) {
1086
1097
  rb_raise(rb_eArgError, "Expected hash arguments.");
1087
1098
  }
1088
- VALUE depth = rb_hash_lookup(hash_args, ID2SYM(rb_intern("recursion_limit")));
1099
+ VALUE depth =
1100
+ rb_hash_lookup(hash_args, ID2SYM(rb_intern("recursion_limit")));
1089
1101
 
1090
1102
  if (depth != Qnil && TYPE(depth) == T_FIXNUM) {
1091
- options |= UPB_DECODE_MAXDEPTH(FIX2INT(depth));
1103
+ options |= upb_DecodeOptions_MaxDepth(FIX2INT(depth));
1092
1104
  }
1093
1105
  }
1094
1106
 
1095
- upb_Arena *arena = upb_Arena_New();
1107
+ upb_Arena* arena = upb_Arena_New();
1096
1108
 
1097
- data = upb_Encode(msg->msg, upb_MessageDef_MiniTable(msg->msgdef),
1098
- options, arena, &size);
1109
+ upb_EncodeStatus status =
1110
+ upb_Encode(msg->msg, upb_MessageDef_MiniTable(msg->msgdef), options,
1111
+ arena, &data, &size);
1099
1112
 
1100
- if (data) {
1113
+ if (status == kUpb_EncodeStatus_Ok) {
1101
1114
  VALUE ret = rb_str_new(data, size);
1102
1115
  rb_enc_associate(ret, rb_ascii8bit_encoding());
1103
1116
  upb_Arena_Free(arena);
@@ -1135,7 +1148,8 @@ static VALUE Message_encode_json(int argc, VALUE* argv, VALUE klass) {
1135
1148
  if (argc == 2) {
1136
1149
  VALUE hash_args = argv[1];
1137
1150
  if (TYPE(hash_args) != T_HASH) {
1138
- if (RTEST(rb_funcall(hash_args, rb_intern("respond_to?"), 1, rb_str_new2("to_h")))) {
1151
+ if (RTEST(rb_funcall(hash_args, rb_intern("respond_to?"), 1,
1152
+ rb_str_new2("to_h")))) {
1139
1153
  hash_args = rb_funcall(hash_args, rb_intern("to_h"), 0);
1140
1154
  } else {
1141
1155
  rb_raise(rb_eArgError, "Expected hash arguments.");
@@ -1152,6 +1166,12 @@ static VALUE Message_encode_json(int argc, VALUE* argv, VALUE klass) {
1152
1166
  Qfalse))) {
1153
1167
  options |= upb_JsonEncode_EmitDefaults;
1154
1168
  }
1169
+
1170
+ if (RTEST(rb_hash_lookup2(hash_args,
1171
+ ID2SYM(rb_intern("format_enums_as_integers")),
1172
+ Qfalse))) {
1173
+ options |= upb_JsonEncode_FormatEnumsAsIntegers;
1174
+ }
1155
1175
  }
1156
1176
 
1157
1177
  upb_Status_Clear(&status);
@@ -1201,36 +1221,8 @@ VALUE build_class_from_descriptor(VALUE descriptor) {
1201
1221
  klass = rb_define_class_id(
1202
1222
  // Docs say this parameter is ignored. User will assign return value to
1203
1223
  // their own toplevel constant class name.
1204
- rb_intern("Message"), rb_cObject);
1224
+ rb_intern("Message"), cAbstractMessage);
1205
1225
  rb_ivar_set(klass, descriptor_instancevar_interned, descriptor);
1206
- rb_define_alloc_func(klass, Message_alloc);
1207
- rb_require("google/protobuf/message_exts");
1208
- rb_include_module(klass, rb_eval_string("::Google::Protobuf::MessageExts"));
1209
- rb_extend_object(
1210
- klass, rb_eval_string("::Google::Protobuf::MessageExts::ClassMethods"));
1211
-
1212
- rb_define_method(klass, "method_missing", Message_method_missing, -1);
1213
- rb_define_method(klass, "respond_to_missing?", Message_respond_to_missing,
1214
- -1);
1215
- rb_define_method(klass, "initialize", Message_initialize, -1);
1216
- rb_define_method(klass, "dup", Message_dup, 0);
1217
- // Also define #clone so that we don't inherit Object#clone.
1218
- rb_define_method(klass, "clone", Message_dup, 0);
1219
- rb_define_method(klass, "==", Message_eq, 1);
1220
- rb_define_method(klass, "eql?", Message_eq, 1);
1221
- rb_define_method(klass, "freeze", Message_freeze, 0);
1222
- rb_define_method(klass, "hash", Message_hash, 0);
1223
- rb_define_method(klass, "to_h", Message_to_h, 0);
1224
- rb_define_method(klass, "inspect", Message_inspect, 0);
1225
- rb_define_method(klass, "to_s", Message_inspect, 0);
1226
- rb_define_method(klass, "[]", Message_index, 1);
1227
- rb_define_method(klass, "[]=", Message_index_set, 2);
1228
- rb_define_singleton_method(klass, "decode", Message_decode, -1);
1229
- rb_define_singleton_method(klass, "encode", Message_encode, -1);
1230
- rb_define_singleton_method(klass, "decode_json", Message_decode_json, -1);
1231
- rb_define_singleton_method(klass, "encode_json", Message_encode_json, -1);
1232
- rb_define_singleton_method(klass, "descriptor", Message_descriptor, 0);
1233
-
1234
1226
  return klass;
1235
1227
  }
1236
1228
 
@@ -1290,15 +1282,22 @@ VALUE build_module_from_enumdesc(VALUE _enumdesc) {
1290
1282
  int n = upb_EnumDef_ValueCount(e);
1291
1283
  for (int i = 0; i < n; i++) {
1292
1284
  const upb_EnumValueDef* ev = upb_EnumDef_Value(e, i);
1293
- const char* name = upb_EnumValueDef_Name(ev);
1285
+ upb_Arena* arena = upb_Arena_New();
1286
+ const char* src_name = upb_EnumValueDef_Name(ev);
1287
+ char* name = upb_strdup2(src_name, strlen(src_name), arena);
1294
1288
  int32_t value = upb_EnumValueDef_Number(ev);
1295
1289
  if (name[0] < 'A' || name[0] > 'Z') {
1296
- rb_warn(
1297
- "Enum value '%s' does not start with an uppercase letter "
1298
- "as is required for Ruby constants.",
1299
- name);
1290
+ if (name[0] >= 'a' && name[0] <= 'z') {
1291
+ name[0] -= 32; // auto capitalize
1292
+ } else {
1293
+ rb_warn(
1294
+ "Enum value '%s' does not start with an uppercase letter "
1295
+ "as is required for Ruby constants.",
1296
+ name);
1297
+ }
1300
1298
  }
1301
1299
  rb_define_const(mod, name, INT2NUM(value));
1300
+ upb_Arena_Free(arena);
1302
1301
  }
1303
1302
 
1304
1303
  rb_define_singleton_method(mod, "lookup", enum_lookup, 1);
@@ -1309,7 +1308,7 @@ VALUE build_module_from_enumdesc(VALUE _enumdesc) {
1309
1308
  return mod;
1310
1309
  }
1311
1310
 
1312
- // Internal only; used by Google::Protobuf.deep_copy.
1311
+ // Internal to the library; used by Google::Protobuf.deep_copy.
1313
1312
  upb_Message* Message_deep_copy(const upb_Message* msg, const upb_MessageDef* m,
1314
1313
  upb_Arena* arena) {
1315
1314
  // Serialize and parse.
@@ -1317,11 +1316,13 @@ upb_Message* Message_deep_copy(const upb_Message* msg, const upb_MessageDef* m,
1317
1316
  const upb_MiniTable* layout = upb_MessageDef_MiniTable(m);
1318
1317
  size_t size;
1319
1318
 
1320
- char* data = upb_Encode(msg, layout, 0, tmp_arena, &size);
1321
- upb_Message* new_msg = upb_Message_New(m, arena);
1319
+ upb_Message* new_msg = upb_Message_New(layout, arena);
1320
+ char* data;
1322
1321
 
1323
- if (!data || upb_Decode(data, size, new_msg, layout, NULL, 0, arena) !=
1324
- kUpb_DecodeStatus_Ok) {
1322
+ if (upb_Encode(msg, layout, 0, tmp_arena, &data, &size) !=
1323
+ kUpb_EncodeStatus_Ok ||
1324
+ upb_Decode(data, size, new_msg, layout, NULL, 0, arena) !=
1325
+ kUpb_DecodeStatus_Ok) {
1325
1326
  upb_Arena_Free(tmp_arena);
1326
1327
  rb_raise(cParseError, "Error occurred copying proto");
1327
1328
  }
@@ -1348,7 +1349,8 @@ const upb_Message* Message_GetUpbMessage(VALUE value, const upb_MessageDef* m,
1348
1349
  switch (upb_MessageDef_WellKnownType(m)) {
1349
1350
  case kUpb_WellKnown_Timestamp: {
1350
1351
  // Time -> Google::Protobuf::Timestamp
1351
- upb_Message* msg = upb_Message_New(m, arena);
1352
+ const upb_MiniTable* t = upb_MessageDef_MiniTable(m);
1353
+ upb_Message* msg = upb_Message_New(t, arena);
1352
1354
  upb_MessageValue sec, nsec;
1353
1355
  struct timespec time;
1354
1356
  const upb_FieldDef* sec_f = upb_MessageDef_FindFieldByNumber(m, 1);
@@ -1359,13 +1361,14 @@ const upb_Message* Message_GetUpbMessage(VALUE value, const upb_MessageDef* m,
1359
1361
  time = rb_time_timespec(value);
1360
1362
  sec.int64_val = time.tv_sec;
1361
1363
  nsec.int32_val = time.tv_nsec;
1362
- upb_Message_Set(msg, sec_f, sec, arena);
1363
- upb_Message_Set(msg, nsec_f, nsec, arena);
1364
+ upb_Message_SetFieldByDef(msg, sec_f, sec, arena);
1365
+ upb_Message_SetFieldByDef(msg, nsec_f, nsec, arena);
1364
1366
  return msg;
1365
1367
  }
1366
1368
  case kUpb_WellKnown_Duration: {
1367
1369
  // Numeric -> Google::Protobuf::Duration
1368
- upb_Message* msg = upb_Message_New(m, arena);
1370
+ const upb_MiniTable* t = upb_MessageDef_MiniTable(m);
1371
+ upb_Message* msg = upb_Message_New(t, arena);
1369
1372
  upb_MessageValue sec, nsec;
1370
1373
  const upb_FieldDef* sec_f = upb_MessageDef_FindFieldByNumber(m, 1);
1371
1374
  const upb_FieldDef* nsec_f = upb_MessageDef_FindFieldByNumber(m, 2);
@@ -1374,8 +1377,8 @@ const upb_Message* Message_GetUpbMessage(VALUE value, const upb_MessageDef* m,
1374
1377
 
1375
1378
  sec.int64_val = NUM2LL(value);
1376
1379
  nsec.int32_val = round((NUM2DBL(value) - NUM2LL(value)) * 1000000000);
1377
- upb_Message_Set(msg, sec_f, sec, arena);
1378
- upb_Message_Set(msg, nsec_f, nsec, arena);
1380
+ upb_Message_SetFieldByDef(msg, sec_f, sec, arena);
1381
+ upb_Message_SetFieldByDef(msg, nsec_f, nsec, arena);
1379
1382
  return msg;
1380
1383
  }
1381
1384
  default:
@@ -1392,11 +1395,42 @@ const upb_Message* Message_GetUpbMessage(VALUE value, const upb_MessageDef* m,
1392
1395
  return self->msg;
1393
1396
  }
1394
1397
 
1398
+ static void Message_define_class(VALUE klass) {
1399
+ rb_define_alloc_func(klass, Message_alloc);
1400
+
1401
+ rb_require("google/protobuf/message_exts");
1402
+ rb_define_method(klass, "method_missing", Message_method_missing, -1);
1403
+ rb_define_method(klass, "respond_to_missing?", Message_respond_to_missing,
1404
+ -1);
1405
+ rb_define_method(klass, "initialize", Message_initialize, -1);
1406
+ rb_define_method(klass, "dup", Message_dup, 0);
1407
+ // Also define #clone so that we don't inherit Object#clone.
1408
+ rb_define_method(klass, "clone", Message_dup, 0);
1409
+ rb_define_method(klass, "==", Message_eq, 1);
1410
+ rb_define_method(klass, "eql?", Message_eq, 1);
1411
+ rb_define_method(klass, "freeze", Message_freeze, 0);
1412
+ rb_define_method(klass, "hash", Message_hash, 0);
1413
+ rb_define_method(klass, "to_h", Message_to_h, 0);
1414
+ rb_define_method(klass, "inspect", Message_inspect, 0);
1415
+ rb_define_method(klass, "to_s", Message_inspect, 0);
1416
+ rb_define_method(klass, "[]", Message_index, 1);
1417
+ rb_define_method(klass, "[]=", Message_index_set, 2);
1418
+ rb_define_singleton_method(klass, "decode", Message_decode, -1);
1419
+ rb_define_singleton_method(klass, "encode", Message_encode, -1);
1420
+ rb_define_singleton_method(klass, "decode_json", Message_decode_json, -1);
1421
+ rb_define_singleton_method(klass, "encode_json", Message_encode_json, -1);
1422
+ rb_define_singleton_method(klass, "descriptor", Message_descriptor, 0);
1423
+ }
1424
+
1395
1425
  void Message_register(VALUE protobuf) {
1396
1426
  cParseError = rb_const_get(protobuf, rb_intern("ParseError"));
1427
+ cAbstractMessage =
1428
+ rb_define_class_under(protobuf, "AbstractMessage", rb_cObject);
1429
+ Message_define_class(cAbstractMessage);
1430
+ rb_gc_register_address(&cAbstractMessage);
1397
1431
 
1398
1432
  // Ruby-interned string: "descriptor". We use this identifier to store an
1399
1433
  // instance variable on message classes we create in order to link them back
1400
1434
  // to their descriptors.
1401
- descriptor_instancevar_interned = rb_intern("descriptor");
1435
+ descriptor_instancevar_interned = rb_intern("@descriptor");
1402
1436
  }
@@ -31,8 +31,6 @@
31
31
  #ifndef RUBY_PROTOBUF_MESSAGE_H_
32
32
  #define RUBY_PROTOBUF_MESSAGE_H_
33
33
 
34
- #include <ruby/ruby.h>
35
-
36
34
  #include "protobuf.h"
37
35
  #include "ruby-upb.h"
38
36