google-protobuf 3.11.0 → 3.12.0

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.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c22ed71a5c0e59a40ec1e60d15bf6c981b4ce7a54f279dd748eea54278db0153
4
- data.tar.gz: 610690cb60428fe824e8e378d2b506f093870d8bedf7e930322fa3579acbb360
3
+ metadata.gz: 350de56c66a16de213635709b4d4e295bf4ea6404b487aaed6d42b3ce069067e
4
+ data.tar.gz: c9cdd0880d273e47fe4dcb70797fb3068174f7f3c2b4f3f2945f05782878e0fd
5
5
  SHA512:
6
- metadata.gz: 45b158e8252bf8a1ac83c7c2858bf90d2b0593cbdfacd85d204c0777a2e063810a06bd62713f4fe804003ee20e1a4ef6ebbe037b546616fbe1d194ae960376a1
7
- data.tar.gz: 500e314e580d361f6ecc1fb8fc9d7ffaed0a0444f2d08353676424fde715835cd16442adea1cd01939503f05f37030150dab2c9813aa7db2a0cd789f0f8af4e4
6
+ metadata.gz: 6b0fecc0c6fc1ef76a9ccd232e1f94c5334500d498ea5a8ee7f5be724827f83b4f4518ea4881d28d797f239be252d6f1d7a3fb6d630fd572cd1999d6095a35c8
7
+ data.tar.gz: ba9ba2cf25c2bbf5d4959926e4ead989b5dbcf886a91b9940c11217fdf4c476c6a6e2cfd372e1593b253ed1efdb8ff2711e45b3c2f68434ccc1c326acde0dca8
@@ -136,7 +136,7 @@ static void rewrite_enum_default(const upb_symtab* symtab,
136
136
  * same number.
137
137
  *
138
138
  * Here we do a pass over all enum defaults and rewrite numeric defaults by
139
- * looking up their labels. This is compilcated by the fact that the enum
139
+ * looking up their labels. This is complicated by the fact that the enum
140
140
  * definition can live in either the symtab or the file_proto.
141
141
  * */
142
142
  static void rewrite_enum_defaults(
@@ -572,7 +572,7 @@ VALUE Descriptor_file_descriptor(VALUE _self) {
572
572
  * call-seq:
573
573
  * Descriptor.name => name
574
574
  *
575
- * Returns the name of this message type as a fully-qualfied string (e.g.,
575
+ * Returns the name of this message type as a fully-qualified string (e.g.,
576
576
  * My.Package.MessageType).
577
577
  */
578
578
  VALUE Descriptor_name(VALUE _self) {
@@ -1100,7 +1100,7 @@ VALUE FieldDescriptor_get(VALUE _self, VALUE msg_rb) {
1100
1100
  * FieldDescriptor.has?(message) => boolean
1101
1101
  *
1102
1102
  * Returns whether the value is set on the given message. Raises an
1103
- * exception when calling with proto syntax 3.
1103
+ * exception when calling for fields that do not have presence.
1104
1104
  */
1105
1105
  VALUE FieldDescriptor_has(VALUE _self, VALUE msg_rb) {
1106
1106
  DEFINE_SELF(FieldDescriptor, self, _self);
@@ -1434,6 +1434,7 @@ void MessageBuilderContext_register(VALUE module) {
1434
1434
  rb_define_method(klass, "initialize",
1435
1435
  MessageBuilderContext_initialize, 2);
1436
1436
  rb_define_method(klass, "optional", MessageBuilderContext_optional, -1);
1437
+ rb_define_method(klass, "proto3_optional", MessageBuilderContext_proto3_optional, -1);
1437
1438
  rb_define_method(klass, "required", MessageBuilderContext_required, -1);
1438
1439
  rb_define_method(klass, "repeated", MessageBuilderContext_repeated, -1);
1439
1440
  rb_define_method(klass, "map", MessageBuilderContext_map, -1);
@@ -1469,7 +1470,8 @@ VALUE MessageBuilderContext_initialize(VALUE _self,
1469
1470
 
1470
1471
  static void msgdef_add_field(VALUE msgbuilder_rb, upb_label_t label, VALUE name,
1471
1472
  VALUE type, VALUE number, VALUE type_class,
1472
- VALUE options, int oneof_index) {
1473
+ VALUE options, int oneof_index,
1474
+ bool proto3_optional) {
1473
1475
  DEFINE_SELF(MessageBuilderContext, self, msgbuilder_rb);
1474
1476
  FileBuilderContext* file_context =
1475
1477
  ruby_to_FileBuilderContext(self->file_builder);
@@ -1489,6 +1491,10 @@ static void msgdef_add_field(VALUE msgbuilder_rb, upb_label_t label, VALUE name,
1489
1491
  google_protobuf_FieldDescriptorProto_set_type(
1490
1492
  field_proto, (int)ruby_to_descriptortype(type));
1491
1493
 
1494
+ if (proto3_optional) {
1495
+ google_protobuf_FieldDescriptorProto_set_proto3_optional(field_proto, true);
1496
+ }
1497
+
1492
1498
  if (type_class != Qnil) {
1493
1499
  Check_Type(type_class, T_STRING);
1494
1500
 
@@ -1574,7 +1580,38 @@ VALUE MessageBuilderContext_optional(int argc, VALUE* argv, VALUE _self) {
1574
1580
  }
1575
1581
 
1576
1582
  msgdef_add_field(_self, UPB_LABEL_OPTIONAL, name, type, number, type_class,
1577
- options, -1);
1583
+ options, -1, false);
1584
+
1585
+ return Qnil;
1586
+ }
1587
+
1588
+ /*
1589
+ * call-seq:
1590
+ * MessageBuilderContext.proto3_optional(name, type, number,
1591
+ * type_class = nil, options = nil)
1592
+ *
1593
+ * Defines a true proto3 optional field (that tracks presence) on this message
1594
+ * type with the given type, tag number, and type class (for message and enum
1595
+ * fields). The type must be a Ruby symbol (as accepted by
1596
+ * FieldDescriptor#type=) and the type_class must be a string, if present (as
1597
+ * accepted by FieldDescriptor#submsg_name=).
1598
+ */
1599
+ VALUE MessageBuilderContext_proto3_optional(int argc, VALUE* argv,
1600
+ VALUE _self) {
1601
+ VALUE name, type, number;
1602
+ VALUE type_class, options = Qnil;
1603
+
1604
+ rb_scan_args(argc, argv, "32", &name, &type, &number, &type_class, &options);
1605
+
1606
+ // Allow passing (name, type, number, options) or
1607
+ // (name, type, number, type_class, options)
1608
+ if (argc == 4 && RB_TYPE_P(type_class, T_HASH)) {
1609
+ options = type_class;
1610
+ type_class = Qnil;
1611
+ }
1612
+
1613
+ msgdef_add_field(_self, UPB_LABEL_OPTIONAL, name, type, number, type_class,
1614
+ options, -1, true);
1578
1615
 
1579
1616
  return Qnil;
1580
1617
  }
@@ -1607,7 +1644,7 @@ VALUE MessageBuilderContext_required(int argc, VALUE* argv, VALUE _self) {
1607
1644
  }
1608
1645
 
1609
1646
  msgdef_add_field(_self, UPB_LABEL_REQUIRED, name, type, number, type_class,
1610
- options, -1);
1647
+ options, -1, false);
1611
1648
 
1612
1649
  return Qnil;
1613
1650
  }
@@ -1633,7 +1670,7 @@ VALUE MessageBuilderContext_repeated(int argc, VALUE* argv, VALUE _self) {
1633
1670
  type_class = (argc > 3) ? argv[3] : Qnil;
1634
1671
 
1635
1672
  msgdef_add_field(_self, UPB_LABEL_REPEATED, name, type, number, type_class,
1636
- Qnil, -1);
1673
+ Qnil, -1, false);
1637
1674
 
1638
1675
  return Qnil;
1639
1676
  }
@@ -1758,6 +1795,56 @@ VALUE MessageBuilderContext_oneof(VALUE _self, VALUE name) {
1758
1795
  return Qnil;
1759
1796
  }
1760
1797
 
1798
+ void MessageBuilderContext_add_synthetic_oneofs(VALUE _self) {
1799
+ DEFINE_SELF(MessageBuilderContext, self, _self);
1800
+ FileBuilderContext* file_context =
1801
+ ruby_to_FileBuilderContext(self->file_builder);
1802
+ size_t field_count, oneof_count;
1803
+ google_protobuf_FieldDescriptorProto** fields =
1804
+ google_protobuf_DescriptorProto_mutable_field(self->msg_proto, &field_count);
1805
+ const google_protobuf_OneofDescriptorProto*const* oneofs =
1806
+ google_protobuf_DescriptorProto_oneof_decl(self->msg_proto, &oneof_count);
1807
+ VALUE names = rb_hash_new();
1808
+ VALUE underscore = rb_str_new2("_");
1809
+ size_t i;
1810
+
1811
+ // We have to build a set of all names, to ensure that synthetic oneofs are
1812
+ // not creating conflicts.
1813
+ for (i = 0; i < field_count; i++) {
1814
+ upb_strview name = google_protobuf_FieldDescriptorProto_name(fields[i]);
1815
+ rb_hash_aset(names, rb_str_new(name.data, name.size), Qtrue);
1816
+ }
1817
+ for (i = 0; i < oneof_count; i++) {
1818
+ upb_strview name = google_protobuf_OneofDescriptorProto_name(oneofs[i]);
1819
+ rb_hash_aset(names, rb_str_new(name.data, name.size), Qtrue);
1820
+ }
1821
+
1822
+ for (i = 0; i < field_count; i++) {
1823
+ google_protobuf_OneofDescriptorProto* oneof_proto;
1824
+ VALUE oneof_name;
1825
+ upb_strview field_name;
1826
+
1827
+ if (!google_protobuf_FieldDescriptorProto_proto3_optional(fields[i])) {
1828
+ continue;
1829
+ }
1830
+
1831
+ // Prepend '_' until we are no longer conflicting.
1832
+ field_name = google_protobuf_FieldDescriptorProto_name(fields[i]);
1833
+ oneof_name = rb_str_new(field_name.data, field_name.size);
1834
+ while (rb_hash_lookup(names, oneof_name) != Qnil) {
1835
+ oneof_name = rb_str_plus(underscore, oneof_name);
1836
+ }
1837
+
1838
+ rb_hash_aset(names, oneof_name, Qtrue);
1839
+ google_protobuf_FieldDescriptorProto_set_oneof_index(fields[i],
1840
+ oneof_count++);
1841
+ oneof_proto = google_protobuf_DescriptorProto_add_oneof_decl(
1842
+ self->msg_proto, file_context->arena);
1843
+ google_protobuf_OneofDescriptorProto_set_name(
1844
+ oneof_proto, FileBuilderContext_strdup(self->file_builder, oneof_name));
1845
+ }
1846
+ }
1847
+
1761
1848
  // -----------------------------------------------------------------------------
1762
1849
  // OneofBuilderContext.
1763
1850
  // -----------------------------------------------------------------------------
@@ -1829,7 +1916,7 @@ VALUE OneofBuilderContext_optional(int argc, VALUE* argv, VALUE _self) {
1829
1916
  rb_scan_args(argc, argv, "32", &name, &type, &number, &type_class, &options);
1830
1917
 
1831
1918
  msgdef_add_field(self->message_builder, UPB_LABEL_OPTIONAL, name, type,
1832
- number, type_class, options, self->oneof_index);
1919
+ number, type_class, options, self->oneof_index, false);
1833
1920
 
1834
1921
  return Qnil;
1835
1922
  }
@@ -2033,6 +2120,7 @@ VALUE FileBuilderContext_add_message(VALUE _self, VALUE name) {
2033
2120
  VALUE ctx = rb_class_new_instance(2, args, cMessageBuilderContext);
2034
2121
  VALUE block = rb_block_proc();
2035
2122
  rb_funcall_with_block(ctx, rb_intern("instance_eval"), 0, NULL, block);
2123
+ MessageBuilderContext_add_synthetic_oneofs(ctx);
2036
2124
  return Qnil;
2037
2125
  }
2038
2126
 
@@ -30,6 +30,10 @@
30
30
 
31
31
  #include "protobuf.h"
32
32
 
33
+ VALUE initialize_rb_class_with_no_args(VALUE klass) {
34
+ return rb_funcall(klass, rb_intern("new"), 0);
35
+ }
36
+
33
37
  // This function is equivalent to rb_str_cat(), but unlike the real
34
38
  // rb_str_cat(), it doesn't leak memory in some versions of Ruby.
35
39
  // For more information, see:
@@ -44,6 +48,23 @@ VALUE noleak_rb_str_cat(VALUE rb_str, const char *str, long len) {
44
48
  return rb_str;
45
49
  }
46
50
 
51
+ bool is_wrapper(const upb_msgdef* m) {
52
+ switch (upb_msgdef_wellknowntype(m)) {
53
+ case UPB_WELLKNOWN_DOUBLEVALUE:
54
+ case UPB_WELLKNOWN_FLOATVALUE:
55
+ case UPB_WELLKNOWN_INT64VALUE:
56
+ case UPB_WELLKNOWN_UINT64VALUE:
57
+ case UPB_WELLKNOWN_INT32VALUE:
58
+ case UPB_WELLKNOWN_UINT32VALUE:
59
+ case UPB_WELLKNOWN_STRINGVALUE:
60
+ case UPB_WELLKNOWN_BYTESVALUE:
61
+ case UPB_WELLKNOWN_BOOLVALUE:
62
+ return true;
63
+ default:
64
+ return false;
65
+ }
66
+ }
67
+
47
68
  // The code below also comes from upb's prototype Ruby binding, developed by
48
69
  // haberman@.
49
70
 
@@ -117,19 +138,26 @@ static const void* newhandlerdata(upb_handlers* h, uint32_t ofs, int32_t hasbit)
117
138
  typedef struct {
118
139
  size_t ofs;
119
140
  int32_t hasbit;
141
+ upb_fieldtype_t wrapped_type; // Only for wrappers.
120
142
  VALUE subklass;
121
143
  } submsg_handlerdata_t;
122
144
 
123
145
  // Creates a handlerdata that contains offset and submessage type information.
124
146
  static const void *newsubmsghandlerdata(upb_handlers* h,
147
+ const upb_fielddef *f,
125
148
  uint32_t ofs,
126
149
  int32_t hasbit,
127
150
  VALUE subklass) {
128
151
  submsg_handlerdata_t *hd = ALLOC(submsg_handlerdata_t);
152
+ const upb_msgdef *subm = upb_fielddef_msgsubdef(f);
129
153
  hd->ofs = ofs;
130
154
  hd->hasbit = hasbit;
131
155
  hd->subklass = subklass;
132
156
  upb_handlers_addcleanup(h, hd, xfree);
157
+ if (is_wrapper(subm)) {
158
+ const upb_fielddef *value_f = upb_msgdef_itof(subm, 1);
159
+ hd->wrapped_type = upb_fielddef_type(value_f);
160
+ }
133
161
  return hd;
134
162
  }
135
163
 
@@ -271,7 +299,7 @@ static void *appendsubmsg_handler(void *closure, const void *hd) {
271
299
  const submsg_handlerdata_t *submsgdata = hd;
272
300
  MessageHeader* submsg;
273
301
 
274
- VALUE submsg_rb = rb_class_new_instance(0, NULL, submsgdata->subklass);
302
+ VALUE submsg_rb = initialize_rb_class_with_no_args(submsgdata->subklass);
275
303
  RepeatedField_push(ary, submsg_rb);
276
304
 
277
305
  TypedData_Get_Struct(submsg_rb, MessageHeader, &Message_type, submsg);
@@ -298,7 +326,7 @@ static void *submsg_handler(void *closure, const void *hd) {
298
326
 
299
327
  if (DEREF(msg, submsgdata->ofs, VALUE) == Qnil) {
300
328
  DEREF(msg, submsgdata->ofs, VALUE) =
301
- rb_class_new_instance(0, NULL, submsgdata->subklass);
329
+ initialize_rb_class_with_no_args(submsgdata->subklass);
302
330
  }
303
331
 
304
332
  set_hasbit(closure, submsgdata->hasbit);
@@ -310,12 +338,39 @@ static void *submsg_handler(void *closure, const void *hd) {
310
338
  }
311
339
 
312
340
  static void* startwrapper(void* closure, const void* hd) {
313
- char* msg = closure;
314
341
  const submsg_handlerdata_t* submsgdata = hd;
342
+ char* msg = closure;
343
+ VALUE* field = (VALUE*)(msg + submsgdata->ofs);
315
344
 
316
345
  set_hasbit(closure, submsgdata->hasbit);
317
346
 
318
- return msg + submsgdata->ofs;
347
+ switch (submsgdata->wrapped_type) {
348
+ case UPB_TYPE_FLOAT:
349
+ case UPB_TYPE_DOUBLE:
350
+ *field = DBL2NUM(0);
351
+ break;
352
+ case UPB_TYPE_BOOL:
353
+ *field = Qfalse;
354
+ break;
355
+ case UPB_TYPE_STRING:
356
+ *field = get_frozen_string(NULL, 0, false);
357
+ break;
358
+ case UPB_TYPE_BYTES:
359
+ *field = get_frozen_string(NULL, 0, true);
360
+ break;
361
+ case UPB_TYPE_ENUM:
362
+ case UPB_TYPE_INT32:
363
+ case UPB_TYPE_INT64:
364
+ case UPB_TYPE_UINT32:
365
+ case UPB_TYPE_UINT64:
366
+ *field = INT2NUM(0);
367
+ break;
368
+ case UPB_TYPE_MESSAGE:
369
+ rb_raise(rb_eRuntimeError,
370
+ "Internal logic error with well-known types.");
371
+ }
372
+
373
+ return field;
319
374
  }
320
375
 
321
376
  // Handler data for startmap/endmap handlers.
@@ -379,10 +434,8 @@ static void *startmap_handler(void *closure, const void *hd) {
379
434
  }
380
435
 
381
436
  static bool endmap_handler(void *closure, const void *hd) {
382
- MessageHeader* msg = closure;
383
- const map_handlerdata_t* mapdata = hd;
384
- VALUE map_rb = DEREF(msg, mapdata->ofs, VALUE);
385
- Map_set_frame(map_rb, Qnil);
437
+ map_parse_frame_t* frame = closure;
438
+ Map_set_frame(frame->map, Qnil);
386
439
  return true;
387
440
  }
388
441
 
@@ -498,7 +551,7 @@ static void *oneofsubmsg_handler(void *closure,
498
551
  if (oldcase != oneofdata->oneof_case_num ||
499
552
  DEREF(msg, oneofdata->ofs, VALUE) == Qnil) {
500
553
  DEREF(msg, oneofdata->ofs, VALUE) =
501
- rb_class_new_instance(0, NULL, oneofdata->subklass);
554
+ initialize_rb_class_with_no_args(oneofdata->subklass);
502
555
  }
503
556
  // Set the oneof case *after* allocating the new class instance -- otherwise,
504
557
  // if the Ruby GC is invoked as part of a call into the VM, it might invoke
@@ -522,23 +575,6 @@ static void* oneof_startwrapper(void* closure, const void* hd) {
522
575
  return msg + oneofdata->ofs;
523
576
  }
524
577
 
525
- bool is_wrapper(const upb_msgdef* m) {
526
- switch (upb_msgdef_wellknowntype(m)) {
527
- case UPB_WELLKNOWN_DOUBLEVALUE:
528
- case UPB_WELLKNOWN_FLOATVALUE:
529
- case UPB_WELLKNOWN_INT64VALUE:
530
- case UPB_WELLKNOWN_UINT64VALUE:
531
- case UPB_WELLKNOWN_INT32VALUE:
532
- case UPB_WELLKNOWN_UINT32VALUE:
533
- case UPB_WELLKNOWN_STRINGVALUE:
534
- case UPB_WELLKNOWN_BYTESVALUE:
535
- case UPB_WELLKNOWN_BOOLVALUE:
536
- return true;
537
- default:
538
- return false;
539
- }
540
- }
541
-
542
578
  // Set up handlers for a repeated field.
543
579
  static void add_handlers_for_repeated_field(upb_handlers *h,
544
580
  const Descriptor* desc,
@@ -579,7 +615,7 @@ static void add_handlers_for_repeated_field(upb_handlers *h,
579
615
  case UPB_TYPE_MESSAGE: {
580
616
  VALUE subklass = field_type_class(desc->layout, f);
581
617
  upb_handlerattr attr = UPB_HANDLERATTR_INIT;
582
- attr.handler_data = newsubmsghandlerdata(h, 0, -1, subklass);
618
+ attr.handler_data = newsubmsghandlerdata(h, f, 0, -1, subklass);
583
619
  if (is_wrapper(upb_fielddef_msgsubdef(f))) {
584
620
  upb_handlers_setstartsubmsg(h, f, appendwrapper_handler, &attr);
585
621
  } else {
@@ -708,7 +744,7 @@ static void add_handlers_for_singular_field(const Descriptor* desc,
708
744
  case UPB_TYPE_MESSAGE: {
709
745
  upb_handlerattr attr = UPB_HANDLERATTR_INIT;
710
746
  attr.handler_data = newsubmsghandlerdata(
711
- h, offset, hasbit, field_type_class(desc->layout, f));
747
+ h, f, offset, hasbit, field_type_class(desc->layout, f));
712
748
  if (is_wrapper(upb_fielddef_msgsubdef(f))) {
713
749
  upb_handlers_setstartsubmsg(h, f, startwrapper, &attr);
714
750
  } else {
@@ -897,7 +933,7 @@ void add_handlers_for_message(const void *closure, upb_handlers *h) {
897
933
  !upb_msg_field_done(&i);
898
934
  upb_msg_field_next(&i)) {
899
935
  const upb_fielddef *f = upb_msg_iter_field(&i);
900
- const upb_oneofdef *oneof = upb_fielddef_containingoneof(f);
936
+ const upb_oneofdef* oneof = upb_fielddef_realcontainingoneof(f);
901
937
  size_t offset = get_field_offset(desc->layout, f);
902
938
 
903
939
  if (oneof) {
@@ -1004,7 +1040,7 @@ VALUE Message_decode(VALUE klass, VALUE data) {
1004
1040
  rb_raise(rb_eArgError, "Expected string for binary protobuf data.");
1005
1041
  }
1006
1042
 
1007
- msg_rb = rb_class_new_instance(0, NULL, msgklass);
1043
+ msg_rb = initialize_rb_class_with_no_args(msgklass);
1008
1044
  TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg);
1009
1045
 
1010
1046
  {
@@ -1080,7 +1116,7 @@ VALUE Message_decode_json(int argc, VALUE* argv, VALUE klass) {
1080
1116
  // convert, because string handlers pass data directly to message string
1081
1117
  // fields.
1082
1118
 
1083
- msg_rb = rb_class_new_instance(0, NULL, msgklass);
1119
+ msg_rb = initialize_rb_class_with_no_args(msgklass);
1084
1120
  TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg);
1085
1121
 
1086
1122
  {
@@ -1162,7 +1198,7 @@ static void putsubmsg(VALUE submsg, const upb_fielddef *f, upb_sink sink,
1162
1198
 
1163
1199
  upb_sink_startsubmsg(sink, getsel(f, UPB_HANDLER_STARTSUBMSG), &subsink);
1164
1200
  putmsg(submsg, subdesc, subsink, depth + 1, emit_defaults, is_json, true);
1165
- upb_sink_endsubmsg(sink, getsel(f, UPB_HANDLER_ENDSUBMSG));
1201
+ upb_sink_endsubmsg(sink, subsink, getsel(f, UPB_HANDLER_ENDSUBMSG));
1166
1202
  }
1167
1203
 
1168
1204
  static void putary(VALUE ary, const upb_fielddef* f, upb_sink sink, int depth,
@@ -1307,7 +1343,7 @@ static void putmap(VALUE map, const upb_fielddef* f, upb_sink sink, int depth,
1307
1343
  entry_sink, emit_defaults, is_json);
1308
1344
 
1309
1345
  upb_sink_endmsg(entry_sink, &status);
1310
- upb_sink_endsubmsg(subsink, getsel(f, UPB_HANDLER_ENDSUBMSG));
1346
+ upb_sink_endsubmsg(subsink, entry_sink, getsel(f, UPB_HANDLER_ENDSUBMSG));
1311
1347
  }
1312
1348
 
1313
1349
  upb_sink_endseq(sink, getsel(f, UPB_HANDLER_ENDSEQ));
@@ -1432,6 +1468,7 @@ static void putmsg(VALUE msg_rb, const Descriptor* desc,
1432
1468
  MessageHeader* msg;
1433
1469
  upb_msg_field_iter i;
1434
1470
  upb_status status;
1471
+ bool json_wrapper = is_wrapper(desc->msgdef) && is_json;
1435
1472
 
1436
1473
  if (is_json &&
1437
1474
  upb_msgdef_wellknowntype(desc->msgdef) == UPB_WELLKNOWN_ANY) {
@@ -1469,7 +1506,7 @@ static void putmsg(VALUE msg_rb, const Descriptor* desc,
1469
1506
  !upb_msg_field_done(&i);
1470
1507
  upb_msg_field_next(&i)) {
1471
1508
  upb_fielddef *f = upb_msg_iter_field(&i);
1472
- const upb_oneofdef *oneof = upb_fielddef_containingoneof(f);
1509
+ const upb_oneofdef* oneof = upb_fielddef_realcontainingoneof(f);
1473
1510
  bool is_matching_oneof = false;
1474
1511
  uint32_t offset =
1475
1512
  desc->layout->fields[upb_fielddef_index(f)].offset +
@@ -1508,7 +1545,7 @@ static void putmsg(VALUE msg_rb, const Descriptor* desc,
1508
1545
  is_default = RSTRING_LEN(str) == 0;
1509
1546
  }
1510
1547
 
1511
- if (is_matching_oneof || emit_defaults || !is_default) {
1548
+ if (is_matching_oneof || emit_defaults || !is_default || json_wrapper) {
1512
1549
  putstr(str, f, sink);
1513
1550
  }
1514
1551
  } else if (upb_fielddef_issubmsg(f)) {
@@ -1528,7 +1565,7 @@ static void putmsg(VALUE msg_rb, const Descriptor* desc,
1528
1565
  } else if (upb_msgdef_syntax(desc->msgdef) == UPB_SYNTAX_PROTO3) { \
1529
1566
  is_default = default_value == value; \
1530
1567
  } \
1531
- if (is_matching_oneof || emit_defaults || !is_default) { \
1568
+ if (is_matching_oneof || emit_defaults || !is_default || json_wrapper) { \
1532
1569
  upb_sink_put##upbtype(sink, sel, value); \
1533
1570
  } \
1534
1571
  } break;
@@ -1677,7 +1714,7 @@ static void discard_unknown(VALUE msg_rb, const Descriptor* desc) {
1677
1714
  !upb_msg_field_done(&it);
1678
1715
  upb_msg_field_next(&it)) {
1679
1716
  upb_fielddef *f = upb_msg_iter_field(&it);
1680
- const upb_oneofdef *oneof = upb_fielddef_containingoneof(f);
1717
+ const upb_oneofdef* oneof = upb_fielddef_realcontainingoneof(f);
1681
1718
  uint32_t offset =
1682
1719
  desc->layout->fields[upb_fielddef_index(f)].offset +
1683
1720
  sizeof(MessageHeader);