google-protobuf 3.11.0 → 3.12.0

Sign up to get free protection for your applications and to get access to all the features.

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);